예제 #1
0
        private async Task SyncApplicationMetadataFromManifest <TManifest>(TManifest manifest, Application application,
                                                                           Dictionary <ApplicationImageInstanceKey, string> updatedImageTags) where TManifest : DeploymentManifest
        {
            _log.LogTrace("Parsing deployment manifest prior to updating application info ...");

            var deploymentManifestInfo =
                await _deploymentManifestSourceManagementFacade.GetDeploymentManifestInfo(manifest);

            foreach (var(deploymentManifestInstanceKey, value) in deploymentManifestInfo.Instances)
            {
                var applicationImage = deploymentManifestInstanceKey.ApplicationImage;
                var instanceId       = deploymentManifestInstanceKey.InstanceName;

                var key = new ApplicationImageInstanceKey(application, applicationImage, instanceId);
                if (!updatedImageTags.TryGetValue(key, out var currentTag))
                {
                    // we didn't update the tag in the deployment manifest, use the original tag loaded from the manifest
                    currentTag = value.Tag;
                }

                await _applicationImageInstanceService.AddOrUpdateInstance(
                    application,
                    applicationImage,
                    value.Name,
                    value.Type,
                    value.Source,
                    currentTag
                    );
            }
        }
예제 #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);
        }