feat: implement Phase 6 — Software Deployment
Backend: - SoftwarePackage model (Name, Version, OsType, PackageManager, PackageName, InstallerUrl, Checksum, SilentArgs) - RmmDbContext: SoftwarePackages DbSet + unique index on (Name, Version, OsType) - SoftwarePackagesController: full CRUD with OsType filter - DeployController: POST /api/v1/deploy creates InstallSoftware/UninstallSoftware TaskItem - EF Migration: AddSoftwarePackages (20260319130448) Go Agent: - internal/deployer/deployer.go: Install() and Uninstall() with: - Chocolatey (Windows), apt/dnf (Linux), auto-detect - Direct installer fallback: HTTP download + SHA256 verify + silent install - Supports .msi, .exe (Windows) and .deb, .rpm (Linux) - main.go: COMMAND_TYPE_INSTALL_SOFTWARE and COMMAND_TYPE_UNINSTALL_SOFTWARE routed to deployer Frontend: - SoftwarePage: Katalog tab (CRUD, OS filter, smart package manager select) + Deploy tab - api/types.ts: SoftwarePackage, PackageManager, DeployRequest/Response types - api/client.ts: softwarePackagesApi and deployApi - App.tsx: Software nav item with Package icon Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
63
Backend/src/NexusRMM.Api/Controllers/DeployController.cs
Normal file
63
Backend/src/NexusRMM.Api/Controllers/DeployController.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NexusRMM.Core.Models;
|
||||
using NexusRMM.Infrastructure.Data;
|
||||
|
||||
namespace NexusRMM.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/v1/deploy")]
|
||||
public class DeployController : ControllerBase
|
||||
{
|
||||
private readonly RmmDbContext _db;
|
||||
public DeployController(RmmDbContext db) => _db = db;
|
||||
|
||||
/// <summary>
|
||||
/// Startet Software-Deployment auf einem Agent.
|
||||
/// Erstellt einen TaskItem mit Typ InstallSoftware/UninstallSoftware.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Deploy([FromBody] DeployRequest req)
|
||||
{
|
||||
var agent = await _db.Agents.FindAsync(req.AgentId);
|
||||
if (agent is null) return NotFound(new { error = "Agent nicht gefunden" });
|
||||
|
||||
var pkg = await _db.SoftwarePackages.FindAsync(req.PackageId);
|
||||
if (pkg is null) return NotFound(new { error = "Paket nicht gefunden" });
|
||||
|
||||
var payload = new
|
||||
{
|
||||
packageName = pkg.PackageName,
|
||||
packageManager = pkg.PackageManager,
|
||||
installerUrl = pkg.InstallerUrl ?? "",
|
||||
checksum = pkg.Checksum ?? "",
|
||||
silentArgs = pkg.SilentArgs ?? "",
|
||||
displayName = pkg.Name,
|
||||
version = pkg.Version,
|
||||
};
|
||||
|
||||
var task = new TaskItem
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
AgentId = req.AgentId,
|
||||
Type = req.Action == "uninstall" ? TaskType.UninstallSoftware : TaskType.InstallSoftware,
|
||||
Payload = JsonSerializer.SerializeToElement(payload),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
_db.Tasks.Add(task);
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return CreatedAtAction(nameof(Deploy), new { id = task.Id }, new
|
||||
{
|
||||
task.Id,
|
||||
task.AgentId,
|
||||
task.Type,
|
||||
task.Status,
|
||||
PackageName = pkg.Name,
|
||||
Version = pkg.Version,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record DeployRequest(Guid AgentId, int PackageId, string Action); // Action: "install" | "uninstall"
|
||||
@@ -0,0 +1,85 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NexusRMM.Core.Models;
|
||||
using NexusRMM.Infrastructure.Data;
|
||||
|
||||
namespace NexusRMM.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/v1/software-packages")]
|
||||
public class SoftwarePackagesController : ControllerBase
|
||||
{
|
||||
private readonly RmmDbContext _db;
|
||||
public SoftwarePackagesController(RmmDbContext db) => _db = db;
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAll([FromQuery] OsType? osType = null)
|
||||
{
|
||||
var q = _db.SoftwarePackages.AsQueryable();
|
||||
if (osType.HasValue) q = q.Where(p => p.OsType == osType.Value);
|
||||
return Ok(await q.OrderBy(p => p.Name).ToListAsync());
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
public async Task<IActionResult> GetById(int id)
|
||||
{
|
||||
var pkg = await _db.SoftwarePackages.FindAsync(id);
|
||||
return pkg is null ? NotFound() : Ok(pkg);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] CreateSoftwarePackageRequest req)
|
||||
{
|
||||
var pkg = new SoftwarePackage
|
||||
{
|
||||
Name = req.Name,
|
||||
Version = req.Version,
|
||||
OsType = req.OsType,
|
||||
PackageManager = req.PackageManager,
|
||||
PackageName = req.PackageName,
|
||||
InstallerUrl = req.InstallerUrl,
|
||||
Checksum = req.Checksum,
|
||||
SilentArgs = req.SilentArgs,
|
||||
};
|
||||
_db.SoftwarePackages.Add(pkg);
|
||||
await _db.SaveChangesAsync();
|
||||
return CreatedAtAction(nameof(GetById), new { id = pkg.Id }, pkg);
|
||||
}
|
||||
|
||||
[HttpPut("{id:int}")]
|
||||
public async Task<IActionResult> Update(int id, [FromBody] CreateSoftwarePackageRequest req)
|
||||
{
|
||||
var pkg = await _db.SoftwarePackages.FindAsync(id);
|
||||
if (pkg is null) return NotFound();
|
||||
pkg.Name = req.Name;
|
||||
pkg.Version = req.Version;
|
||||
pkg.OsType = req.OsType;
|
||||
pkg.PackageManager = req.PackageManager;
|
||||
pkg.PackageName = req.PackageName;
|
||||
pkg.InstallerUrl = req.InstallerUrl;
|
||||
pkg.Checksum = req.Checksum;
|
||||
pkg.SilentArgs = req.SilentArgs;
|
||||
await _db.SaveChangesAsync();
|
||||
return Ok(pkg);
|
||||
}
|
||||
|
||||
[HttpDelete("{id:int}")]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
var pkg = await _db.SoftwarePackages.FindAsync(id);
|
||||
if (pkg is null) return NotFound();
|
||||
_db.SoftwarePackages.Remove(pkg);
|
||||
await _db.SaveChangesAsync();
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
public record CreateSoftwarePackageRequest(
|
||||
string Name,
|
||||
string Version,
|
||||
OsType OsType,
|
||||
string PackageManager,
|
||||
string PackageName,
|
||||
string? InstallerUrl,
|
||||
string? Checksum,
|
||||
string? SilentArgs);
|
||||
26
Backend/src/NexusRMM.Core/Models/SoftwarePackage.cs
Normal file
26
Backend/src/NexusRMM.Core/Models/SoftwarePackage.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace NexusRMM.Core.Models;
|
||||
|
||||
public class SoftwarePackage
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Version { get; set; } = string.Empty;
|
||||
public OsType OsType { get; set; }
|
||||
|
||||
/// <summary>Paketmanager: "choco", "apt", "dnf", "direct"</summary>
|
||||
public string PackageManager { get; set; } = "choco";
|
||||
|
||||
/// <summary>Paketname für den Paketmanager (z.B. "7zip" für choco)</summary>
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Optionale direkte Download-URL (für Fallback)</summary>
|
||||
public string? InstallerUrl { get; set; }
|
||||
|
||||
/// <summary>SHA256-Prüfsumme der Installer-Datei</summary>
|
||||
public string? Checksum { get; set; }
|
||||
|
||||
/// <summary>Silent-Install-Parameter für direkten Installer</summary>
|
||||
public string? SilentArgs { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public class RmmDbContext : DbContext
|
||||
public DbSet<Ticket> Tickets => Set<Ticket>();
|
||||
public DbSet<AlertRule> AlertRules => Set<AlertRule>();
|
||||
public DbSet<Alert> Alerts => Set<Alert>();
|
||||
public DbSet<SoftwarePackage> SoftwarePackages => Set<SoftwarePackage>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -58,5 +59,11 @@ public class RmmDbContext : DbContext
|
||||
e.HasOne(a => a.Rule).WithMany(r => r.Alerts).HasForeignKey(a => a.RuleId);
|
||||
e.HasOne(a => a.Agent).WithMany(a => a.Alerts).HasForeignKey(a => a.AgentId);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<SoftwarePackage>(e =>
|
||||
{
|
||||
e.HasKey(p => p.Id);
|
||||
e.HasIndex(p => new { p.Name, p.Version, p.OsType }).IsUnique();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
368
Backend/src/NexusRMM.Infrastructure/Migrations/20260319130448_AddSoftwarePackages.Designer.cs
generated
Normal file
368
Backend/src/NexusRMM.Infrastructure/Migrations/20260319130448_AddSoftwarePackages.Designer.cs
generated
Normal file
@@ -0,0 +1,368 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using NexusRMM.Infrastructure.Data;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NexusRMM.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(RmmDbContext))]
|
||||
[Migration("20260319130448_AddSoftwarePackages")]
|
||||
partial class AddSoftwarePackages
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.5")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Agent", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AgentVersion")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("EnrolledAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Hostname")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("IpAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("LastSeen")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("MacAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("MeshAgentId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("OsType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("OsVersion")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.PrimitiveCollection<string>("Tags")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Hostname");
|
||||
|
||||
b.HasIndex("MacAddress");
|
||||
|
||||
b.ToTable("Agents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.AgentMetric", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<Guid>("AgentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonElement>("Metrics")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<DateTime>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AgentId");
|
||||
|
||||
b.HasIndex("Timestamp");
|
||||
|
||||
b.ToTable("AgentMetrics");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Alert", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<bool>("Acknowledged")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("AgentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("RuleId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Severity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AgentId");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("RuleId");
|
||||
|
||||
b.ToTable("Alerts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.AlertRule", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("MetricPath")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Operator")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Severity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<double>("Threshold")
|
||||
.HasColumnType("double precision");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AlertRules");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.SoftwarePackage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Checksum")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("InstallerUrl")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("OsType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("PackageManager")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PackageName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SilentArgs")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Version")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name", "Version", "OsType")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SoftwarePackages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.TaskItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AgentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("CompletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<JsonElement?>("Payload")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<JsonElement?>("Result")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AgentId");
|
||||
|
||||
b.ToTable("Tasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Ticket", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid?>("AgentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AgentId");
|
||||
|
||||
b.ToTable("Tickets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.AgentMetric", b =>
|
||||
{
|
||||
b.HasOne("NexusRMM.Core.Models.Agent", "Agent")
|
||||
.WithMany("Metrics")
|
||||
.HasForeignKey("AgentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Agent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Alert", b =>
|
||||
{
|
||||
b.HasOne("NexusRMM.Core.Models.Agent", "Agent")
|
||||
.WithMany("Alerts")
|
||||
.HasForeignKey("AgentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("NexusRMM.Core.Models.AlertRule", "Rule")
|
||||
.WithMany("Alerts")
|
||||
.HasForeignKey("RuleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Agent");
|
||||
|
||||
b.Navigation("Rule");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.TaskItem", b =>
|
||||
{
|
||||
b.HasOne("NexusRMM.Core.Models.Agent", "Agent")
|
||||
.WithMany("Tasks")
|
||||
.HasForeignKey("AgentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Agent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Ticket", b =>
|
||||
{
|
||||
b.HasOne("NexusRMM.Core.Models.Agent", "Agent")
|
||||
.WithMany("Tickets")
|
||||
.HasForeignKey("AgentId");
|
||||
|
||||
b.Navigation("Agent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.Agent", b =>
|
||||
{
|
||||
b.Navigation("Alerts");
|
||||
|
||||
b.Navigation("Metrics");
|
||||
|
||||
b.Navigation("Tasks");
|
||||
|
||||
b.Navigation("Tickets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.AlertRule", b =>
|
||||
{
|
||||
b.Navigation("Alerts");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NexusRMM.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddSoftwarePackages : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SoftwarePackages",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
Version = table.Column<string>(type: "text", nullable: false),
|
||||
OsType = table.Column<int>(type: "integer", nullable: false),
|
||||
PackageManager = table.Column<string>(type: "text", nullable: false),
|
||||
PackageName = table.Column<string>(type: "text", nullable: false),
|
||||
InstallerUrl = table.Column<string>(type: "text", nullable: true),
|
||||
Checksum = table.Column<string>(type: "text", nullable: true),
|
||||
SilentArgs = table.Column<string>(type: "text", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SoftwarePackages", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SoftwarePackages_Name_Version_OsType",
|
||||
table: "SoftwarePackages",
|
||||
columns: new[] { "Name", "Version", "OsType" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "SoftwarePackages");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,53 @@ namespace NexusRMM.Infrastructure.Migrations
|
||||
b.ToTable("AlertRules");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.SoftwarePackage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Checksum")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("InstallerUrl")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("OsType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("PackageManager")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PackageName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SilentArgs")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Version")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name", "Version", "OsType")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SoftwarePackages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NexusRMM.Core.Models.TaskItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
||||
Reference in New Issue
Block a user