using Microsoft.EntityFrameworkCore; using Microsoft.SelfService.Portal.Core.API.Context; using Microsoft.SelfService.Portal.Core.API.Interfaces; using Microsoft.SelfService.Portal.Core.API.Models; using System.Text.Json; namespace Microsoft.SelfService.Portal.Core.API.Repository { public class DeploymentBatchRepository : IDeploymentBatchInterface { private readonly DataContext _context; public DeploymentBatchRepository(DataContext context) { _context = context; } public ICollection GetDeploymentBatches() { return _context.DeploymentGroups .Include(batch => batch.TemplateSelections) .ThenInclude(selection => selection.TemplateVersion) .ThenInclude(version => version.Template) .Include(batch => batch.TargetAssignments) .ToList(); } public DeploymentGroupModel? GetDeploymentBatchById(Guid id) { return _context.DeploymentGroups .Include(t => t.Template) .ThenInclude(tc => tc.TemplateCategory) .ThenInclude(s => s.Service) .Include(d => d.Deployments) .ThenInclude(vm => vm.Target) .Include(batch => batch.TemplateSelections) .ThenInclude(selection => selection.TemplateVersion) .Include(batch => batch.ParameterValues) .Include(batch => batch.TargetAssignments) .ThenInclude(target => target.Target) .Where(dg => dg.Id == id).FirstOrDefault(); } public bool AddDeploymentBatchById(DeploymentGroupModel deploymentBatch, ICollection? targetIds) { if (deploymentBatch.Id == Guid.Empty) { deploymentBatch.Id = Guid.NewGuid(); } var requestedTemplateVersionId = deploymentBatch.TemplateSelections .OrderBy(selection => selection.SortOrder) .Select(selection => (Guid?)selection.TemplateVersionId) .FirstOrDefault(); var templateVersion = requestedTemplateVersionId.HasValue ? _context.TemplateVersions .Include(version => version.Template) .ThenInclude(template => template.TemplateCategory) .ThenInclude(category => category.Service) .FirstOrDefault(version => version.Id == requestedTemplateVersionId.Value) : null; var template = templateVersion?.Template ?? _context.Templates .Include(existing => existing.TemplateCategory) .ThenInclude(existing => existing.Service) .Include(existing => existing.TemplateVersions) .FirstOrDefault(existing => existing.Id == deploymentBatch.TemplateId); if (template == null) { return false; } deploymentBatch.TemplateId = template.Id; if (deploymentBatch.DeploymentRuleId.HasValue) { var ruleExists = _context.DeploymentRules.Any(existing => existing.Id == deploymentBatch.DeploymentRuleId.Value); if (!ruleExists) { return false; } } var isCloudService = template.TemplateCategory.Service.IsCloudService; var selectedTargetIds = (targetIds ?? Array.Empty()) .Concat(deploymentBatch.TargetAssignments.Select(assignment => assignment.TargetId)) .Distinct() .ToList(); if (!isCloudService && selectedTargetIds.Count == 0) { return false; } if (selectedTargetIds.Count > 0) { var existingTargetIds = _context.Targets .Where(existing => selectedTargetIds.Contains(existing.Id)) .Select(existing => existing.Id) .ToHashSet(); if (existingTargetIds.Count != selectedTargetIds.Count) { return false; } } _context.Add(deploymentBatch); if (deploymentBatch.TemplateSelections.Count == 0) { templateVersion ??= template.TemplateVersions? .OrderByDescending(version => version.IsPublished) .ThenByDescending(version => version.PublishedAt) .ThenByDescending(version => version.Created) .FirstOrDefault(); if (templateVersion == null) { return false; } deploymentBatch.TemplateSelections.Add(new DeploymentTemplateSelectionModel { Id = Guid.NewGuid(), DeploymentGroupId = deploymentBatch.Id, TemplateVersionId = templateVersion.Id, TemplateRole = "Service", SortOrder = 10, Alias = template.Name }); } if (deploymentBatch.TargetAssignments.Count == 0) { var sortOrder = 10; foreach (var targetId in selectedTargetIds) { var targetName = _context.Targets .Where(target => target.Id == targetId) .Select(target => target.Name) .FirstOrDefault(); deploymentBatch.TargetAssignments.Add(new DeploymentTargetAssignmentModel { Id = Guid.NewGuid(), DeploymentGroupId = deploymentBatch.Id, TargetId = targetId, RoleKey = "Node", SortOrder = sortOrder, NodeDataJson = JsonSerializer.Serialize(new { nodeName = targetName ?? targetId.ToString() }) }); sortOrder += 10; } } if (!SaveChanges()) { return false; } if (!isCloudService) { foreach (var targetId in selectedTargetIds) { _context.Deployments.Add(new DeploymentModel { DeploymentGroupId = deploymentBatch.Id, TargetId = targetId, Status = QueueJobStatus.Pending, JSONData = "{}" }); } return SaveChanges(); } return true; } public bool DeleteDeploymentBatchById(DeploymentGroupModel deploymentBatch) { var templateSelections = _context.DeploymentTemplateSelections .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) .ToList(); var parameterValues = _context.DeploymentParameterValues .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) .ToList(); var targetAssignments = _context.DeploymentTargetAssignments .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) .ToList(); var deployments = _context.Deployments .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) .ToList(); if (parameterValues.Count > 0) { _context.DeploymentParameterValues.RemoveRange(parameterValues); } if (targetAssignments.Count > 0) { _context.DeploymentTargetAssignments.RemoveRange(targetAssignments); } if (templateSelections.Count > 0) { _context.DeploymentTemplateSelections.RemoveRange(templateSelections); } if (deployments.Count > 0) { _context.Deployments.RemoveRange(deployments); } _context.Remove(deploymentBatch); return SaveChanges(); } public bool EditDeploymentBatchById(DeploymentGroupModel deploymentBatch) { _context.Update(deploymentBatch); return SaveChanges(); } public bool CheckDeploymentBatchById(Guid id) { return _context.DeploymentGroups .Any(d => d.Id == id); } public bool SaveChanges() { var saved = _context.SaveChanges(); return saved > 0 ? true : false; } } }