Exemple #1
0
        public async Task <bool> EnqueueDeployment(Deployment deployment, TimeSpan?delay = null, bool force = false)
        {
            if (!force)
            {
                if (deployment.Status != DeploymentStatus.Pending)
                {
                    return(false);
                }
            }

            // add entry in store
            var dao = await _deploymentQueueRepository.Add(new DeploymentQueue()
            {
                DeploymentId      = deployment.Id,
                Id                = Guid.NewGuid(),
                ApplicationId     = deployment.ApplicationId,
                AttemptCount      = 0,
                AvailableDateTime = DateTime.Now.Add(delay ?? TimeSpan.FromSeconds(0)),
                CreationDateTime  = DateTime.Now
            });

            await _deploymentQueueRepository.Save();

            await _deploymentService.ChangeDeploymentUpdateStatus(deployment.Id, DeploymentStatus.Queued);

            return(true);
        }
Exemple #2
0
        private async Task <bool> InternalExecute <TManifest>(TManifest manifest, Application application)
            where TManifest : DeploymentManifest
        {
            // prefetch and structure some metadata required throughout
            var imageMap = application.Images.ToDictionary(
                x => $"{x.Repository}-{x.TagProperty.Path}"
                );

            // store
            var manifestsChanged = false;

            // 1. check for any orphan preview releases
            var appImagesWithPreviewReleases = imageMap.Values
                                               .Where(x => x.SourceCode.IsAvailable && x.DeploymentSettings.PreviewReleases.Enabled)
                                               .ToArray();

            if (appImagesWithPreviewReleases.Any())
            {
                _log.LogInformation("Checking for orphan preview releases ...");
                foreach (var item in appImagesWithPreviewReleases)
                {
                    if (!item.SourceCode.IsAvailable)
                    {
                        continue;
                    }

                    var openPullRequests = (await _githubPullRequestService.GetOpenPRs(item))
                                           .ToArray();
                    _log.LogTrace("Found {prCount} open pull requests", openPullRequests.Length);

                    var appImageInstances = (await _applicationImageInstanceService.GetInstancesFor(application, item))
                                            .ToArray();
                    _log.LogTrace("Found {instanceCount} active instances", appImageInstances.Length);

                    foreach (var applicationImageInstance in appImageInstances)
                    {
                        if (applicationImageInstance.Source.Type != ApplicationImageInstanceSourceType.PullRequest)
                        {
                            continue;
                        }

                        if (openPullRequests.Any(x => x.PrNumber.Equals(applicationImageInstance.Source.PullRequestId)))
                        {
                            continue;
                        }

                        _log.LogTrace("No pull request found for instance {instanceName}, removing ...",
                                      applicationImageInstance.Name);
                        await _deploymentManifestSourceManagementFacade.RemovePreviewRelease(manifest, item,
                                                                                             applicationImageInstance.Name);

                        await _applicationImageInstanceService.RemoveInstance(application, item, applicationImageInstance);

                        manifestsChanged = true;
                    }
                }
            }

            _log.LogTrace("Checking for pending deployments to apply.");

            // start updating files
            var        updatedImageTags      = new Dictionary <ApplicationImageInstanceKey, string>();
            Deployment?nextPendingDeployment = null;

            while ((nextPendingDeployment =
                        await _deploymentQueueService.GetNextPendingDeploymentUpdate(application)) != null)
            {
                await _deploymentService.ChangeDeploymentUpdateStatus(
                    nextPendingDeployment.Id,
                    DeploymentStatus.Starting
                    );

                _log.LogTrace("Executing pending deployment update ...");

                await _deploymentService.ChangeDeploymentUpdateStatus(
                    nextPendingDeployment.Id,
                    DeploymentStatus.UpdatingManifests
                    );

                var deploymentManifestInfo =
                    await _deploymentManifestSourceManagementFacade.GetDeploymentManifestInfo(manifest);

                var image = imageMap[$"{nextPendingDeployment.ImageRepository}-{nextPendingDeployment.UpdatePath}"];

                var dmiKey = new DeploymentManifestInstanceKey(image, nextPendingDeployment.InstanceId);

                switch (nextPendingDeployment.Type)
                {
                case DeploymentType.ImageUpdate:
                    await _deploymentManifestSourceManagementFacade.UpdateApplicationImageVersion(
                        manifest,
                        image,
                        nextPendingDeployment.InstanceId,
                        nextPendingDeployment.TargetTag
                        );

                    break;

                case DeploymentType.PreviewRelease:
                    if (!deploymentManifestInfo.Instances.ContainsKey(dmiKey))
                    {
                        await _deploymentManifestSourceManagementFacade.CreatePreviewRelease(
                            manifest,
                            image,
                            nextPendingDeployment.InstanceId,
                            nextPendingDeployment.TargetTag
                            );
                    }
                    else
                    {
                        await _deploymentManifestSourceManagementFacade.UpdateApplicationImageVersion(
                            manifest,
                            image,
                            nextPendingDeployment.InstanceId,
                            nextPendingDeployment.TargetTag
                            );
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                var key = new ApplicationImageInstanceKey(application, image, nextPendingDeployment.InstanceId);
                updatedImageTags[key] = nextPendingDeployment.TargetTag;
                manifestsChanged      = true;

                // TODO: rework this so that failures to push get indicated
                await _deploymentService.FinishDeploymentUpdate(
                    nextPendingDeployment.Id,
                    manifestsChanged?DeploymentStatus.Complete : DeploymentStatus.Failed
                    );
            }

            await SyncApplicationMetadataFromManifest(manifest, application, updatedImageTags);

            _log.LogTrace("Deployment manifest repository syncing complete ...");


            return(manifestsChanged);
        }
Exemple #3
0
        private async Task <bool> SynchronizeHelmApplicationSource(Repository gitRepository,
                                                                   ApplicationSourceTrackingContext context,
                                                                   HelmApplicationSource helmApplicationSource)
        {
            var relativePath          = helmApplicationSource.Path;
            var applicationSourcePath = Path.Combine(context.GitRepositoryPath, relativePath);

            var application   = context.Application;
            var yamlUtilities = new YamlUtilities();

            // build map of images -> yaml file that defines them and image -> current tag
            _log.LogInformation("Beginning to parse value files defined in application source ...");

            var imageToFilenameMap   = new Dictionary <Image, string>();
            var imageToTagInManifest = new Dictionary <Image, string>();

            foreach (var file in helmApplicationSource.ValuesFiles)
            {
                var yaml     = new YamlStream();
                var filePath = Path.Combine(applicationSourcePath, file);
                yamlUtilities.ReadYamlStream(yaml, filePath);

                foreach (var doc in yaml.Documents)
                {
                    foreach (var image in context.Application.Images)
                    {
                        var tagInManifest = yamlUtilities.ExtractValueFromDoc(image.TagProperty.Path, doc);

                        if (tagInManifest == null)
                        {
                            continue;
                        }

                        if (imageToFilenameMap.ContainsKey(image))
                        {
                            // TODO: handle situation where multiple files define the same image tag (ERROR and warn user)
                        }

                        imageToFilenameMap[image]   = file;
                        imageToTagInManifest[image] = tagInManifest;
                    }
                }
            }

            _log.LogInformation("Completing parsing value files defined in application source ...");

            // start updating files
            var manifestsChanged = false;
            DeploymentUpdate deploymentUpdate = null;

            while ((deploymentUpdate = await _deploymentService.GetNextPendingDeploymentUpdate(application)) != null)
            {
                _log.LogInformation("Executing pending deployment update ...");

                await _deploymentService.ChangeDeploymentUpdateStatus(
                    deploymentUpdate,
                    DeploymentUpdateStatus.UpdatingManifests
                    );

                manifestsChanged = await UpdateDeploymentManifests(gitRepository,
                                                                   deploymentUpdate,
                                                                   imageToFilenameMap,
                                                                   imageToTagInManifest.TryGetAndReturn(deploymentUpdate.Image) ?? "n/a",
                                                                   applicationSourcePath,
                                                                   yamlUtilities,
                                                                   relativePath);

                if (manifestsChanged)
                {
                    imageToTagInManifest[deploymentUpdate.Image] = deploymentUpdate.TargetTag;
                }

                await _deploymentService.FinishDeploymentUpdate(
                    deploymentUpdate,
                    manifestsChanged?DeploymentUpdateStatus.Complete : DeploymentUpdateStatus.Failed
                    );
            }

            if (!manifestsChanged)
            {
                // we don't have a deployment, ensure application manifest is up to date with latest image tags
                foreach (var keyValuePair in imageToTagInManifest)
                {
                    _applicationService.SetCurrentImageTag(application, keyValuePair.Key, keyValuePair.Value);
                }
            }

            return(manifestsChanged);
        }