コード例 #1
0
        public override Task ExecuteAsync()
        {
            var imageInfoFiles = Directory.EnumerateFiles(
                Options.SourceImageInfoFolderPath,
                "*.json",
                SearchOption.AllDirectories);

            List <ImageArtifactDetails> srcImageArtifactDetailsList = imageInfoFiles
                                                                      .OrderBy(file => file) // Ensure the files are ordered for testing consistency between OS's.
                                                                      .Select(imageDataPath => ImageInfoHelper.LoadFromFile(imageDataPath, Manifest))
                                                                      .ToList();

            if (!srcImageArtifactDetailsList.Any())
            {
                throw new InvalidOperationException(
                          $"No JSON files found in source folder '{Options.SourceImageInfoFolderPath}'");
            }

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails();

            foreach (ImageArtifactDetails srcImageArtifactDetails in srcImageArtifactDetailsList)
            {
                ImageInfoHelper.MergeImageArtifactDetails(srcImageArtifactDetails, targetImageArtifactDetails);
            }

            string destinationContents = JsonHelper.SerializeObject(targetImageArtifactDetails) + Environment.NewLine;

            File.WriteAllText(Options.DestinationImageInfoPath, destinationContents);

            return(Task.CompletedTask);
        }
コード例 #2
0
        public void ImageInfoHelper_MergeRepos_EmptyTarget()
        {
            RepoData[] repoDataSet = new RepoData[]
            {
                new RepoData
                {
                    Repo = "repo1",
                },
                new RepoData
                {
                    Repo   = "repo2",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            new ImageData()
                        }
                    }
                }
            };

            List <RepoData> targetRepos = new List <RepoData>();

            ImageInfoHelper.MergeRepos(repoDataSet, targetRepos);

            CompareRepos(repoDataSet, targetRepos);
        }
コード例 #3
0
        public override Task ExecuteAsync()
        {
            var imageInfoFiles = Directory.EnumerateFiles(
                Options.SourceImageInfoFolderPath,
                "*.json",
                SearchOption.AllDirectories);

            List <RepoData[]> srcReposList = imageInfoFiles
                                             .OrderBy(file => file) // Ensure the files are ordered for testing consistency between OS's.
                                             .Select(imageDataPath => JsonConvert.DeserializeObject <RepoData[]>(File.ReadAllText(imageDataPath)))
                                             .ToList();

            if (!srcReposList.Any())
            {
                throw new InvalidOperationException(
                          $"No JSON files found in source folder '{Options.SourceImageInfoFolderPath}'");
            }

            List <RepoData> combinedRepos = new List <RepoData>();

            foreach (RepoData[] repos in srcReposList)
            {
                ImageInfoHelper.MergeRepos(repos, combinedRepos);
            }

            RepoData[] reposArray = combinedRepos
                                    .OrderBy(r => r.Repo)
                                    .ToArray();

            string destinationContents = JsonHelper.SerializeObject(reposArray) + Environment.NewLine;

            File.WriteAllText(Options.DestinationImageInfoPath, destinationContents);

            return(Task.CompletedTask);
        }
コード例 #4
0
        private void SaveTagInfoToImageInfoFile(IEnumerable <ImageInfo> imageInfos, DateTime createdDate)
        {
            this.loggerService.WriteSubheading("SETTING TAG INFO");

            ImageArtifactDetails imageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);

            // Find the images from the image info file that correspond to the images that were published
            IEnumerable <ImageData> imageDataList = imageArtifactDetails.Repos
                                                    .SelectMany(repo => repo.Images)
                                                    .Where(image => imageInfos.Contains(image.ManifestImage));

            if (imageDataList.Count() != imageInfos.Count())
            {
                this.loggerService.WriteError(
                    $"There is a mismatch between the number of images being published and the number of images contained in the image info file ({imageInfos.Count()} vs {imageDataList.Count()}, respectively).");
                this.environmentService.Exit(1);
            }

            Parallel.ForEach(imageDataList, image =>
            {
                image.Manifest.Created = createdDate;

                TagInfo sharedTag  = image.ManifestImage.SharedTags.First();
                JArray tagManifest = this.manifestToolService.Inspect(sharedTag.FullyQualifiedName, Options.IsDryRun);
                string digest      = tagManifest?
                                     .OfType <JObject>()
                                     .First(manifestType => manifestType["MediaType"].Value <string>() == ManifestListMediaType)
                                     ["Digest"].Value <string>();
                image.Manifest.Digest = digest;
            });

            string imageInfoString = JsonHelper.SerializeObject(imageArtifactDetails);

            File.WriteAllText(Options.ImageInfoPath, imageInfoString);
        }
コード例 #5
0
        private async Task <GitObject> GetUpdatedImageInfoGitObjectAsync()
        {
            ImageArtifactDetails srcImageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);

            string repoPath = await GitHelper.DownloadAndExtractGitRepoArchiveAsync(httpClient, Options.GitOptions);

            try
            {
                string repoImageInfoPath = Path.Combine(repoPath, Options.GitOptions.Path);
                string originalTargetImageInfoContents = File.ReadAllText(repoImageInfoPath);

                ImageArtifactDetails newImageArtifactDetails;

                if (originalTargetImageInfoContents != null)
                {
                    ImageArtifactDetails targetImageArtifactDetails = ImageInfoHelper.LoadFromContent(
                        originalTargetImageInfoContents, Manifest, skipManifestValidation: true);

                    RemoveOutOfDateContent(targetImageArtifactDetails);

                    ImageInfoMergeOptions options = new ImageInfoMergeOptions
                    {
                        ReplaceTags = true
                    };

                    ImageInfoHelper.MergeImageArtifactDetails(srcImageArtifactDetails, targetImageArtifactDetails, options);

                    newImageArtifactDetails = targetImageArtifactDetails;
                }
                else
                {
                    // If there is no existing file to update, there's nothing to merge with so the source data
                    // becomes the target data.
                    newImageArtifactDetails = srcImageArtifactDetails;
                }

                string newTargetImageInfoContents =
                    JsonHelper.SerializeObject(newImageArtifactDetails) + Environment.NewLine;

                if (originalTargetImageInfoContents != newTargetImageInfoContents)
                {
                    return(new GitObject
                    {
                        Path = Options.GitOptions.Path,
                        Type = GitObject.TypeBlob,
                        Mode = GitObject.ModeFile,
                        Content = newTargetImageInfoContents
                    });
                }
                else
                {
                    return(null);
                }
            }
            finally
            {
                Directory.Delete(repoPath, recursive: true);
            }
        }
コード例 #6
0
        public void ImageInfoHelper_MergeRepos_ImageDigest()
        {
            ImageInfo imageInfo1 = CreateImageInfo();

            ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile = "image1",
                                        Digest     = "digest"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile = "image1"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageInfoHelper.MergeImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);
            CompareImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);
        }
コード例 #7
0
        private (string imageInfo, string layerInfo) GetImageInfoCsv()
        {
            StringBuilder imageInfo = new();
            StringBuilder layerInfo = new();

            foreach (RepoData repo in ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest).Repos)
            {
                foreach (ImageData image in repo.Images)
                {
                    foreach (PlatformData platform in image.Platforms)
                    {
                        string timestamp = platform.Created.ToUniversalTime().ToString("yyyy'-'MM'-'dd' 'HH':'mm':'ss");
                        string sha       = DockerHelper.GetDigestSha(platform.Digest);
                        imageInfo.AppendLine(FormatImageCsv(sha, platform, image, repo.Repo, timestamp));

                        IEnumerable <TagInfo> tagInfos = (platform.PlatformInfo?.Tags ?? Enumerable.Empty <TagInfo>())
                                                         .Where(tagInfo => platform.SimpleTags.Contains(tagInfo.Name))
                                                         .ToList();

                        IEnumerable <string> syndicatedRepos = tagInfos
                                                               .Select(tag => tag.SyndicatedRepo)
                                                               .Where(repo => repo != null)
                                                               .Distinct();

                        foreach (string syndicatedRepo in syndicatedRepos)
                        {
                            imageInfo.AppendLine(
                                FormatImageCsv(sha, platform, image, syndicatedRepo, timestamp));
                        }

                        foreach (TagInfo tag in tagInfos)
                        {
                            imageInfo.AppendLine(FormatImageCsv(tag.Name, platform, image, repo.Repo, timestamp));

                            if (tag.SyndicatedRepo != null)
                            {
                                foreach (string destinationTag in tag.SyndicatedDestinationTags)
                                {
                                    imageInfo.AppendLine(
                                        FormatImageCsv(destinationTag, platform, image, tag.SyndicatedRepo, timestamp));
                                }
                            }
                        }

                        for (int i = 0; i < platform.Layers.Count; i++)
                        {
                            // TODO: Track layer size (currently set to 0) https://github.com/dotnet/docker-tools/issues/745
                            layerInfo.AppendLine(FormatLayerCsv(
                                                     platform.Layers[i], 0, platform.Layers.Count - i, sha, platform, image, repo.Repo, timestamp));
                        }
                    }
                }
            }

            // Kusto ingest API does not handle an empty line, therefore the last line must be trimmed.
            return(imageInfo.ToString().TrimEnd(Environment.NewLine), layerInfo.ToString().TrimEnd(Environment.NewLine));
        }
コード例 #8
0
        private async Task <IEnumerable <ImageResultInfo> > WaitForImageIngestionAsync(IMcrStatusClient statusClient)
        {
            ImageArtifactDetails imageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);

            List <Task <ImageResultInfo> > tasks = GetImageDigestInfos(imageArtifactDetails)
                                                   .Select(digestInfo => ReportImageStatusWithContinuationAsync(statusClient, digestInfo))
                                                   .ToList();

            return(await TaskHelper.WhenAll(tasks, Options.WaitTimeout));
        }
コード例 #9
0
        public CopyAcrImagesCommand(IAzureManagementFactory azureManagementFactory, IEnvironmentService environmentService) : base()
        {
            this.azureManagementFactory = azureManagementFactory ?? throw new ArgumentNullException(nameof(azureManagementFactory));
            this.environmentService     = environmentService ?? throw new ArgumentNullException(nameof(environmentService));
            this.imageArtifactDetails   = new Lazy <ImageArtifactDetails>(() =>
            {
                if (!String.IsNullOrEmpty(Options.ImageInfoPath))
                {
                    return(ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest));
                }

                return(null);
            });
        }
コード例 #10
0
        public CopyAcrImagesCommand(
            IAzureManagementFactory azureManagementFactory, ILoggerService loggerService)
            : base(azureManagementFactory, loggerService)
        {
            _imageArtifactDetails = new Lazy <ImageArtifactDetails>(() =>
            {
                if (!string.IsNullOrEmpty(Options.ImageInfoPath))
                {
                    return(ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest));
                }

                return(null);
            });
        }
コード例 #11
0
        private string GetImageInfoCsv()
        {
            StringBuilder builder = new StringBuilder();

            foreach (RepoData repo in ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest).Repos)
            {
                foreach (ImageData image in repo.Images)
                {
                    foreach (PlatformData platform in image.Platforms)
                    {
                        string timestamp = platform.Created.ToUniversalTime().ToString("yyyy'-'MM'-'dd' 'HH':'mm':'ss");
                        string sha       = DockerHelper.GetDigestSha(platform.Digest);
                        builder.AppendLine(FormatCsv(sha, platform, image, repo.Repo, timestamp));

                        IEnumerable <TagInfo> tagInfos = platform.PlatformInfo.Tags
                                                         .Where(tagInfo => platform.SimpleTags.Contains(tagInfo.Name))
                                                         .ToList();

                        IEnumerable <string> syndicatedRepos = tagInfos
                                                               .Select(tag => tag.SyndicatedRepo)
                                                               .Where(repo => repo != null)
                                                               .Distinct();

                        foreach (string syndicatedRepo in syndicatedRepos)
                        {
                            builder.AppendLine(
                                FormatCsv(sha, platform, image, syndicatedRepo, timestamp));
                        }

                        foreach (TagInfo tag in tagInfos)
                        {
                            builder.AppendLine(FormatCsv(tag.Name, platform, image, repo.Repo, timestamp));

                            if (tag.SyndicatedRepo != null)
                            {
                                foreach (string destinationTag in tag.SyndicatedDestinationTags)
                                {
                                    builder.AppendLine(
                                        FormatCsv(destinationTag, platform, image, tag.SyndicatedRepo, timestamp));
                                }
                            }
                        }
                    }
                }
            }

            // Kusto ingest API does not handle an empty line, therefore the last line must be trimmed.
            return(builder.ToString().TrimEnd(Environment.NewLine));
        }
コード例 #12
0
        private async Task <ImageArtifactDetails> GetImageInfoForSubscriptionAsync(Subscription subscription, ManifestInfo manifest)
        {
            string imageDataJson;

            using (IGitHubClient gitHubClient = _gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun))
            {
                GitHubProject project = new GitHubProject(subscription.ImageInfo.Repo, subscription.ImageInfo.Owner);
                GitHubBranch  branch  = new GitHubBranch(subscription.ImageInfo.Branch, project);

                GitFile repo = subscription.Manifest;
                imageDataJson = await gitHubClient.GetGitHubFileContentsAsync(subscription.ImageInfo.Path, branch);
            }

            return(ImageInfoHelper.LoadFromContent(imageDataJson, manifest, skipManifestValidation: true));
        }
コード例 #13
0
        public override Task ExecuteAsync()
        {
            IEnumerable <(string Tag, string Platform)> platformTags;

            if (string.IsNullOrEmpty(Options.ImageInfoPath))
            {
                platformTags = Manifest.GetFilteredPlatforms()
                               .Where(platform => platform.Tags.Any())
                               .Select(platform => (platform.Tags.First().FullyQualifiedName, platform.PlatformLabel));
            }
            else
            {
                // We want to apply manifest filtering to the loading of the image info file. This allows, for example,
                // only images of a specific architecture to be pulled.
                ImageArtifactDetails imageArtifactDetails = ImageInfoHelper.LoadFromFile(
                    Options.ImageInfoPath, Manifest, skipManifestValidation: true, useFilteredManifest: true);
                platformTags = imageArtifactDetails.Repos
                               .SelectMany(repo => repo.Images)
                               .SelectMany(image => image.Platforms)
                               // If the platform doesn't have an associated manifest instance, it means the manifest filter
                               // options had filtered out the platform. In that case, it doesn't apply and shouldn't be pulled.
                               .Where(platform => platform.PlatformInfo is not null && platform.SimpleTags.Any())
                               .Select(platform => (
                                           TagInfo.GetFullyQualifiedName(platform.PlatformInfo !.FullRepoModelName, platform.SimpleTags.First()),
                                           platform.PlatformInfo !.PlatformLabel));
            }

            platformTags = platformTags
                           .Distinct()
                           .ToList();

            _loggerService.WriteHeading("PULLING IMAGES");
            foreach ((string tag, string platform) in platformTags)
            {
                _dockerService.PullImage(tag, platform, Options.IsDryRun);
            }

            if (Options.OutputVariableName is not null)
            {
                _loggerService.WriteMessage(
                    PipelineHelper.FormatOutputVariable(
                        Options.OutputVariableName,
                        string.Join(',', platformTags.Select(platformTag => platformTag.Tag))));
            }

            return(Task.CompletedTask);
        }
コード例 #14
0
        private string?GetUpdatedImageInfo(string repoPath)
        {
            ImageArtifactDetails srcImageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);

            string repoImageInfoPath = Path.Combine(repoPath, Options.GitOptions.Path);
            string originalTargetImageInfoContents = File.ReadAllText(repoImageInfoPath);

            ImageArtifactDetails newImageArtifactDetails;

            if (originalTargetImageInfoContents != null)
            {
                ImageArtifactDetails targetImageArtifactDetails = ImageInfoHelper.LoadFromContent(
                    originalTargetImageInfoContents, Manifest, skipManifestValidation: true);

                RemoveOutOfDateContent(targetImageArtifactDetails);

                ImageInfoMergeOptions options = new ImageInfoMergeOptions
                {
                    IsPublish = true
                };

                ImageInfoHelper.MergeImageArtifactDetails(srcImageArtifactDetails, targetImageArtifactDetails, options);

                newImageArtifactDetails = targetImageArtifactDetails;
            }
            else
            {
                // If there is no existing file to update, there's nothing to merge with so the source data
                // becomes the target data.
                newImageArtifactDetails = srcImageArtifactDetails;
            }

            string newTargetImageInfoContents =
                JsonHelper.SerializeObject(newImageArtifactDetails) + Environment.NewLine;

            if (originalTargetImageInfoContents != newTargetImageInfoContents)
            {
                return(newTargetImageInfoContents);
            }
            else
            {
                return(null);
            }
        }
コード例 #15
0
        private void WriteImagesMarkdown(StringBuilder notificationMarkdown)
        {
            if (!File.Exists(Options.ImageInfoPath))
            {
                return;
            }

            ImageArtifactDetails    imageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);
            IEnumerable <ImageData> images = imageArtifactDetails.Repos.SelectMany(repo => repo.Images);
            List <(string digestSha, IEnumerable <string> tags)> publishedImages = new();

            foreach (ImageData image in images)
            {
                if (image.Manifest is not null)
                {
                    string digestSha          = DockerHelper.GetDigestSha(image.Manifest.Digest);
                    IEnumerable <string> tags = GetTags(image.ManifestImage.SharedTags);
                    publishedImages.Add((digestSha, tags));
                }

                publishedImages.AddRange(
                    image.Platforms
                    .Where(platform => platform.PlatformInfo.Tags.Any())
                    .Select(platform =>
                {
                    string digestSha          = DockerHelper.GetDigestSha(platform.Digest);
                    IEnumerable <string> tags = GetTags(platform.PlatformInfo.Tags);
                    return(digestSha, tags);
                }));
            }

            notificationMarkdown.AppendLine("## Images");
            notificationMarkdown.AppendLine();

            foreach ((string digestSha, IEnumerable <string> tags) in publishedImages.OrderBy(digestTags => digestTags.digestSha))
            {
                notificationMarkdown.AppendLine($"* {digestSha}");
                foreach (string tag in tags.OrderBy(tag => tag))
                {
                    notificationMarkdown.AppendLine($"  * {tag}");
                }
            }
        }
コード例 #16
0
        public override Task ExecuteAsync()
        {
            _loggerService.WriteHeading("GENERATING MANIFESTS");

            ImageArtifactDetails imageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);

            ExecuteWithUser(() =>
            {
                IEnumerable <string> manifests = Manifest.FilteredRepos
                                                 .SelectMany(repo =>
                                                             repo.FilteredImages
                                                             .Where(image => image.SharedTags.Any())
                                                             .Select(image => (repo, image)))
                                                 .SelectMany(repoImage => GenerateManifests(repoImage.repo, repoImage.image))
                                                 .ToList();

                DateTime createdDate = DateTime.Now.ToUniversalTime();
                Parallel.ForEach(manifests, manifest =>
                {
                    string manifestFilename = $"manifest.{Guid.NewGuid()}.yml";
                    _loggerService.WriteSubheading($"PUBLISHING MANIFEST:  '{manifestFilename}'{Environment.NewLine}{manifest}");
                    File.WriteAllText(manifestFilename, manifest);

                    try
                    {
                        _manifestToolService.PushFromSpec(manifestFilename, Options.IsDryRun);
                    }
                    finally
                    {
                        File.Delete(manifestFilename);
                    }
                });

                WriteManifestSummary();

                SaveTagInfoToImageInfoFile(createdDate, imageArtifactDetails);
            });

            return(Task.CompletedTask);
        }
コード例 #17
0
        private string GetImageInfoCsv()
        {
            StringBuilder builder = new StringBuilder();

            foreach (RepoData repo in ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest).Repos)
            {
                foreach (ImageData image in repo.Images)
                {
                    foreach (PlatformData platform in image.Platforms)
                    {
                        string timestamp = platform.Created.ToUniversalTime().ToString("yyyy'-'MM'-'dd' 'HH':'mm':'ss");
                        builder.AppendLine(FormatCsv(platform.Digest, platform, image, repo, timestamp));

                        foreach (string tag in platform.SimpleTags)
                        {
                            builder.AppendLine(FormatCsv(tag, platform, image, repo, timestamp));
                        }
                    }
                }
            }

            // Kusto ingest API does not handle an empty line, therefore the last line must be trimmed.
            return(builder.ToString().TrimEnd(Environment.NewLine));
        }
コード例 #18
0
        public void ImageInfoHelper_MergeRepos_EmptyTarget()
        {
            ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo = "repo1",
                    },
                    new RepoData
                    {
                        Repo   = "repo2",
                        Images =
                        {
                            new ImageData
                            {
                                Platforms =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile = "image1"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails();

            ImageInfoHelper.MergeImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);

            CompareImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);
        }
コード例 #19
0
        public void ImageInfoHelper_MergeRepos_RemoveTag()
        {
            PlatformData srcPlatform1;
            PlatformData targetPlatform2;

            ImageInfo imageInfo1 = CreateImageInfo();

            ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    {
                                        srcPlatform1 = new PlatformData
                                        {
                                            Dockerfile = "image1",
                                            SimpleTags =
                                            {
                                                "tag1",
                                                "tag3"
                                            }
                                        }
                                    }
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "sharedtag1",
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    {
                                        new PlatformData
                                        {
                                            Dockerfile = "image1",
                                            SimpleTags =
                                            {
                                                "tag1",
                                                "tag2",
                                                "tag4"
                                            }
                                        }
                                    },
                                    {
                                        targetPlatform2 = new PlatformData
                                        {
                                            Dockerfile = "image2",
                                            SimpleTags =
                                            {
                                                "a"
                                            }
                                        }
                                    }
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "sharedtag2",
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageInfoMergeOptions options = new ImageInfoMergeOptions
            {
                ReplaceTags = true
            };

            ImageInfoHelper.MergeImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails, options);

            ImageArtifactDetails expected = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                Platforms =
                                {
                                    srcPlatform1,
                                    targetPlatform2
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "sharedtag1",
                                    }
                                }
                            }
                        }
                    }
                }
            };

            CompareImageArtifactDetails(expected, targetImageArtifactDetails);
        }
コード例 #20
0
        private void BuildImages()
        {
            _loggerService.WriteHeading("BUILDING IMAGES");

            ImageArtifactDetails?srcImageArtifactDetails = null;

            if (Options.ImageInfoSourcePath != null)
            {
                srcImageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoSourcePath, Manifest, skipManifestValidation: true);
            }

            foreach (RepoInfo repoInfo in Manifest.FilteredRepos)
            {
                RepoData?repoData    = CreateRepoData(repoInfo);
                RepoData?srcRepoData = srcImageArtifactDetails?.Repos.FirstOrDefault(srcRepo => srcRepo.Repo == repoInfo.Name);

                foreach (ImageInfo image in repoInfo.FilteredImages)
                {
                    ImageData?imageData = CreateImageData(image);
                    repoData?.Images.Add(imageData);

                    ImageData?srcImageData = srcRepoData?.Images.FirstOrDefault(srcImage => srcImage.ManifestImage == image);

                    foreach (PlatformInfo platform in image.FilteredPlatforms)
                    {
                        // Tag the built images with the shared tags as well as the platform tags.
                        // Some tests and image FROM instructions depend on these tags.

                        IEnumerable <TagInfo> allTagInfos = platform.Tags
                                                            .Concat(image.SharedTags)
                                                            .ToList();

                        _builtTags.AddRange(allTagInfos);

                        IEnumerable <string> allTags = allTagInfos
                                                       .Select(tag => tag.FullyQualifiedName)
                                                       .ToList();

                        PlatformData?platformData = CreatePlatformData(image, platform);
                        imageData?.Platforms.Add(platformData);

                        bool isCachedImage = !Options.NoCache && CheckForCachedImage(srcImageData, repoInfo, platform, allTags, platformData);

                        if (!isCachedImage)
                        {
                            BuildImage(platform, allTags);

                            if (platformData != null)
                            {
                                platformData.BaseImageDigest =
                                    _imageDigestCache.GetImageDigest(platform.FinalStageFromImage, Options.IsDryRun);
                            }
                        }
                    }
                }

                if (repoData?.Images.Any() == true)
                {
                    _imageArtifactDetails?.Repos.Add(repoData);
                }
            }
        }
コード例 #21
0
        public override async Task ExecuteAsync()
        {
            RepoData[] srcRepos = JsonConvert.DeserializeObject <RepoData[]>(File.ReadAllText(Options.ImageInfoPath));

            using (IGitHubClient gitHubClient = this.gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun))
            {
                await GitHelper.ExecuteGitOperationsWithRetryAsync(async() =>
                {
                    bool hasChanges     = false;
                    GitReference gitRef = await GitHelper.PushChangesAsync(gitHubClient, Options, "Merging image info updates from build.", async branch =>
                    {
                        string originalTargetImageInfoContents = await gitHubClient.GetGitHubFileContentsAsync(Options.GitOptions.Path, branch);
                        IEnumerable <RepoData> newImageInfo;

                        if (originalTargetImageInfoContents != null)
                        {
                            List <RepoData> targetRepos = JsonConvert.DeserializeObject <RepoData[]>(originalTargetImageInfoContents).ToList();

                            ImageInfoMergeOptions options = new ImageInfoMergeOptions
                            {
                                ReplaceTags = true
                            };

                            ImageInfoHelper.MergeRepos(srcRepos, targetRepos, options);

                            newImageInfo = targetRepos;
                        }
                        else
                        {
                            // If there is no existing file to update, there's nothing to merge with so the source data
                            // becomes the target data.
                            newImageInfo = srcRepos;
                        }

                        string newTargetImageInfoContents =
                            JsonHelper.SerializeObject(newImageInfo.OrderBy(r => r.Repo).ToArray()) + Environment.NewLine;

                        if (originalTargetImageInfoContents != newTargetImageInfoContents)
                        {
                            GitObject imageInfoGitObject = new GitObject
                            {
                                Path    = Options.GitOptions.Path,
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = newTargetImageInfoContents
                            };

                            hasChanges = true;
                            return(new GitObject[] { imageInfoGitObject });
                        }
                        else
                        {
                            return(Enumerable.Empty <GitObject>());
                        }
                    });

                    Uri imageInfoPathIdentifier = GitHelper.GetBlobUrl(Options.GitOptions);

                    if (hasChanges)
                    {
                        if (!Options.IsDryRun)
                        {
                            Uri commitUrl = GitHelper.GetCommitUrl(Options.GitOptions, gitRef.Object.Sha);
                            Logger.WriteMessage($"The '{imageInfoPathIdentifier}' file was updated ({commitUrl}).");
                        }
                        else
                        {
                            Logger.WriteMessage($"The '{imageInfoPathIdentifier}' file would have been updated.");
                        }
                    }
                    else
                    {
                        Logger.WriteMessage($"No changes to the '{imageInfoPathIdentifier}' file were needed.");
                    }
                });
            }
        }
コード例 #22
0
        public void ImageInfoHelper_MergeRepos_ExistingTarget()
        {
            PlatformData repo2Image1;
            PlatformData repo2Image2;
            PlatformData repo2Image3;
            PlatformData repo3Image1;

            DateTime oldCreatedDate = DateTime.Now.Subtract(TimeSpan.FromDays(1));
            DateTime newCreatedDate = DateTime.Now;

            ImageInfo imageInfo1 = CreateImageInfo();
            ImageInfo imageInfo2 = CreateImageInfo();

            ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo2",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    {
                                        repo2Image1 = new PlatformData
                                        {
                                            Dockerfile      = "image1",
                                            BaseImageDigest = "base1digest-NEW",
                                            Created         = newCreatedDate
                                        }
                                    },
                                    {
                                        repo2Image3 = new PlatformData
                                        {
                                            Dockerfile = "image3"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    new RepoData
                    {
                        Repo   = "repo3",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo2,
                                Platforms     =
                                {
                                    {
                                        repo3Image1 = new PlatformData
                                        {
                                            Dockerfile = "image1"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    new RepoData
                    {
                        Repo = "repo4",
                    }
                }
            };

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo = "repo1"
                    },
                    new RepoData
                    {
                        Repo   = "repo2",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile      = "image1",
                                        BaseImageDigest = "base1digest",
                                        Created         = oldCreatedDate
                                    },
                                    {
                                        repo2Image2 = new PlatformData
                                        {
                                            Dockerfile      = "image2",
                                            BaseImageDigest = "base2digest"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    new RepoData
                    {
                        Repo = "repo3"
                    }
                }
            };

            ImageInfoHelper.MergeImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);

            ImageArtifactDetails expected = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo = "repo1"
                    },
                    new RepoData
                    {
                        Repo   = "repo2",
                        Images =
                        {
                            new ImageData
                            {
                                Platforms =
                                {
                                    repo2Image1,
                                    repo2Image2,
                                    repo2Image3
                                }
                            }
                        }
                    },
                    new RepoData
                    {
                        Repo   = "repo3",
                        Images =
                        {
                            new ImageData
                            {
                                Platforms =
                                {
                                    repo3Image1
                                }
                            }
                        }
                    },
                    new RepoData
                    {
                        Repo = "repo4",
                    }
                }
            };

            CompareImageArtifactDetails(expected, targetImageArtifactDetails);
        }
コード例 #23
0
        public void ImageInfoHelper_MergeRepos_MergeTags()
        {
            PlatformData srcImage1;
            PlatformData targetImage2;

            ImageInfo imageInfo1 = CreateImageInfo();

            ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    {
                                        srcImage1 = new PlatformData
                                        {
                                            Dockerfile = "image1",
                                            SimpleTags =
                                            {
                                                "tag1",
                                                "tag3"
                                            }
                                        }
                                    }
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "shared1",
                                        "shared2"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                ManifestImage = imageInfo1,
                                Platforms     =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile = "image1",
                                        SimpleTags =
                                        {
                                            "tag1",
                                            "tag2",
                                            "tag4"
                                        }
                                    },
                                    {
                                        targetImage2 = new PlatformData
                                        {
                                            Dockerfile = "image2",
                                            SimpleTags =
                                            {
                                                "a"
                                            }
                                        }
                                    }
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "shared2",
                                        "shared3"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            ImageInfoHelper.MergeImageArtifactDetails(imageArtifactDetails, targetImageArtifactDetails);

            ImageArtifactDetails expected = new ImageArtifactDetails
            {
                Repos =
                {
                    new RepoData
                    {
                        Repo   = "repo1",
                        Images =
                        {
                            new ImageData
                            {
                                Platforms =
                                {
                                    new PlatformData
                                    {
                                        Dockerfile = "image1",
                                        SimpleTags =
                                        {
                                            "tag1",
                                            "tag2",
                                            "tag3",
                                            "tag4"
                                        }
                                    },
                                    targetImage2
                                },
                                Manifest = new ManifestData
                                {
                                    SharedTags =
                                    {
                                        "shared1",
                                        "shared2",
                                        "shared3"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            CompareImageArtifactDetails(expected, targetImageArtifactDetails);
        }
コード例 #24
0
        public void ImageInfoHelper_MergeRepos_ExistingTarget()
        {
            ImageData repo2Image1;
            ImageData repo2Image2;
            ImageData repo2Image3;
            ImageData repo3Image1;

            RepoData[] repoDataSet = new RepoData[]
            {
                new RepoData
                {
                    Repo   = "repo2",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            repo2Image1 = new ImageData
                            {
                                BaseImages = new SortedDictionary <string, string>
                                {
                                    { "base1", "base1digest-NEW" }
                                }
                            }
                        }
                        ,
                        {
                            "image3",
                            repo2Image3 = new ImageData()
                        }
                    }
                },
                new RepoData
                {
                    Repo   = "repo3",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            repo3Image1 = new ImageData()
                        }
                    }
                },
                new RepoData
                {
                    Repo = "repo4",
                }
            };

            List <RepoData> targetRepos = new List <RepoData>
            {
                new RepoData
                {
                    Repo = "repo1"
                },
                new RepoData
                {
                    Repo   = "repo2",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            new ImageData
                            {
                                BaseImages = new SortedDictionary <string, string>
                                {
                                    { "base1", "base1digest" }
                                }
                            }
                        },
                        {
                            "image2",
                            repo2Image2 = new ImageData
                            {
                                BaseImages = new SortedDictionary <string, string>
                                {
                                    { "base2", "base2digest" }
                                }
                            }
                        }
                    }
                },
                new RepoData
                {
                    Repo = "repo3"
                }
            };

            ImageInfoHelper.MergeRepos(repoDataSet, targetRepos);

            List <RepoData> expected = new List <RepoData>
            {
                new RepoData
                {
                    Repo = "repo1"
                },
                new RepoData
                {
                    Repo   = "repo2",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            repo2Image1
                        },
                        {
                            "image2",
                            repo2Image2
                        },
                        {
                            "image3",
                            repo2Image3
                        }
                    }
                },
                new RepoData
                {
                    Repo   = "repo3",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            repo3Image1
                        }
                    }
                },
                new RepoData
                {
                    Repo = "repo4",
                }
            };

            CompareRepos(expected, targetRepos);
        }
コード例 #25
0
        public void ImageInfoHelper_MergeRepos_RemoveTag()
        {
            ImageData srcImage1;
            ImageData targetImage2;

            RepoData[] repoDataSet = new RepoData[]
            {
                new RepoData
                {
                    Repo   = "repo1",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            srcImage1 = new ImageData
                            {
                                SimpleTags =
                                {
                                    "tag1",
                                    "tag3"
                                }
                            }
                        }
                    }
                }
            };

            List <RepoData> targetRepos = new List <RepoData>
            {
                new RepoData
                {
                    Repo   = "repo1",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            new ImageData
                            {
                                SimpleTags =
                                {
                                    "tag1",
                                    "tag2",
                                    "tag4"
                                }
                            }
                        },
                        {
                            "image2",
                            targetImage2 = new ImageData
                            {
                                SimpleTags =
                                {
                                    "a"
                                }
                            }
                        }
                    }
                }
            };

            ImageInfoMergeOptions options = new ImageInfoMergeOptions
            {
                ReplaceTags = true
            };

            ImageInfoHelper.MergeRepos(repoDataSet, targetRepos, options);

            List <RepoData> expected = new List <RepoData>
            {
                new RepoData
                {
                    Repo   = "repo1",
                    Images = new SortedDictionary <string, ImageData>
                    {
                        {
                            "image1",
                            srcImage1
                        },
                        {
                            "image2",
                            targetImage2
                        }
                    }
                }
            };

            CompareRepos(expected, targetRepos);
        }