public void DuplicatedPlatforms(MatrixType matrixType) { TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = matrixType; command.Options.ProductVersionComponents = 2; Manifest manifest = CreateManifest( CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("3.1/runtime/os", tempFolderContext), new string[] { "tag" }) }, productVersion: "3.1"), CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("3.1/runtime/os", tempFolderContext), Array.Empty <string>()) }, productVersion: "3.1"))); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); Assert.Single(matrixInfo.Legs); string expectedLegName; if (matrixType == MatrixType.PlatformDependencyGraph) { expectedLegName = "3.1-runtime-os-Dockerfile-graph"; } else { expectedLegName = "3.1-focal-runtime"; } Assert.Equal(expectedLegName, matrixInfo.Legs[0].Name); string imageBuilderPaths = matrixInfo.Legs[0].Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal($"--path 3.1/runtime/os/Dockerfile", imageBuilderPaths); }
public void Load_Include_Repos() { const string includeManifestPath1 = "manifest.custom1.json"; const string includeManifestPath2 = "manifest.custom2.json"; string manifest = $@" {{ ""includes"": [ ""{includeManifestPath1}"", ""{includeManifestPath2}"" ] }}"; string includeManifest1 = $@" {{ ""repos"": [ {CreateRepo("testRepo1", s_dockerfilePath, "testTag1")}, {CreateRepo("testRepo2", s_dockerfilePath)} ] }}"; string includeManifest2 = $@" {{ ""repos"": [ {CreateRepo("testRepo1", s_dockerfilePath, "testTag2")}, {CreateRepo("testRepo3", s_dockerfilePath)} ] }}"; using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, manifest); File.WriteAllText(Path.Combine(tempFolderContext.Path, includeManifestPath1), includeManifest1); File.WriteAllText(Path.Combine(tempFolderContext.Path, includeManifestPath2), includeManifest2); DockerfileHelper.CreateDockerfile(s_dockerfilePath, tempFolderContext); IManifestOptionsInfo manifestOptions = ManifestHelper.GetManifestOptions(manifestPath); ManifestInfo manifestInfo = ManifestInfo.Load(manifestOptions); Assert.Equal(3, manifestInfo.Model.Repos.Length); Assert.Equal("testRepo1", manifestInfo.Model.Repos[0].Name); Assert.Equal("testRepo2", manifestInfo.Model.Repos[1].Name); Assert.Equal("testRepo3", manifestInfo.Model.Repos[2].Name); Assert.Equal(2, manifestInfo.Model.Repos[0].Images.Length); Assert.Equal(1, manifestInfo.Model.Repos[1].Images.Length); Assert.Equal(1, manifestInfo.Model.Repos[2].Images.Length); }
private GenerateReadmesCommand InitializeCommand( TempFolderContext tempFolderContext, string readmeTemplate = ReadmeTemplate, string productFamilyReadme = DefaultReadme, string repoReadme = DefaultReadme, bool allowOptionalTemplates = true, bool validate = false) { DockerfileHelper.CreateFile(ProductFamilyReadmePath, tempFolderContext, productFamilyReadme); DockerfileHelper.CreateFile(RepoReadmePath, tempFolderContext, repoReadme); DockerfileHelper.CreateFile(AboutRepoTemplatePath, tempFolderContext, AboutRepoTemplate); string templatePath = null; if (readmeTemplate != null) { DockerfileHelper.CreateFile(ReadmeTemplatePath, tempFolderContext, readmeTemplate); templatePath = ReadmeTemplatePath; } Repo repo = CreateRepo("dotnet/repo"); repo.Readmes = new[] { new Readme(RepoReadmePath, templatePath) }; Manifest manifest = CreateManifest(repo); manifest.Registry = "mcr.microsoft.com"; manifest.Readme = new(ProductFamilyReadmePath, templatePath); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); Mock <IGitService> gitServiceMock = new Mock <IGitService>(); _environmentServiceMock = new Mock <IEnvironmentService>(); _environmentServiceMock .Setup(o => o.Exit(1)) .Throws(_exitException); GenerateReadmesCommand command = new GenerateReadmesCommand(_environmentServiceMock.Object, gitServiceMock.Object); command.Options.Manifest = manifestPath; command.Options.AllowOptionalTemplates = allowOptionalTemplates; command.Options.Validate = validate; command.LoadManifest(); return(command); }
private GenerateDockerfilesCommand InitializeCommand( TempFolderContext tempFolderContext, string dockerfileTemplate = DefaultDockerfileTemplate, string dockerfile = DefaultDockerfile, bool validate = false) { DockerfileHelper.CreateFile(DockerfileTemplatePath, tempFolderContext, dockerfileTemplate); DockerfileHelper.CreateFile(DockerfilePath, tempFolderContext, dockerfile); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( CreatePlatform( DockerfilePath, new string[] { "tag1" }, OS.Linux, "buster-slim", Architecture.ARM, "v7", dockerfileTemplatePath: DockerfileTemplatePath), CreatePlatform( DockerfilePath, new string[] { "tag2" }, OS.Windows, "nanoserver-1903"), CreatePlatform( DockerfilePath, new string[] { "tag3" }, OS.Linux, "alpine3.12"))) ); AddVariable(manifest, "Variable1", "Value1"); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); _environmentServiceMock = new Mock <IEnvironmentService>(); _environmentServiceMock .Setup(o => o.Exit(1)) .Throws(_exitException); GenerateDockerfilesCommand command = new GenerateDockerfilesCommand(_environmentServiceMock.Object); command.Options.Manifest = manifestPath; command.Options.Validate = validate; command.LoadManifest(); return(command); }
public async Task GenerateDockerfilesCommand_MismatchedTemplates() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); DockerfileHelper.CreateFile(DockerfilePath, tempFolderContext, DefaultDockerfile); string templatePath1 = "Dockerfile.Template1"; DockerfileHelper.CreateFile(templatePath1, tempFolderContext, DefaultDockerfileTemplate); string templatePath2 = "Dockerfile.Template2"; DockerfileHelper.CreateFile(templatePath2, tempFolderContext, DefaultDockerfileTemplate); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform( DockerfilePath, new string[] { "tag1" }, OS.Windows, "nanoserver-1903", dockerfileTemplatePath: templatePath1), CreatePlatform( DockerfilePath, new string[] { "tag2" }, OS.Windows, "windowsservercore-1903", dockerfileTemplatePath: templatePath2) }, productVersion: "1.2.3" ) ) ); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); GenerateDockerfilesCommand command = new(Mock.Of <IEnvironmentService>()); command.Options.Manifest = manifestPath; command.LoadManifest(); InvalidOperationException exception = await Assert.ThrowsAsync <InvalidOperationException>(() => command.ExecuteAsync()); Assert.StartsWith("Multiple unique template files are associated with the generated artifact path", exception.Message); }
private static ManifestInfo LoadManifestInfo(string manifest, string includeManifestPath = null, string includeManifest = null) { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, manifest); if (includeManifestPath != null) { string fullIncludeManifestPath = Path.Combine(tempFolderContext.Path, includeManifestPath); File.WriteAllText(fullIncludeManifestPath, includeManifest); } DockerfileHelper.CreateDockerfile(s_dockerfilePath, tempFolderContext); IManifestOptionsInfo manifestOptions = ManifestHelper.GetManifestOptions(manifestPath); return(ManifestInfo.Load(manifestOptions)); }
public async Task GenerateReadmesCommand_TemplateArgs() { const string readmeTemplate = @"Hello World {{InsertTemplate(""template-with-args.md"", [ ""my-arg"": 123 ])}}"; const string templateWithArgs = @"ABC-{{ARGS[""my-arg""]}}"; using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); DockerfileHelper.CreateFile("template-with-args.md", tempFolderContext, templateWithArgs); GenerateReadmesCommand command = InitializeCommand(tempFolderContext, readmeTemplate); await command.ExecuteAsync(); string generatedReadme = File.ReadAllText(Path.Combine(tempFolderContext.Path, ProductFamilyReadmePath)); string expectedReadme = @"Hello World ABC-123"; Assert.Equal(expectedReadme, generatedReadme); }
public void HandlesUndocumentedPlatform() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); const string SourceRepoUrl = "https://www.github.com/dotnet/dotnet-docker"; const string RepoName = "repo"; const string SourceBranch = "branch"; // Create MCR tags metadata template file StringBuilder tagsMetadataTemplateBuilder = new StringBuilder(); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlRepo:{RepoName})"); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlTagGroup:tag1a)"); string tagsMetadataTemplatePath = Path.Combine(tempFolderContext.Path, "tags.yaml"); File.WriteAllText(tagsMetadataTemplatePath, tagsMetadataTemplateBuilder.ToString()); Platform platform = ManifestHelper.CreatePlatform( DockerfileHelper.CreateDockerfile($"1.0/{RepoName}/os", tempFolderContext), Array.Empty <string>()); platform.Tags = new Dictionary <string, Tag> { { "tag2", new Tag { IsUndocumented = true } } }; // Create manifest Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo(RepoName, new Image[] { ManifestHelper.CreateImage( platform, ManifestHelper.CreatePlatform( DockerfileHelper.CreateDockerfile($"1.0/{RepoName}/os2", tempFolderContext), new string[] { "tag1a", "tag1b" })) }, mcrTagsMetadataTemplatePath: Path.GetFileName(tagsMetadataTemplatePath)) ); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); // Load manifest IManifestOptionsInfo manifestOptions = GetManifestOptions(manifestPath); ManifestInfo manifestInfo = ManifestInfo.Load(manifestOptions); RepoInfo repo = manifestInfo.AllRepos.First(); Mock <IGitService> gitServiceMock = new Mock <IGitService>(); // Execute generator string result = McrTagsMetadataGenerator.Execute( gitServiceMock.Object, manifestInfo, repo, SourceRepoUrl, SourceBranch); Models.Mcr.McrTagsMetadata tagsMetadata = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build() .Deserialize <Models.Mcr.McrTagsMetadata>(result); // Verify the output only contains the platform with the documented tag Assert.Single(tagsMetadata.Repos[0].TagGroups); Assert.Equal( $"{SourceRepoUrl}/blob/{SourceBranch}/1.0/{RepoName}/os2/Dockerfile", tagsMetadata.Repos[0].TagGroups[0].Dockerfile); Assert.Equal(new string[] { "tag1a", "tag1b" }, tagsMetadata.Repos[0].TagGroups[0].Tags); }
public async Task IngestKustoImageInfoCommand_MultipleRepos() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os", tempFolderContext); string repo1Image2DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os2", tempFolderContext); string repo2Image2DockerfilePath = DockerfileHelper.CreateDockerfile("2.0/sdk/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("r1", CreateImage( new Platform[] { CreatePlatform(repo1Image1DockerfilePath, new string[] { "t1" }), CreatePlatform(repo1Image2DockerfilePath, new string[] { "t2" }) }, productVersion: "1.0.2", sharedTags: new Dictionary <string, Tag> { { "st1", new Tag() } })), CreateRepo("r2", CreateImage( new Platform[] { CreatePlatform(repo2Image2DockerfilePath, new string[] { "t3" }) }, productVersion: "2.0.5")) ); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); ImageArtifactDetails srcImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "r1", Images = { new ImageData { Manifest = new ManifestData { Created = new DateTime(2020, 4, 20, 21, 57, 00, DateTimeKind.Utc), Digest = "abc", SharedTags = new List <string> { "st1" } }, Platforms = { { Helpers.ImageInfoHelper.CreatePlatform( repo1Image1DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 50, DateTimeKind.Utc), digest: "def", simpleTags: new List <string> { "t1" }) }, { Helpers.ImageInfoHelper.CreatePlatform( repo1Image2DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 56, DateTimeKind.Utc), digest: "ghi", simpleTags: new List <string> { "t2" }) } }, ProductVersion = "1.0.2", } } }, new RepoData { Repo = "r2", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform( repo2Image2DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 58, DateTimeKind.Utc), digest: "jkl", simpleTags: new List <string> { "t3" }) }, ProductVersion = "2.0.5" } } } } }; string expectedData = @"""def"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""t1"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""ghi"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os2/Dockerfile"",""r1"",""2020-04-20 21:56:56"" ""t2"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os2/Dockerfile"",""r1"",""2020-04-20 21:56:56"" ""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""2.0.5"",""2.0/sdk/os/Dockerfile"",""r2"",""2020-04-20 21:56:58"" ""t3"",""amd64"",""Linux"",""Ubuntu 20.04"",""2.0.5"",""2.0/sdk/os/Dockerfile"",""r2"",""2020-04-20 21:56:58"""; expectedData = expectedData.NormalizeLineEndings(Environment.NewLine).Trim(); string imageInfoPath = Path.Combine(tempFolderContext.Path, "image-info.json"); File.WriteAllText(imageInfoPath, JsonHelper.SerializeObject(srcImageArtifactDetails)); string ingestedData = null; Mock <IKustoClient> kustoClientMock = new Mock <IKustoClient>(); kustoClientMock .Setup(o => o.IngestFromCsvStreamAsync(It.IsAny <Stream>(), It.IsAny <IngestKustoImageInfoOptions>())) .Callback <Stream, IngestKustoImageInfoOptions>((s, o) => { StreamReader reader = new StreamReader(s); ingestedData = reader.ReadToEnd(); }); IngestKustoImageInfoCommand command = new IngestKustoImageInfoCommand( Mock.Of <ILoggerService>(), kustoClientMock.Object); command.Options.ImageInfoPath = imageInfoPath; command.Options.Manifest = manifestPath; command.LoadManifest(); await command.ExecuteAsync(); _outputHelper.WriteLine($"Expected Data: {Environment.NewLine}{expectedData}"); _outputHelper.WriteLine($"Actual Data: {Environment.NewLine}{ingestedData}"); kustoClientMock.Verify(o => o.IngestFromCsvStreamAsync(It.IsAny <Stream>(), It.IsAny <IngestKustoImageInfoOptions>())); Assert.Equal(expectedData, ingestedData); }
public void DuplicatedPlatform() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); const string SourceRepoUrl = "https://www.github.com/dotnet/dotnet-docker"; const string RepoName = "repo"; const string SourceBranch = "branch"; // Create MCR tags metadata template file StringBuilder tagsMetadataTemplateBuilder = new StringBuilder(); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlRepo:{RepoName})"); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlTagGroup:concreteTagA)"); string tagsMetadataTemplatePath = Path.Combine(tempFolderContext.Path, "tags.yaml"); File.WriteAllText(tagsMetadataTemplatePath, tagsMetadataTemplateBuilder.ToString()); string emptyFileName = "emptyFile.md"; string emptyFilePath = Path.Combine(tempFolderContext.Path, emptyFileName); File.WriteAllText(emptyFilePath, string.Empty); // Create manifest Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo(RepoName, new Image[] { ManifestHelper.CreateImage( new Platform[] { ManifestHelper.CreatePlatform( DockerfileHelper.CreateDockerfile($"1.0/{RepoName}/os", tempFolderContext), new string[] { "concreteTagZ", "concreteTagA" }) }, sharedTags: new Dictionary <string, Tag> { { "shared1", new Tag() }, { "latest", new Tag() }, }), ManifestHelper.CreateImage( new Platform[] { ManifestHelper.CreatePlatform( DockerfileHelper.CreateDockerfile($"1.0/{RepoName}/os", tempFolderContext), Array.Empty <string>()) }, sharedTags: new Dictionary <string, Tag> { { "shared2", new Tag() } }) }, readme: emptyFileName, readmeTemplate: emptyFileName, mcrTagsMetadataTemplate: Path.GetFileName(tagsMetadataTemplatePath)) ); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); // Load manifest IManifestOptionsInfo manifestOptions = ManifestHelper.GetManifestOptions(manifestPath); ManifestInfo manifestInfo = ManifestInfo.Load(manifestOptions); RepoInfo repo = manifestInfo.AllRepos.First(); Mock <IGitService> gitServiceMock = new Mock <IGitService>(); // Execute generator string result = McrTagsMetadataGenerator.Execute( gitServiceMock.Object, manifestInfo, repo, SourceRepoUrl, SourceBranch); TagsMetadata tagsMetadata = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build() .Deserialize <TagsMetadata>(result); // Verify the output only contains the platform with the documented tag Assert.Single(tagsMetadata.Repos[0].TagGroups); Assert.Equal( $"{SourceRepoUrl}/blob/{SourceBranch}/1.0/{RepoName}/os/Dockerfile", tagsMetadata.Repos[0].TagGroups[0].Dockerfile); List <string> expectedTags = new List <string> { "concreteTagZ", "concreteTagA", "shared2", "shared1", "latest" }; Assert.Equal(expectedTags, tagsMetadata.Repos[0].TagGroups[0].Tags); }
public void CrossReferencedDockerfileFromMultipleRepos_ImageGraph(MatrixType matrixType) { TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = matrixType; command.Options.ProductVersionComponents = 2; Manifest manifest = CreateManifest( CreateRepo("core/runtime-deps", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("3.1/runtime-deps/os", tempFolderContext), new string[] { "tag" }) }, productVersion: "3.1")), CreateRepo("core/runtime", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("3.1/runtime/os", tempFolderContext, "core/runtime-deps:tag"), new string[] { "tag" }) }, productVersion: "3.1")), CreateRepo("runtime-deps", CreateImage( new Platform[] { CreatePlatform( "3.1/runtime-deps/os/Dockerfile", new string[] { "tag" }) }, productVersion: "5.0")), CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("5.0/runtime/os", tempFolderContext, "runtime-deps:tag"), new string[] { "tag" }) }, productVersion: "5.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); if (matrixType == MatrixType.PlatformDependencyGraph) { Assert.Single(matrixInfo.Legs); Assert.Equal("3.1-runtime-deps-os-Dockerfile-graph", matrixInfo.Legs[0].Name); string imageBuilderPaths = matrixInfo.Legs[0].Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal($"--path 3.1/runtime-deps/os/Dockerfile --path 3.1/runtime/os/Dockerfile --path 5.0/runtime/os/Dockerfile", imageBuilderPaths); } else { Assert.Equal(2, matrixInfo.Legs.Count); Assert.Equal("3.1-focal-core-runtime-deps", matrixInfo.Legs[0].Name); string imageBuilderPaths = matrixInfo.Legs[0].Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal($"--path 3.1/runtime-deps/os/Dockerfile --path 3.1/runtime/os/Dockerfile", imageBuilderPaths); Assert.Equal("5.0-focal-runtime-deps", matrixInfo.Legs[1].Name); imageBuilderPaths = matrixInfo.Legs[1].Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal($"--path 3.1/runtime-deps/os/Dockerfile --path 5.0/runtime/os/Dockerfile", imageBuilderPaths); } }
public void PlatformVersionedOs_Cached(bool isRuntimeCached, bool isAspnetCached, bool isSdkCached, string expectedPaths) { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformVersionedOs; command.Options.ImageInfoPath = Path.Combine(tempFolderContext.Path, "imageinfo.json"); command.Options.ProductVersionComponents = 2; string runtimeDockerfilePath; string aspnetDockerfilePath; string sdkDockerfilePath; Manifest manifest = CreateManifest( CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform( runtimeDockerfilePath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext), new string[] { "tag" }) }, productVersion: "1.0")), CreateRepo("aspnet", CreateImage( new Platform[] { CreatePlatform( aspnetDockerfilePath = DockerfileHelper.CreateDockerfile("1.0/aspnet/os", tempFolderContext, "runtime:tag"), new string[] { "tag" }) }, productVersion: "1.0")), CreateRepo("sdk", CreateImage( new Platform[] { CreatePlatform( sdkDockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os", tempFolderContext, "aspnet:tag"), new string[] { "tag" }) }, productVersion: "1.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "runtime", Images = { new ImageData { ProductVersion = "1.0", Platforms = { CreateSimplePlatformData(runtimeDockerfilePath, isCached: isRuntimeCached) } } } }, new RepoData { Repo = "aspnet", Images = { new ImageData { ProductVersion = "1.0", Platforms = { CreateSimplePlatformData(aspnetDockerfilePath, isCached: isAspnetCached) } } } }, new RepoData { Repo = "sdk", Images = { new ImageData { ProductVersion = "1.0", Platforms = { CreateSimplePlatformData(sdkDockerfilePath, isCached: isSdkCached) } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonHelper.SerializeObject(imageArtifactDetails)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); if (isRuntimeCached && isAspnetCached && isSdkCached) { Assert.Empty(matrixInfos); } else { Assert.Single(matrixInfos); Assert.Single(matrixInfos.First().Legs); BuildLegInfo buildLeg = matrixInfos.First().Legs.First(); string imageBuilderPaths = buildLeg.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal(expectedPaths, imageBuilderPaths); } }
public void GenerateBuildMatrixCommand_MultiBuildLegGroups() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); const string customBuildLegGroup1 = "custom1"; const string customBuildLegGroup2 = "custom2"; GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformVersionedOs; command.Options.ProductVersionComponents = 2; command.Options.CustomBuildLegGroups = new string[] { customBuildLegGroup1, customBuildLegGroup2 }; Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo1/os", tempFolderContext), new string[] { "tag" }, osVersion: "bionic") }, productVersion: "1.0")), CreateRepo("repo2", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo2/os", tempFolderContext), new string[] { "tag" }, osVersion: "focal", customBuildLegGroups: new CustomBuildLegGroup[] { new CustomBuildLegGroup { Name = customBuildLegGroup1, Type = CustomBuildLegDependencyType.Supplemental, Dependencies = new string[] { "repo1:tag" } } }) }, productVersion: "1.0")), CreateRepo("repo3", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo3/os", tempFolderContext), new string[] { "tag" }, osVersion: "buster") }, productVersion: "1.0")), CreateRepo("repo4", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo4/os", tempFolderContext), new string[] { "tag" }, osVersion: "bullseye", customBuildLegGroups: new CustomBuildLegGroup[] { new CustomBuildLegGroup { Name = customBuildLegGroup1, Type = CustomBuildLegDependencyType.Integral, Dependencies = new string[] { "repo3:tag" } } }) }, productVersion: "1.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); Assert.Equal(3, matrixInfo.Legs.Count()); BuildLegInfo leg = matrixInfo.Legs.First(); string imageBuilderPaths = leg.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal( "--path 1.0/repo1/os/Dockerfile", imageBuilderPaths); leg = matrixInfo.Legs.ElementAt(1); imageBuilderPaths = leg.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal( "--path 1.0/repo2/os/Dockerfile --path 1.0/repo1/os/Dockerfile", imageBuilderPaths); leg = matrixInfo.Legs.ElementAt(2); imageBuilderPaths = leg.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal( "--path 1.0/repo3/os/Dockerfile --path 1.0/repo4/os/Dockerfile", imageBuilderPaths); }
public async Task PublishImageInfoCommand_RemoveOutOfDateContent() { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext); string repo2Image2DockerfilePath = DockerfileHelper.CreateDockerfile("2.0/runtime/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform(repo1Image1DockerfilePath, new string[0]) }, productVersion: "1.0")), CreateRepo("repo2", CreateImage( new Platform[] { CreatePlatform(repo2Image2DockerfilePath, new string[0]) }, productVersion: "2.0")) ); manifest.Registry = "mcr.microsoft.com"; RepoData repo2; ImageArtifactDetails srcImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath) }, ProductVersion = "1.0" } } }, { repo2 = new RepoData { Repo = "repo2", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo2Image2DockerfilePath) }, ProductVersion = "2.0" } } } } } }; string file = Path.Combine(tempFolderContext.Path, "image-info.json"); File.WriteAllText(file, JsonHelper.SerializeObject(srcImageArtifactDetails)); ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath) }, ProductVersion = "1.0" }, new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/runtime2/os", tempFolderContext)) }, ProductVersion = "1.0" } } }, new RepoData { Repo = "repo4" } } }; GitOptions gitOptions = new GitOptions { AuthToken = "token", Repo = "repo", Owner = "owner", Path = "imageinfo.json", Branch = "branch", Email = "*****@*****.**", Username = "******" }; AzdoOptions azdoOptions = new AzdoOptions { AccessToken = "azdo-token", Branch = "testBranch", Repo = "testRepo", Organization = "azdo-org", Project = "azdo-project", Path = "imageinfo.json" }; Mock <IRepository> repositoryMock = GetRepositoryMock(); Mock <IGitService> gitServiceMock = GetGitServiceMock(repositoryMock.Object, gitOptions.Path, targetImageArtifactDetails); PublishImageInfoCommand command = new PublishImageInfoCommand(gitServiceMock.Object, Mock.Of <ILoggerService>()); command.Options.ImageInfoPath = file; command.Options.GitOptions = gitOptions; command.Options.AzdoOptions = azdoOptions; command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); ImageArtifactDetails expectedImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath) }, ProductVersion = "1.0" } } }, repo2 } }; VerifyMocks(repositoryMock); } }
public async Task PublishImageInfoCommand_ReplaceTags() { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext); string repo2Image2DockerfilePath = DockerfileHelper.CreateDockerfile("2.0/runtime/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( CreatePlatform(repo1Image1DockerfilePath, new string[0]))), CreateRepo("repo2", CreateImage( CreatePlatform(repo2Image2DockerfilePath, new string[0]))) ); RepoData repo2; ImageArtifactDetails srcImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "newtag" }) } } } }, { repo2 = new RepoData { Repo = "repo2", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo2Image2DockerfilePath, simpleTags: new List <string> { "tag1" }) } } } } } } }; string file = Path.Combine(tempFolderContext.Path, "image-info.json"); File.WriteAllText(file, JsonHelper.SerializeObject(srcImageArtifactDetails)); ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "oldtag" }) } } } } } }; Mock <IGitHubClient> gitHubClientMock = GetGitHubClientMock(); Mock <IGitHubClientFactory> gitHubClientFactoryMock = new Mock <IGitHubClientFactory>(); gitHubClientFactoryMock .Setup(o => o.GetClient(It.IsAny <GitHubAuth>(), false)) .Returns(gitHubClientMock.Object); GitOptions gitOptions = new GitOptions { AuthToken = "token", Repo = "testRepo", Branch = "testBranch", Path = "imageinfo.json" }; PublishImageInfoCommand command = new PublishImageInfoCommand( gitHubClientFactoryMock.Object, Mock.Of <ILoggerService>(), CreateHttpClientFactory(gitOptions, targetImageArtifactDetails)); command.Options.ImageInfoPath = file; command.Options.GitOptions = gitOptions; command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); ImageArtifactDetails expectedImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "newtag" }) } } } }, repo2 } }; Func <GitObject[], bool> verifyGitObjects = (gitObjects) => { if (gitObjects.Length != 1) { return(false); } return(gitObjects[0].Content.Trim() == JsonHelper.SerializeObject(expectedImageArtifactDetails).Trim()); }; gitHubClientMock.Verify( o => o.PostTreeAsync(It.IsAny <GitHubProject>(), It.IsAny <string>(), It.Is <GitObject[]>(gitObjects => verifyGitObjects(gitObjects)))); } }
public async Task ExcludeProductFamilyReadme() { Mock <IGitHubClient> gitHubClientMock = new(); gitHubClientMock .Setup(o => o.GetReferenceAsync(It.IsAny <GitHubProject>(), It.IsAny <string>())) .ReturnsAsync(new GitReference { Object = new GitReferenceObject() }); gitHubClientMock .Setup(o => o.PostTreeAsync(It.IsAny <GitHubProject>(), It.IsAny <string>(), It.IsAny <GitObject[]>())) .ReturnsAsync(new GitTree()); gitHubClientMock .Setup(o => o.PostCommitAsync(It.IsAny <GitHubProject>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string[]>())) .ReturnsAsync(new GitCommit()); Mock <IGitHubClientFactory> gitHubClientFactoryMock = new(); gitHubClientFactoryMock .Setup(o => o.GetClient(It.IsAny <GitHubAuth>(), false)) .Returns(gitHubClientMock.Object); PublishMcrDocsCommand command = new(Mock.Of <IGitService>(), gitHubClientFactoryMock.Object, Mock.Of <ILoggerService>()); using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); DockerfileHelper.CreateFile(ProductFamilyReadmePath, tempFolderContext, DefaultReadme); DockerfileHelper.CreateFile(RepoReadmePath, tempFolderContext, DefaultReadme); DockerfileHelper.CreateFile(AboutRepoTemplatePath, tempFolderContext, AboutRepoTemplate); DockerfileHelper.CreateFile(ReadmeTemplatePath, tempFolderContext, ReadmeTemplate); // Create MCR tags metadata template file StringBuilder tagsMetadataTemplateBuilder = new(); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlRepo:repo)"); tagsMetadataTemplateBuilder.Append($"$(McrTagsYmlTagGroup:tag)"); string tagsMetadataTemplatePath = Path.Combine(tempFolderContext.Path, TagsYamlPath); File.WriteAllText(tagsMetadataTemplatePath, tagsMetadataTemplateBuilder.ToString()); Repo repo; Manifest manifest = CreateManifest( repo = CreateRepo("dotnet/repo", new Image[] { CreateImage( CreatePlatform(CreateDockerfile("1.0/runtime/linux", tempFolderContext), new string[] { "tag" })) }, RepoReadmePath, ReadmeTemplatePath, Path.GetFileName(tagsMetadataTemplatePath))); manifest.Registry = "mcr.microsoft.com"; manifest.Readme = new(ProductFamilyReadmePath, ReadmeTemplatePath); repo.Id = "repo"; string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); command.Options.Manifest = manifestPath; command.Options.ExcludeProductFamilyReadme = true; command.LoadManifest(); await command.ExecuteAsync(); // Verify published file list does not contain ProductFamilyReadmePath gitHubClientMock .Verify(o => o.PostTreeAsync(It.IsAny <GitHubProject>(), It.IsAny <string>(), It.Is <GitObject[]>(objs => objs.Length == 2 && Path.GetFileName(objs[0].Path) == RepoReadmePath && Path.GetFileName(objs[1].Path) == TagsYamlPath))); }
public async Task PublishImageInfoCommand_ReplaceContent() { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext); string repo2Image2DockerfilePath = DockerfileHelper.CreateDockerfile("2.0/runtime/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform(repo1Image1DockerfilePath, new string[] { "tag1" }) }, productVersion: "1.0")), CreateRepo("repo2", CreateImage( new Platform[] { CreatePlatform(repo2Image2DockerfilePath, new string[] { "tag1" }) }, productVersion: "2.0")) ); RepoData repo2; ImageArtifactDetails srcImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "newtag" }) }, ProductVersion = "1.0", Manifest = new ManifestData { SyndicatedDigests = new List <string> { "newdigest1", "newdigest2" } } } } }, { repo2 = new RepoData { Repo = "repo2", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo2Image2DockerfilePath, simpleTags: new List <string> { "tag1" }) }, ProductVersion = "2.0" } } } } } }; string file = Path.Combine(tempFolderContext.Path, "image-info.json"); File.WriteAllText(file, JsonHelper.SerializeObject(srcImageArtifactDetails)); ImageArtifactDetails targetImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "oldtag" }) }, ProductVersion = "1.0", Manifest = new ManifestData { SyndicatedDigests = new List <string> { "olddigest1", "olddigest2" } } } } } } }; GitOptions gitOptions = new GitOptions { AuthToken = "token", Repo = "PublishImageInfoCommand_ReplaceContent", Branch = "testBranch", Path = "imageinfo.json", Email = "*****@*****.**", Username = "******" }; AzdoOptions azdoOptions = new AzdoOptions { AccessToken = "azdo-token", AzdoBranch = "testBranch", AzdoRepo = "testRepo", Organization = "azdo-org", Project = "azdo-project", AzdoPath = "imageinfo.json" }; Mock <IRepository> repositoryMock = GetRepositoryMock(); Mock <IGitService> gitServiceMock = GetGitServiceMock(repositoryMock.Object, gitOptions.Path, targetImageArtifactDetails); string actualImageArtifactDetailsContents = null; gitServiceMock .Setup(o => o.Stage(It.IsAny <IRepository>(), It.IsAny <string>())) .Callback((IRepository repo, string path) => { actualImageArtifactDetailsContents = File.ReadAllText(path); }); PublishImageInfoCommand command = new PublishImageInfoCommand(gitServiceMock.Object, Mock.Of <ILoggerService>()); command.Options.ImageInfoPath = file; command.Options.GitOptions = gitOptions; command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); ImageArtifactDetails expectedImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform(repo1Image1DockerfilePath, simpleTags: new List <string> { "newtag" }) }, ProductVersion = "1.0", Manifest = new ManifestData { SyndicatedDigests = new List <string> { "newdigest1", "newdigest2" } } } } }, repo2 } }; Assert.Equal(JsonHelper.SerializeObject(expectedImageArtifactDetails), actualImageArtifactDetailsContents.Trim()); VerifyMocks(repositoryMock); } }
public async Task SyndicatedTag() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform(repo1Image1DockerfilePath, new string[] { "t1", "t2", "t3" }) }, productVersion: "1.0.5")) ); const string syndicatedRepository = "repo2"; Platform platform = manifest.Repos.First().Images.First().Platforms.First(); platform.Tags["t1"].Syndication = new TagSyndication { Repo = syndicatedRepository }; platform.Tags["t2"].Syndication = new TagSyndication { Repo = syndicatedRepository, DestinationTags = new string[] { "t2a", "t2b" } }; string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); ImageArtifactDetails srcImageArtifactDetails = new() { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform( repo1Image1DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 58, DateTimeKind.Utc), digest: "jkl", simpleTags: new List <string> { "t1", "t2", "t3" }, layers: new List <string> { "zxc" }) }, ProductVersion = "1.0.5" } } } } }; string expectedImageData = @"""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo1"",""2020-04-20 21:56:58"" ""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo2"",""2020-04-20 21:56:58"" ""t1"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo1"",""2020-04-20 21:56:58"" ""t1"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo2"",""2020-04-20 21:56:58"" ""t2"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo1"",""2020-04-20 21:56:58"" ""t2a"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo2"",""2020-04-20 21:56:58"" ""t2b"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo2"",""2020-04-20 21:56:58"" ""t3"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo1"",""2020-04-20 21:56:58"""; expectedImageData = expectedImageData.NormalizeLineEndings(Environment.NewLine).Trim(); string expectedLayerData = @"""zxc"",""0"",""1"",""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.5"",""1.0/sdk/os/Dockerfile"",""repo1"",""2020-04-20 21:56:58"""; expectedLayerData = expectedLayerData.NormalizeLineEndings(Environment.NewLine).Trim(); await ValidateExecuteAsync(tempFolderContext, manifestPath, srcImageArtifactDetails, expectedImageData, expectedLayerData); }
public async Task CopyAcrImagesCommand_RuntimeDepsSharing() { const string subscriptionId = "my subscription"; using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); Mock <IRegistriesOperations> registriesOperationsMock = AzureHelper.CreateRegistriesOperationsMock(); IAzure azure = AzureHelper.CreateAzureMock(registriesOperationsMock); Mock <IAzureManagementFactory> azureManagementFactoryMock = AzureHelper.CreateAzureManagementFactoryMock(subscriptionId, azure); Mock <IEnvironmentService> environmentServiceMock = new Mock <IEnvironmentService>(); CopyAcrImagesCommand command = new CopyAcrImagesCommand(azureManagementFactoryMock.Object, Mock.Of <ILoggerService>()); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.Subscription = subscriptionId; command.Options.ResourceGroup = "my resource group"; command.Options.SourceRepoPrefix = command.Options.RepoPrefix = "test/"; command.Options.ImageInfoPath = "image-info.json"; string dockerfileRelativePath = DockerfileHelper.CreateDockerfile("3.1/runtime-deps/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("runtime-deps", CreateImage( new Platform[] { CreatePlatform(dockerfileRelativePath, new string[] { "3.1" }, osVersion: "focal") }, productVersion: "3.1"), CreateImage( new Platform[] { CreatePlatform(dockerfileRelativePath, new string[] { "5.0" }, osVersion: "focal") }, productVersion: "5.0")) ); manifest.Registry = "mcr.microsoft.com"; File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); RepoData runtimeRepo; ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { { runtimeRepo = new RepoData { Repo = "runtime-deps", Images = { new ImageData { Platforms = { CreatePlatform( PathHelper.NormalizePath(dockerfileRelativePath), simpleTags: new List <string> { "3.1" }, osVersion: "focal") }, ProductVersion = "3.1" }, new ImageData { Platforms = { CreatePlatform( PathHelper.NormalizePath(dockerfileRelativePath), simpleTags: new List <string> { "5.0" }, osVersion: "focal") }, ProductVersion = "5.0" } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonConvert.SerializeObject(imageArtifactDetails)); command.LoadManifest(); await command.ExecuteAsync(); List <string> expectedTags = new List <string> { $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:3.1", $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:5.0" }; foreach (string expectedTag in expectedTags) { registriesOperationsMock .Verify(o => o.ImportImageWithHttpMessagesAsync( command.Options.ResourceGroup, manifest.Registry, It.Is <ImportImageParametersInner>(parameters => VerifyImportImageParameters(parameters, new List <string> { expectedTag })), It.IsAny <Dictionary <string, List <string> > >(), It.IsAny <CancellationToken>())); } }
public void GenerateBuildMatrixCommand_CustomBuildLegGroupingParentGraph() { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { const string customBuildLegGrouping = "custom"; GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformVersionedOs; command.Options.ProductVersionComponents = 2; command.Options.CustomBuildLegGrouping = customBuildLegGrouping; string dockerfileRuntimeDepsFullPath = DockerfileHelper.CreateDockerfile("1.0/runtime-deps/os", tempFolderContext); string dockerfileRuntimePath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext, "runtime-deps:tag"); string dockerfileRuntime2FullPath = DockerfileHelper.CreateDockerfile("2.0/runtime/os2", tempFolderContext); string dockerfileSdk2FullPath = DockerfileHelper.CreateDockerfile("2.0/sdk/os2", tempFolderContext, "runtime2:tag"); Manifest manifest = CreateManifest( CreateRepo("runtime-deps", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntimeDepsFullPath, new string[] { "tag" }) }, productVersion: "1.0")), CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntimePath, new string[] { "runtime" }, customBuildLegGroupings: new CustomBuildLegGrouping[] { new CustomBuildLegGrouping { Name = customBuildLegGrouping, Dependencies = new string[] { "sdk2:tag" } } }) }, productVersion: "1.0")), CreateRepo("runtime2", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntime2FullPath, new string[] { "tag" }, osVersion: "buster-slim") }, productVersion: "2.0")), CreateRepo("sdk2", CreateImage( new Platform[] { CreatePlatform(dockerfileSdk2FullPath, new string[] { "tag" }, osVersion: "buster") }, productVersion: "2.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); BuildLegInfo leg_1_0 = matrixInfo.Legs.First(); string imageBuilderPaths = leg_1_0.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal("--path 1.0/runtime-deps/os/Dockerfile --path 1.0/runtime/os/Dockerfile --path 2.0/sdk/os2/Dockerfile --path 2.0/runtime/os2/Dockerfile", imageBuilderPaths); string osVersions = leg_1_0.Variables.First(variable => variable.Name == "osVersions").Value; Assert.Equal("--os-version disco --os-version buster --os-version buster-slim", osVersions); BuildLegInfo leg_2_0 = matrixInfo.Legs.ElementAt(1); imageBuilderPaths = leg_2_0.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal("--path 2.0/runtime/os2/Dockerfile --path 2.0/sdk/os2/Dockerfile", imageBuilderPaths); osVersions = leg_2_0.Variables.First(variable => variable.Name == "osVersions").Value; Assert.Equal("--os-version buster-slim --os-version buster", osVersions); } }
public void GenerateBuildMatrixCommand_ParentGraphOutsidePlatformGroup() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformVersionedOs; command.Options.ProductVersionComponents = 2; string dockerfileRuntimeFullPath = DockerfileHelper.CreateDockerfile("1.0/runtime/os", tempFolderContext); string dockerfileRuntime2FullPath = DockerfileHelper.CreateDockerfile("1.0/runtime2/os", tempFolderContext, "sdk3:tag"); string dockerfileRuntime3FullPath = DockerfileHelper.CreateDockerfile("1.0/runtime3/os2", tempFolderContext); string dockerfileSdk3FullPath = DockerfileHelper.CreateDockerfile("1.0/sdk3/os2", tempFolderContext, "runtime3:tag"); Manifest manifest = CreateManifest( // Define a Dockerfile that has the same OS version and product version as runtime2 but no actual dependency to // ensure it gets its own matrix leg. CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntimeFullPath, new string[] { "tag" }, osVersion: "buster") }, productVersion: "1.0")), CreateRepo("runtime2", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntime2FullPath, new string[] { "runtime" }, osVersion: "bullseye") }, productVersion: "1.0")), CreateRepo("runtime3", CreateImage( new Platform[] { CreatePlatform(dockerfileRuntime3FullPath, new string[] { "tag" }, osVersion: "alpine3.12") }, productVersion: "1.0")), CreateRepo("sdk3", CreateImage( new Platform[] { CreatePlatform(dockerfileSdk3FullPath, new string[] { "tag" }, osVersion: "alpine3.12") }, productVersion: "1.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); Assert.Equal(2, matrixInfo.Legs.Count); BuildLegInfo leg_1_0 = matrixInfo.Legs.First(); string imageBuilderPaths = leg_1_0.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal("--path 1.0/runtime/os/Dockerfile", imageBuilderPaths); BuildLegInfo leg_2_0 = matrixInfo.Legs.ElementAt(1); imageBuilderPaths = leg_2_0.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal("--path 1.0/runtime2/os/Dockerfile --path 1.0/sdk3/os2/Dockerfile --path 1.0/runtime3/os2/Dockerfile", imageBuilderPaths); }
public void GenerateBuildMatrixCommand_ServerCoreAndNanoServerDependency() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); const string customBuildLegGrouping = "custom"; GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformDependencyGraph; command.Options.ProductVersionComponents = 2; command.Options.CustomBuildLegGrouping = customBuildLegGrouping; Manifest manifest = CreateManifest( CreateRepo("runtime", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/runtime/nanoserver-1909", tempFolderContext), new string[] { "nanoserver-1909" }, os: OS.Windows, osVersion: "nanoserver-1909") }, productVersion: "1.0"), CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/runtime/windowsservercore-1909", tempFolderContext), new string[] { "windowsservercore-1909" }, os: OS.Windows, osVersion: "windowsservercore-1909") }, productVersion: "1.0")), CreateRepo("aspnet", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/aspnet/nanoserver-1909", tempFolderContext, "runtime:nanoserver-1909"), new string[] { "nanoserver-1909" }, os: OS.Windows, osVersion: "nanoserver-1909") }, productVersion: "1.0"), CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/aspnet/windowsservercore-1909", tempFolderContext, "runtime:windowsservercore-1909"), new string[] { "windowsservercore-1909" }, os: OS.Windows, osVersion: "windowsservercore-1909", customBuildLegGroupings: new CustomBuildLegGrouping[] { new CustomBuildLegGrouping { Name = customBuildLegGrouping, Dependencies = new string[] { "aspnet:nanoserver-1909" } } }) }, productVersion: "1.0")) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); IEnumerable <BuildMatrixInfo> matrixInfos = command.GenerateMatrixInfo(); Assert.Single(matrixInfos); BuildMatrixInfo matrixInfo = matrixInfos.First(); BuildLegInfo leg = matrixInfo.Legs.First(); string imageBuilderPaths = leg.Variables.First(variable => variable.Name == "imageBuilderPaths").Value; Assert.Equal( "--path 1.0/runtime/nanoserver-1909/Dockerfile --path 1.0/aspnet/nanoserver-1909/Dockerfile --path 1.0/runtime/windowsservercore-1909/Dockerfile --path 1.0/aspnet/windowsservercore-1909/Dockerfile", imageBuilderPaths); string osVersions = leg.Variables.First(variable => variable.Name == "osVersions").Value; Assert.Equal( "--os-version nanoserver-1909 --os-version windowsservercore-1909", osVersions); }
public async Task IngestKustoImageInfoCommand_MultipleRepos() { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); string repo1Image1DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os", tempFolderContext); string repo1Image2DockerfilePath = DockerfileHelper.CreateDockerfile("1.0/sdk/os2", tempFolderContext); string repo2Image2DockerfilePath = DockerfileHelper.CreateDockerfile("2.0/sdk/os", tempFolderContext); Manifest manifest = CreateManifest( CreateRepo("r1", CreateImage( new Platform[] { CreatePlatform(repo1Image1DockerfilePath, new string[] { "t1" }), CreatePlatform(repo1Image2DockerfilePath, new string[] { "t2" }) }, productVersion: "1.0.2", sharedTags: new Dictionary <string, Tag> { { "st1", new Tag() } })), CreateRepo("r2", CreateImage( new Platform[] { CreatePlatform(repo2Image2DockerfilePath, new string[] { "t3" }) }, productVersion: "2.0.5")) ); string manifestPath = Path.Combine(tempFolderContext.Path, "manifest.json"); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest)); ImageArtifactDetails srcImageArtifactDetails = new() { Repos = { new RepoData { Repo = "r1", Images = { new ImageData { Manifest = new ManifestData { Created = new DateTime(2020, 4, 20, 21, 57, 00, DateTimeKind.Utc), Digest = "abc", SharedTags = new List <string> { "st1" } }, Platforms = { { Helpers.ImageInfoHelper.CreatePlatform( repo1Image1DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 50, DateTimeKind.Utc), digest: "def", simpleTags: new List <string> { "t1" }, layers: new List <string> { "qwe", "asd" }) }, { Helpers.ImageInfoHelper.CreatePlatform( repo1Image2DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 56, DateTimeKind.Utc), digest: "ghi", simpleTags: new List <string> { "t2" }, layers: new List <string> { "qwe" }) } }, ProductVersion = "1.0.2", } } }, new RepoData { Repo = "r2", Images = { new ImageData { Platforms = { Helpers.ImageInfoHelper.CreatePlatform( repo2Image2DockerfilePath, created: new DateTime(2020, 4, 20, 21, 56, 58, DateTimeKind.Utc), digest: "jkl", simpleTags: new List <string> { "t3" }, layers: new List <string> { "zxc" }) }, ProductVersion = "2.0.5" } } } } }; string expectedImageData = @"""def"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""t1"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""ghi"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os2/Dockerfile"",""r1"",""2020-04-20 21:56:56"" ""t2"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os2/Dockerfile"",""r1"",""2020-04-20 21:56:56"" ""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""2.0.5"",""2.0/sdk/os/Dockerfile"",""r2"",""2020-04-20 21:56:58"" ""t3"",""amd64"",""Linux"",""Ubuntu 20.04"",""2.0.5"",""2.0/sdk/os/Dockerfile"",""r2"",""2020-04-20 21:56:58"""; expectedImageData = expectedImageData.NormalizeLineEndings(Environment.NewLine).Trim(); string expectedLayerData = @"""qwe"",""0"",""2"",""def"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""asd"",""0"",""1"",""def"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os/Dockerfile"",""r1"",""2020-04-20 21:56:50"" ""qwe"",""0"",""1"",""ghi"",""amd64"",""Linux"",""Ubuntu 20.04"",""1.0.2"",""1.0/sdk/os2/Dockerfile"",""r1"",""2020-04-20 21:56:56"" ""zxc"",""0"",""1"",""jkl"",""amd64"",""Linux"",""Ubuntu 20.04"",""2.0.5"",""2.0/sdk/os/Dockerfile"",""r2"",""2020-04-20 21:56:58"""; expectedLayerData = expectedLayerData.NormalizeLineEndings(Environment.NewLine).Trim(); await ValidateExecuteAsync(tempFolderContext, manifestPath, srcImageArtifactDetails, expectedImageData, expectedLayerData); }