Refactor code structure for improved readability and maintainability
This commit is contained in:
+110
-29
@@ -11,25 +11,25 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<EventModel> Events { get; set; }
|
||||
|
||||
public DbSet<EnvironmentModel> Environments { get; set; }
|
||||
public DbSet<EnvironmentDomainsModel> EnvironmentDomains { get; set; }
|
||||
public DbSet<DomainModel> Domains { get; set; }
|
||||
public DbSet<VirtualMachineModel> VirtualMachines { get; set; }
|
||||
public DbSet<TargetModel> Targets { get; set; }
|
||||
public DbSet<DeploymentModel> Deployments { get; set; }
|
||||
public DbSet<DeploymentGroupModel> DeploymentGroups { get; set; }
|
||||
public DbSet<TemplateModel> Templates { get; set; }
|
||||
public DbSet<TemplateVersionModel> TemplateVersions { get; set; }
|
||||
public DbSet<DeploymentRuleModel> DeploymentRules { get; set; }
|
||||
public DbSet<DeploymentRuleStepModel> DeploymentRuleSteps { get; set; }
|
||||
public DbSet<DeploymentTemplateSelectionModel> DeploymentTemplateSelections { get; set; }
|
||||
public DbSet<DeploymentParameterValueModel> DeploymentParameterValues { get; set; }
|
||||
public DbSet<DeploymentTargetAssignmentModel> DeploymentTargetAssignments { get; set; }
|
||||
public DbSet<TemplateCategoryModel> TemplateCategories { get; set; }
|
||||
public DbSet<ServiceModel> Services { get; set; }
|
||||
public DbSet<ServiceRoleDefinitionModel> ServiceRoleDefinitions { get; set; }
|
||||
public DbSet<TemplateOptionModel> TemplateOptions { get; set; }
|
||||
public DbSet<OptionModel> Options { get; set; }
|
||||
public DbSet<OptionCategoryModel> OptionCategories { get; set; }
|
||||
public DbSet<JobModel> Jobs { get; set; }
|
||||
public DbSet<RunbookModel> Runbooks { get; set; }
|
||||
public DbSet<QueueJobModel> QueueJobs { get; set; }
|
||||
public DbSet<QueueJobTargetModel> QueueJobTargets { get; set; }
|
||||
public DbSet<QueueJobStepModel> QueueJobSteps { get; set; }
|
||||
@@ -77,6 +77,14 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
modelBuilder.Entity<DeploymentGroupModel>()
|
||||
.ToTable("DeploymentBatches");
|
||||
|
||||
modelBuilder.Entity<TargetModel>()
|
||||
.Property(target => target.TargetType)
|
||||
.HasMaxLength(64);
|
||||
|
||||
modelBuilder.Entity<TargetModel>()
|
||||
.Property(target => target.ProviderType)
|
||||
.HasMaxLength(64);
|
||||
|
||||
modelBuilder.Entity<DeploymentModel>()
|
||||
.ToTable("DeploymentExecutions");
|
||||
modelBuilder.Entity<DeploymentModel>()
|
||||
@@ -105,12 +113,12 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
.HasColumnName("DependsOnDeploymentJobStepId");
|
||||
|
||||
modelBuilder.Entity<DeploymentModel>()
|
||||
.HasKey(d => new { d.VirtualMachineId, d.DeploymentGroupId });
|
||||
.HasKey(d => new { d.TargetId, d.DeploymentGroupId });
|
||||
|
||||
modelBuilder.Entity<DeploymentModel>()
|
||||
.HasOne(d => d.VirtualMachine)
|
||||
.HasOne(d => d.Target)
|
||||
.WithMany(vm => vm.Deployments)
|
||||
.HasForeignKey(d => d.VirtualMachineId);
|
||||
.HasForeignKey(d => d.TargetId);
|
||||
|
||||
modelBuilder.Entity<DeploymentModel>()
|
||||
.HasOne(d => d.DeploymentGroup)
|
||||
@@ -122,11 +130,103 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
.WithMany(t => t.DeploymentGroups)
|
||||
.HasForeignKey(dg => dg.TemplateId);
|
||||
|
||||
modelBuilder.Entity<DeploymentGroupModel>()
|
||||
.HasOne(dg => dg.DeploymentRule)
|
||||
.WithMany()
|
||||
.HasForeignKey(dg => dg.DeploymentRuleId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<DeploymentTemplateSelectionModel>()
|
||||
.HasOne(selection => selection.DeploymentGroup)
|
||||
.WithMany(batch => batch.TemplateSelections)
|
||||
.HasForeignKey(selection => selection.DeploymentGroupId);
|
||||
|
||||
modelBuilder.Entity<DeploymentTemplateSelectionModel>()
|
||||
.HasOne(selection => selection.TemplateVersion)
|
||||
.WithMany()
|
||||
.HasForeignKey(selection => selection.TemplateVersionId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<DeploymentTemplateSelectionModel>()
|
||||
.HasIndex(selection => new { selection.DeploymentGroupId, selection.SortOrder })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>()
|
||||
.HasOne(parameterValue => parameterValue.DeploymentGroup)
|
||||
.WithMany(batch => batch.ParameterValues)
|
||||
.HasForeignKey(parameterValue => parameterValue.DeploymentGroupId);
|
||||
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>()
|
||||
.HasOne(parameterValue => parameterValue.DeploymentTemplateSelection)
|
||||
.WithMany()
|
||||
.HasForeignKey(parameterValue => parameterValue.DeploymentTemplateSelectionId)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>()
|
||||
.HasIndex(parameterValue => new { parameterValue.DeploymentGroupId, parameterValue.DeploymentTemplateSelectionId, parameterValue.Name })
|
||||
.IsUnique()
|
||||
.HasFilter("[DeploymentTemplateSelectionId] IS NOT NULL");
|
||||
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>()
|
||||
.HasIndex(parameterValue => new { parameterValue.DeploymentGroupId, parameterValue.Name })
|
||||
.IsUnique()
|
||||
.HasFilter("[DeploymentTemplateSelectionId] IS NULL");
|
||||
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>()
|
||||
.ToTable(table => table.HasCheckConstraint("CK_DeploymentParameterValues_ValueJson_IsJson", "ISJSON([ValueJson]) = 1"));
|
||||
|
||||
modelBuilder.Entity<DeploymentTargetAssignmentModel>()
|
||||
.HasOne(target => target.DeploymentGroup)
|
||||
.WithMany(batch => batch.TargetAssignments)
|
||||
.HasForeignKey(target => target.DeploymentGroupId);
|
||||
|
||||
modelBuilder.Entity<DeploymentTargetAssignmentModel>()
|
||||
.HasOne(target => target.Target)
|
||||
.WithMany()
|
||||
.HasForeignKey(target => target.TargetId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<DeploymentTargetAssignmentModel>()
|
||||
.HasIndex(target => new { target.DeploymentGroupId, target.TargetId, target.RoleKey })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<DeploymentTargetAssignmentModel>()
|
||||
.ToTable(table => table.HasCheckConstraint("CK_DeploymentTargetAssignments_NodeDataJson_IsJson", "ISJSON([NodeDataJson]) = 1"));
|
||||
|
||||
modelBuilder.Entity<TemplateModel>()
|
||||
.HasOne(template => template.DeploymentRule)
|
||||
.WithMany()
|
||||
.HasForeignKey(template => template.DeploymentRuleId);
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.HasOne(version => version.Template)
|
||||
.WithMany(template => template.TemplateVersions)
|
||||
.HasForeignKey(version => version.TemplateId);
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.HasIndex(version => new { version.TemplateId, version.Version })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.HasIndex(version => version.TemplateId)
|
||||
.IsUnique()
|
||||
.HasFilter("[IsPublished] = 1");
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.Property(version => version.Version)
|
||||
.HasMaxLength(64);
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.Property(version => version.JsonHash)
|
||||
.HasMaxLength(64);
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.Property(version => version.SchemaVersion)
|
||||
.HasMaxLength(32);
|
||||
|
||||
modelBuilder.Entity<TemplateVersionModel>()
|
||||
.ToTable(table => table.HasCheckConstraint("CK_TemplateVersions_JsonData_IsJson", "ISJSON([JsonData]) = 1"));
|
||||
|
||||
modelBuilder.Entity<DeploymentRuleStepModel>()
|
||||
.HasOne(step => step.DeploymentRule)
|
||||
.WithMany(rule => rule.Steps)
|
||||
@@ -148,28 +248,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
.HasForeignKey(step => step.DependsOnQueueJobStepId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<JobModel>()
|
||||
.HasKey(j => new { j.RunbookId, j.DeploymentId });
|
||||
|
||||
modelBuilder.Entity<JobModel>()
|
||||
.HasOne(j => j.Deployment)
|
||||
.WithMany(d => d.Jobs)
|
||||
.HasPrincipalKey(d => d.Id)
|
||||
.HasForeignKey(j => j.DeploymentId);
|
||||
|
||||
modelBuilder.Entity<JobModel>()
|
||||
.HasOne(j => j.Runbook)
|
||||
.WithMany(r => r.Jobs)
|
||||
.HasPrincipalKey(r => r.Id)
|
||||
.HasForeignKey(j => j.RunbookId);
|
||||
|
||||
modelBuilder.Entity<EventModel>()
|
||||
.HasOne(e => e.Runbook)
|
||||
.WithMany(r => r.Events)
|
||||
.HasPrincipalKey(e => e.Id)
|
||||
.HasForeignKey(r => r.RunbookId);
|
||||
|
||||
OnModelCreatingAddDefaultSqlValues(modelBuilder);
|
||||
DemoData.Seed(modelBuilder);
|
||||
}
|
||||
|
||||
private void OnModelCreatingAddDefaultSqlValues(ModelBuilder modelBuilder)
|
||||
@@ -206,3 +286,4 @@ namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
{
|
||||
public class DataContextFactory : IDesignTimeDbContextFactory<DataContext>
|
||||
{
|
||||
public DataContext CreateDbContext(string[] args)
|
||||
{
|
||||
var basePath = ResolveBasePath();
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(basePath)
|
||||
.AddJsonFile("appsettings.json", optional: false)
|
||||
.AddJsonFile("appsettings.Development.json", optional: true)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var connectionString = configuration.GetConnectionString("Context")
|
||||
?? throw new InvalidOperationException("Connection string 'Context' not found.");
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<DataContext>();
|
||||
optionsBuilder.UseSqlServer(connectionString);
|
||||
|
||||
return new DataContext(optionsBuilder.Options);
|
||||
}
|
||||
|
||||
private static string ResolveBasePath()
|
||||
{
|
||||
var currentDirectory = Directory.GetCurrentDirectory();
|
||||
var projectDirectory = Path.Combine(
|
||||
currentDirectory,
|
||||
".Net",
|
||||
"Microsoft.SelfService.Portal.Core.API");
|
||||
|
||||
if (File.Exists(Path.Combine(currentDirectory, "appsettings.json")))
|
||||
{
|
||||
return currentDirectory;
|
||||
}
|
||||
|
||||
if (File.Exists(Path.Combine(projectDirectory, "appsettings.json")))
|
||||
{
|
||||
return projectDirectory;
|
||||
}
|
||||
|
||||
var assemblyDirectory = AppContext.BaseDirectory;
|
||||
if (File.Exists(Path.Combine(assemblyDirectory, "appsettings.json")))
|
||||
{
|
||||
return assemblyDirectory;
|
||||
}
|
||||
|
||||
return currentDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.SelfService.Portal.Core.API.Models;
|
||||
|
||||
namespace Microsoft.SelfService.Portal.Core.API.Context
|
||||
{
|
||||
internal static class DemoData
|
||||
{
|
||||
private static readonly DateTime Timestamp = new(2026, 7, 7, 0, 0, 0, DateTimeKind.Utc);
|
||||
private const string Owner = "DemoSeed";
|
||||
|
||||
internal static readonly Guid EnvironmentContosoTestId = Guid.Parse("10000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid EnvironmentContosoProdId = Guid.Parse("10000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid EnvironmentM365Id = Guid.Parse("10000000-0000-0000-0000-000000000003");
|
||||
|
||||
internal static readonly Guid DomainCentralId = Guid.Parse("20000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DomainResourceId = Guid.Parse("20000000-0000-0000-0000-000000000002");
|
||||
|
||||
internal static readonly Guid VmDc01Id = Guid.Parse("30000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid VmDc02Id = Guid.Parse("30000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid VmSql01Id = Guid.Parse("30000000-0000-0000-0000-000000000003");
|
||||
internal static readonly Guid VmSp01Id = Guid.Parse("30000000-0000-0000-0000-000000000004");
|
||||
internal static readonly Guid VmSp02Id = Guid.Parse("30000000-0000-0000-0000-000000000005");
|
||||
internal static readonly Guid TargetM365TenantId = Guid.Parse("30000000-0000-0000-0000-000000000006");
|
||||
internal static readonly Guid TargetTeamsPolicyScopeId = Guid.Parse("30000000-0000-0000-0000-000000000007");
|
||||
|
||||
internal static readonly Guid ServiceActiveDirectoryId = Guid.Parse("40000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid ServiceSqlServerId = Guid.Parse("40000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid ServiceSharePointId = Guid.Parse("40000000-0000-0000-0000-000000000003");
|
||||
internal static readonly Guid ServiceTeamsId = Guid.Parse("40000000-0000-0000-0000-000000000004");
|
||||
|
||||
internal static readonly Guid CategoryActiveDirectoryId = Guid.Parse("50000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid CategorySqlServerId = Guid.Parse("50000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid CategorySharePointId = Guid.Parse("50000000-0000-0000-0000-000000000003");
|
||||
internal static readonly Guid CategoryTeamsId = Guid.Parse("50000000-0000-0000-0000-000000000004");
|
||||
|
||||
internal static readonly Guid RuleStandardId = Guid.Parse("60000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid RuleStepValidateId = Guid.Parse("60000000-0000-0000-0000-000000000101");
|
||||
internal static readonly Guid RuleStepApproveId = Guid.Parse("60000000-0000-0000-0000-000000000102");
|
||||
internal static readonly Guid RuleStepDeployId = Guid.Parse("60000000-0000-0000-0000-000000000103");
|
||||
|
||||
internal static readonly Guid TemplateActiveDirectoryId = Guid.Parse("70000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid TemplateSqlServerId = Guid.Parse("70000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid TemplateSharePointId = Guid.Parse("70000000-0000-0000-0000-000000000003");
|
||||
internal static readonly Guid TemplateTeamsId = Guid.Parse("70000000-0000-0000-0000-000000000004");
|
||||
|
||||
internal static readonly Guid TemplateActiveDirectoryVersionId = Guid.Parse("71000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid TemplateSqlServerVersionId = Guid.Parse("71000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid TemplateSharePointVersionId = Guid.Parse("71000000-0000-0000-0000-000000000003");
|
||||
internal static readonly Guid TemplateTeamsVersionId = Guid.Parse("71000000-0000-0000-0000-000000000004");
|
||||
|
||||
internal static readonly Guid DeploymentBatchSharePointId = Guid.Parse("80000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DeploymentSp01Id = Guid.Parse("81000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DeploymentSp02Id = Guid.Parse("81000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid DeploymentSharePointTemplateSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DeploymentParameterDatabasePrefixId = Guid.Parse("83000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DeploymentParameterFarmAccountId = Guid.Parse("83000000-0000-0000-0000-000000000002");
|
||||
internal static readonly Guid DeploymentTargetSp01Id = Guid.Parse("84000000-0000-0000-0000-000000000001");
|
||||
internal static readonly Guid DeploymentTargetSp02Id = Guid.Parse("84000000-0000-0000-0000-000000000002");
|
||||
|
||||
internal static void Seed(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<EnvironmentModel>().HasData(Environments());
|
||||
modelBuilder.Entity<DomainModel>().HasData(Domains());
|
||||
modelBuilder.Entity<EnvironmentDomainsModel>().HasData(EnvironmentDomains());
|
||||
modelBuilder.Entity<TargetModel>().HasData(Targets());
|
||||
modelBuilder.Entity<ServiceModel>().HasData(Services());
|
||||
modelBuilder.Entity<ServiceRoleDefinitionModel>().HasData(ServiceRoleDefinitions());
|
||||
modelBuilder.Entity<TemplateCategoryModel>().HasData(TemplateCategories());
|
||||
modelBuilder.Entity<DeploymentRuleModel>().HasData(DeploymentRules());
|
||||
modelBuilder.Entity<DeploymentRuleStepModel>().HasData(DeploymentRuleSteps());
|
||||
modelBuilder.Entity<TemplateModel>().HasData(Templates());
|
||||
modelBuilder.Entity<TemplateVersionModel>().HasData(TemplateVersions());
|
||||
modelBuilder.Entity<DeploymentGroupModel>().HasData(DeploymentBatches());
|
||||
modelBuilder.Entity<DeploymentModel>().HasData(Deployments());
|
||||
modelBuilder.Entity<DeploymentTemplateSelectionModel>().HasData(DeploymentTemplateSelections());
|
||||
modelBuilder.Entity<DeploymentParameterValueModel>().HasData(DeploymentParameterValues());
|
||||
modelBuilder.Entity<DeploymentTargetAssignmentModel>().HasData(DeploymentTargetAssignments());
|
||||
}
|
||||
|
||||
private static object[] Environments() =>
|
||||
[
|
||||
Base(new EnvironmentModel { Id = EnvironmentContosoTestId, Name = "Contoso Test", EnvironmentType = EnvironmentStages.Test, HostingType = EnvironmentHostingTypes.OnPrem, MetadataJson = "{\"location\":\"Datacenter A\"}" }),
|
||||
Base(new EnvironmentModel { Id = EnvironmentContosoProdId, Name = "Contoso Production", EnvironmentType = EnvironmentStages.Production, HostingType = EnvironmentHostingTypes.OnPrem, MetadataJson = "{\"location\":\"Datacenter A\"}" }),
|
||||
Base(new EnvironmentModel { Id = EnvironmentM365Id, Name = "Contoso M365", EnvironmentType = EnvironmentStages.Production, HostingType = EnvironmentHostingTypes.M365Tenant, ProviderType = "Microsoft365", TenantId = "11111111-1111-1111-1111-111111111111", MetadataJson = "{\"tenant\":\"contoso.onmicrosoft.com\"}" })
|
||||
];
|
||||
|
||||
private static object[] Domains() =>
|
||||
[
|
||||
Base(new DomainModel { Id = DomainCentralId, Name = "Central Management", FQDN = "corp.contoso.com", NetBIOS = "CONTOSO" }),
|
||||
Base(new DomainModel { Id = DomainResourceId, Name = "Resource Domain", FQDN = "resource.contoso.com", NetBIOS = "RESOURCE" })
|
||||
];
|
||||
|
||||
private static object[] EnvironmentDomains() =>
|
||||
[
|
||||
Junction(new EnvironmentDomainsModel { EnvironmentId = EnvironmentContosoTestId, DomainId = DomainCentralId }),
|
||||
Junction(new EnvironmentDomainsModel { EnvironmentId = EnvironmentContosoProdId, DomainId = DomainCentralId }),
|
||||
Junction(new EnvironmentDomainsModel { EnvironmentId = EnvironmentContosoProdId, DomainId = DomainResourceId })
|
||||
];
|
||||
|
||||
private static object[] Targets() =>
|
||||
[
|
||||
Base(new TargetModel { Id = VmDc01Id, DomainID = DomainCentralId, Name = "CT-DC-01", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Test\"}" }),
|
||||
Base(new TargetModel { Id = VmDc02Id, DomainID = DomainCentralId, Name = "CT-DC-02", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Production\"}" }),
|
||||
Base(new TargetModel { Id = VmSql01Id, DomainID = DomainCentralId, Name = "CT-SQL-01", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SqlServer\",\"environment\":\"Test\"}" }),
|
||||
Base(new TargetModel { Id = VmSp01Id, DomainID = DomainCentralId, Name = "CT-SHP-01", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}" }),
|
||||
Base(new TargetModel { Id = VmSp02Id, DomainID = DomainCentralId, Name = "CT-SHP-02", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}" }),
|
||||
Base(new TargetModel { Id = TargetM365TenantId, Name = "contoso.onmicrosoft.com", TargetType = "Tenant", ProviderType = "Microsoft365", ExternalId = "11111111-1111-1111-1111-111111111111", MetadataJson = "{\"environment\":\"Production\",\"workload\":\"M365\"}" }),
|
||||
Base(new TargetModel { Id = TargetTeamsPolicyScopeId, Name = "Teams - Standard Users", TargetType = "PolicyScope", ProviderType = "Microsoft365", ExternalId = "Teams.StandardUsers", MetadataJson = "{\"workload\":\"Teams\",\"scope\":\"StandardUsers\"}" })
|
||||
];
|
||||
|
||||
private static object[] Services() =>
|
||||
[
|
||||
Base(new ServiceModel { Id = ServiceActiveDirectoryId, Name = "Active Directory", Description = "On-premises directory and identity service.", IconKey = "network", IsCloudService = false }),
|
||||
Base(new ServiceModel { Id = ServiceSqlServerId, Name = "SQL Server", Description = "Database platform for application workloads.", IconKey = "database", IsCloudService = false }),
|
||||
Base(new ServiceModel { Id = ServiceSharePointId, Name = "SharePoint Server", Description = "Collaboration platform for on-premises workloads.", IconKey = "sharepoint", IsCloudService = false }),
|
||||
Base(new ServiceModel { Id = ServiceTeamsId, Name = "Microsoft Teams", Description = "Cloud collaboration workload in Microsoft 365.", IconKey = "messages-square", IsCloudService = true })
|
||||
];
|
||||
|
||||
private static object[] ServiceRoleDefinitions() =>
|
||||
[
|
||||
Base(new ServiceRoleDefinitionModel { Id = Guid.Parse("41000000-0000-0000-0000-000000000001"), ServiceId = ServiceSharePointId, Key = "Farm", Name = "Farm", Description = "SharePoint farm role." }),
|
||||
Base(new ServiceRoleDefinitionModel { Id = Guid.Parse("41000000-0000-0000-0000-000000000002"), ServiceId = ServiceSharePointId, Key = "WebFrontEnd", Name = "Web Front End", Description = "SharePoint web front-end role." }),
|
||||
Base(new ServiceRoleDefinitionModel { Id = Guid.Parse("41000000-0000-0000-0000-000000000003"), ServiceId = ServiceSharePointId, Key = "Application", Name = "Application", Description = "SharePoint service application role." }),
|
||||
Base(new ServiceRoleDefinitionModel { Id = Guid.Parse("41000000-0000-0000-0000-000000000004"), ServiceId = ServiceSqlServerId, Key = "Database", Name = "Database", Description = "SQL Server database role." })
|
||||
];
|
||||
|
||||
private static object[] TemplateCategories() =>
|
||||
[
|
||||
Base(new TemplateCategoryModel { Id = CategoryActiveDirectoryId, ServiceId = ServiceActiveDirectoryId, Name = "Domain Services", Description = "Templates for domain controller and domain configuration.", Color = "#2563EB", IsActive = true }),
|
||||
Base(new TemplateCategoryModel { Id = CategorySqlServerId, ServiceId = ServiceSqlServerId, Name = "Database Platform", Description = "Templates for SQL Server workloads.", Color = "#16A34A", IsActive = true }),
|
||||
Base(new TemplateCategoryModel { Id = CategorySharePointId, ServiceId = ServiceSharePointId, Name = "Collaboration Farm", Description = "Templates for SharePoint Server farms.", Color = "#0F766E", IsActive = true }),
|
||||
Base(new TemplateCategoryModel { Id = CategoryTeamsId, ServiceId = ServiceTeamsId, Name = "Teams Policies", Description = "Templates for Teams policy configuration.", Color = "#7C3AED", IsActive = true })
|
||||
];
|
||||
|
||||
private static object[] DeploymentRules() =>
|
||||
[
|
||||
Base(new DeploymentRuleModel { Id = RuleStandardId, Name = "Standard Provisioning", Description = "Validate input, wait for approval, then provision targets.", IsActive = true })
|
||||
];
|
||||
|
||||
private static object[] DeploymentRuleSteps() =>
|
||||
[
|
||||
Base(new DeploymentRuleStepModel { Id = RuleStepValidateId, DeploymentRuleId = RuleStandardId, SortOrder = 10, Name = "Validate configuration", StepType = QueueJobStepType.Provision, RequiresApproval = false, MetadataJson = "{\"action\":\"validate\"}" }),
|
||||
Base(new DeploymentRuleStepModel { Id = RuleStepApproveId, DeploymentRuleId = RuleStandardId, SortOrder = 20, Name = "Approve deployment", StepType = QueueJobStepType.Approval, RequiresApproval = true, MetadataJson = "{\"approverGroup\":\"Platform Owners\"}" }),
|
||||
Base(new DeploymentRuleStepModel { Id = RuleStepDeployId, DeploymentRuleId = RuleStandardId, SortOrder = 30, Name = "Provision workload", StepType = QueueJobStepType.Provision, RequiresApproval = false, MetadataJson = "{\"action\":\"deploy\"}" })
|
||||
];
|
||||
|
||||
private static object[] Templates() =>
|
||||
[
|
||||
Base(new TemplateModel { Id = TemplateActiveDirectoryId, TemplateCategoryId = CategoryActiveDirectoryId, DeploymentRuleId = RuleStandardId, Name = "Contoso Active Directory Domain", Version = "1.0.0", Description = "Creates a reusable Active Directory domain baseline.", JSONData = ActiveDirectoryTemplateJson }),
|
||||
Base(new TemplateModel { Id = TemplateSqlServerId, TemplateCategoryId = CategorySqlServerId, DeploymentRuleId = RuleStandardId, Name = "Contoso SQL Server", Version = "1.0.0", Description = "Creates a SQL Server baseline for application workloads.", JSONData = SqlServerTemplateJson }),
|
||||
Base(new TemplateModel { Id = TemplateSharePointId, TemplateCategoryId = CategorySharePointId, DeploymentRuleId = RuleStandardId, Name = "Contoso SharePoint Server", Version = "1.0.0", Description = "Creates a SharePoint Server farm baseline.", JSONData = SharePointTemplateJson }),
|
||||
Base(new TemplateModel { Id = TemplateTeamsId, TemplateCategoryId = CategoryTeamsId, DeploymentRuleId = RuleStandardId, Name = "Contoso Teams Policies", Version = "1.0.0", Description = "Creates a Microsoft Teams policy baseline.", JSONData = TeamsTemplateJson })
|
||||
];
|
||||
|
||||
private static object[] TemplateVersions() =>
|
||||
[
|
||||
TemplateVersion(TemplateActiveDirectoryVersionId, TemplateActiveDirectoryId, ActiveDirectoryTemplateJson),
|
||||
TemplateVersion(TemplateSqlServerVersionId, TemplateSqlServerId, SqlServerTemplateJson),
|
||||
TemplateVersion(TemplateSharePointVersionId, TemplateSharePointId, SharePointTemplateJson),
|
||||
TemplateVersion(TemplateTeamsVersionId, TemplateTeamsId, TeamsTemplateJson)
|
||||
];
|
||||
|
||||
private static object[] DeploymentBatches() =>
|
||||
[
|
||||
Base(new DeploymentGroupModel { Id = DeploymentBatchSharePointId, TemplateId = TemplateSharePointId, DeploymentRuleId = RuleStandardId, Status = QueueJobStatus.Pending })
|
||||
];
|
||||
|
||||
private static object[] Deployments() =>
|
||||
[
|
||||
Base(new DeploymentModel { Id = DeploymentSp01Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp01Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"WebFrontEnd\"}" }),
|
||||
Base(new DeploymentModel { Id = DeploymentSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Application\"}" })
|
||||
];
|
||||
|
||||
private static object[] DeploymentTemplateSelections() =>
|
||||
[
|
||||
Base(new DeploymentTemplateSelectionModel { Id = DeploymentSharePointTemplateSelectionId, DeploymentGroupId = DeploymentBatchSharePointId, TemplateVersionId = TemplateSharePointVersionId, TemplateRole = "Service", SortOrder = 10, Alias = "SharePoint" })
|
||||
];
|
||||
|
||||
private static object[] DeploymentParameterValues() =>
|
||||
[
|
||||
Base(new DeploymentParameterValueModel { Id = DeploymentParameterDatabasePrefixId, DeploymentGroupId = DeploymentBatchSharePointId, DeploymentTemplateSelectionId = DeploymentSharePointTemplateSelectionId, Name = "DatabasePrefix", ValueJson = "{\"value\":\"SharePoint_Contoso_Test\"}", IsOverride = true, IsSecretReference = false }),
|
||||
Base(new DeploymentParameterValueModel { Id = DeploymentParameterFarmAccountId, DeploymentGroupId = DeploymentBatchSharePointId, DeploymentTemplateSelectionId = DeploymentSharePointTemplateSelectionId, Name = "FarmAccount", ValueJson = "{\"provider\":\"SecretManagement\",\"vault\":\"ContosoDemo\",\"name\":\"Windows/SharePoint/FarmAccount\"}", IsOverride = true, IsSecretReference = true })
|
||||
];
|
||||
|
||||
private static object[] DeploymentTargetAssignments() =>
|
||||
[
|
||||
Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetSp01Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp01Id, RoleKey = "WebFrontEnd", SortOrder = 10, NodeDataJson = "{\"nodeName\":\"CT-SHP-01\"}" }),
|
||||
Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, RoleKey = "Application", SortOrder = 20, NodeDataJson = "{\"nodeName\":\"CT-SHP-02\"}" })
|
||||
];
|
||||
|
||||
private static TemplateVersionModel TemplateVersion(Guid id, Guid templateId, string jsonData)
|
||||
{
|
||||
return Base(new TemplateVersionModel
|
||||
{
|
||||
Id = id,
|
||||
TemplateId = templateId,
|
||||
Version = "1.0.0",
|
||||
JsonData = jsonData,
|
||||
JsonHash = TemplateVersionModel.ComputeSha256(jsonData),
|
||||
SchemaVersion = "1.0",
|
||||
IsPublished = true,
|
||||
PublishedAt = Timestamp,
|
||||
PublishedBy = Owner
|
||||
});
|
||||
}
|
||||
|
||||
private static T Base<T>(T model)
|
||||
where T : BaseModel
|
||||
{
|
||||
model.Created = Timestamp;
|
||||
model.Modified = Timestamp;
|
||||
model.CreatedBy = Owner;
|
||||
model.ModifiedBy = Owner;
|
||||
return model;
|
||||
}
|
||||
|
||||
private static T Junction<T>(T model)
|
||||
where T : BaseJunctionModel
|
||||
{
|
||||
model.Created = Timestamp;
|
||||
model.Modified = Timestamp;
|
||||
model.CreatedBy = Owner;
|
||||
model.ModifiedBy = Owner;
|
||||
return model;
|
||||
}
|
||||
|
||||
private const string ActiveDirectoryTemplateJson = """
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"templateType": "Service",
|
||||
"parameters": {
|
||||
"DomainName": { "type": "string", "defaultValue": "corp.contoso.com" },
|
||||
"NetBIOSName": { "type": "string", "defaultValue": "CONTOSO" }
|
||||
},
|
||||
"variables": {
|
||||
"DefaultSiteName": "[concat(parameters('DomainName'), '-DefaultSite')]"
|
||||
},
|
||||
"resources": {
|
||||
"AllNodes": [
|
||||
{ "NodeName": "*", "PSDscAllowPlainTextPassword": true }
|
||||
],
|
||||
"NonNodeData": {
|
||||
"Services": {
|
||||
"ActiveDirectory": {
|
||||
"DomainName": "[parameters('DomainName')]",
|
||||
"NetBIOSName": "[parameters('NetBIOSName')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string SqlServerTemplateJson = """
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"templateType": "Service",
|
||||
"parameters": {
|
||||
"InstanceName": { "type": "string", "defaultValue": "MSSQLSERVER" },
|
||||
"DatabasePrefix": { "type": "string", "defaultValue": "Contoso" }
|
||||
},
|
||||
"variables": {
|
||||
"ConfigDatabase": "[concat(parameters('DatabasePrefix'), '_Config')]"
|
||||
},
|
||||
"resources": {
|
||||
"NonNodeData": {
|
||||
"Services": {
|
||||
"SqlServer": {
|
||||
"InstanceName": "[parameters('InstanceName')]",
|
||||
"ConfigDatabase": "[variables('ConfigDatabase')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string SharePointTemplateJson = """
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"templateType": "Service",
|
||||
"parameters": {
|
||||
"DatabasePrefix": { "type": "string", "defaultValue": "SharePoint_Contoso_Test" },
|
||||
"FarmAccount": { "type": "credential", "metadata": { "description": "Farm account resolved by the credential provider." } }
|
||||
},
|
||||
"variables": {
|
||||
"ConfigDbName": "[concat(parameters('DatabasePrefix'), '_Farm_Config')]",
|
||||
"AdminContentDbName": "[concat(parameters('DatabasePrefix'), '_AdminContent')]"
|
||||
},
|
||||
"resources": {
|
||||
"NonNodeData": {
|
||||
"Services": {
|
||||
"SharePoint": {
|
||||
"Farm": {
|
||||
"ConfigDatabase": "[variables('ConfigDbName')]",
|
||||
"AdminContentDatabase": "[variables('AdminContentDbName')]",
|
||||
"ManagedAccounts": {
|
||||
"FarmAccount": "[parameters('FarmAccount')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string TeamsTemplateJson = """
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"templateType": "Service",
|
||||
"parameters": {
|
||||
"CallingPolicyName": { "type": "string", "defaultValue": "Contoso-Standard-Calling" },
|
||||
"MeetingPolicyName": { "type": "string", "defaultValue": "Contoso-Standard-Meetings" }
|
||||
},
|
||||
"variables": {},
|
||||
"resources": {
|
||||
"NonNodeData": {
|
||||
"Services": {
|
||||
"Teams": {
|
||||
"CallingPolicy": "[parameters('CallingPolicyName')]",
|
||||
"MeetingPolicy": "[parameters('MeetingPolicyName')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user