public void DockerfileUrl(string sourceRepoBranch) { using TempFolderContext tempFolderContext = TestHelper.UseTempFolder(); const string SourceRepoUrl = "https://www.github.com/dotnet/dotnet-docker"; const string RepoName = "repo"; const string TagName = "tag"; // Create Dockerfile string DockerfileDir = $"1.0/{RepoName}/os"; Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, DockerfileDir)); string dockerfileRelativePath = Path.Combine(DockerfileDir, "Dockerfile"); string dockerfileFullPath = PathHelper.NormalizePath(Path.Combine(tempFolderContext.Path, dockerfileRelativePath)); File.WriteAllText(dockerfileFullPath, "FROM base:tag"); // Create MCR tags metadata template file StringBuilder tagsMetadataTemplateBuilder = new StringBuilder(); tagsMetadataTemplateBuilder.AppendLine($"$(McrTagsYmlRepo:{RepoName})"); tagsMetadataTemplateBuilder.Append($"$(McrTagsYmlTagGroup:{TagName})"); string tagsMetadataTemplatePath = Path.Combine(tempFolderContext.Path, "tags.yaml"); File.WriteAllText(tagsMetadataTemplatePath, tagsMetadataTemplateBuilder.ToString()); // Create manifest Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo(RepoName, new Image[] { ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(dockerfileRelativePath, new string[] { TagName })) }, 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>(); const string DockerfileSha = "random_sha"; if (sourceRepoBranch == null) { gitServiceMock .Setup(o => o.GetCommitSha(dockerfileFullPath, true)) .Returns(DockerfileSha); } // Execute generator string result = McrTagsMetadataGenerator.Execute( gitServiceMock.Object, manifestInfo, repo, SourceRepoUrl, sourceRepoBranch); Models.Mcr.McrTagsMetadata tagsMetadata = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build() .Deserialize <Models.Mcr.McrTagsMetadata>(result); string branchOrSha = sourceRepoBranch ?? DockerfileSha; Assert.Equal($"{SourceRepoUrl}/blob/{branchOrSha}/{DockerfileDir}/Dockerfile", tagsMetadata.Repos[0].TagGroups[0].Dockerfile); }
public async Task SyndicatedTag() { string expectedManifest1 = @"image: mcr.microsoft.com/repo:sharedtag2 tags: [sharedtag1] manifests: - image: mcr.microsoft.com/repo:tag1 platform: architecture: amd64 os: linux - image: mcr.microsoft.com/repo:tag3 platform: architecture: amd64 os: linux "; string expectedManifest2 = @"image: mcr.microsoft.com/repo2:sharedtag2a tags: [sharedtag2b] manifests: - image: mcr.microsoft.com/repo2:tag2 platform: architecture: amd64 os: linux "; bool manifest1Found = false; bool manifest2Found = false; Mock <IManifestService> manifestToolService = new Mock <IManifestService>(); manifestToolService .Setup(o => o.PushFromSpec(It.IsAny <string>(), false)) .Callback((string manifestFile, bool isDryRun) => { string manifestContents = File.ReadAllText(manifestFile); if (manifestContents.NormalizeLineEndings(expectedManifest1) == expectedManifest1) { manifest1Found = true; } else if (manifestContents.NormalizeLineEndings(expectedManifest2) == expectedManifest2) { manifest2Found = true; } }); manifestToolService .Setup(o => o.GetManifestAsync(It.IsAny <string>(), It.IsAny <IRegistryCredentialsHost>(), false)) .ReturnsAsync(new ManifestQueryResult("digest", new JsonObject())); DateTime manifestCreatedDate = DateTime.UtcNow; IDateTimeService dateTimeService = Mock.Of <IDateTimeService>(o => o.UtcNow == manifestCreatedDate); PublishManifestCommand command = new PublishManifestCommand( manifestToolService.Object, Mock.Of <ILoggerService>(), dateTimeService); using TempFolderContext tempFolderContext = new TempFolderContext(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.ImageInfoPath = Path.Combine(tempFolderContext.Path, "image-info.json"); string dockerfile1 = CreateDockerfile("1.0/repo/os", tempFolderContext); string dockerfile2 = CreateDockerfile("1.0/repo/os2", tempFolderContext); ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile1, simpleTags: new List <string> { "tag1", "tag2" }) }, Manifest = new ManifestData { SharedTags = { "sharedtag1", "sharedtag2" } } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonHelper.SerializeObject(imageArtifactDetails)); const string syndicatedRepo2 = "repo2"; Platform platform1; Platform platform2; Manifest manifest = CreateManifest( CreateRepo("repo", CreateImage( new Platform[] { platform1 = CreatePlatform(dockerfile1, Array.Empty <string>()), platform2 = CreatePlatform(dockerfile2, Array.Empty <string>()) }, new Dictionary <string, Tag> { { "sharedtag2", new Tag { Syndication = new TagSyndication { Repo = syndicatedRepo2, DestinationTags = new string[] { "sharedtag2a", "sharedtag2b" } } } }, { "sharedtag1", new Tag() } })) ); manifest.Registry = "mcr.microsoft.com"; platform1.Tags = new Dictionary <string, Tag> { { "tag1", new Tag() }, { "tag2", new Tag { Syndication = new TagSyndication { Repo = syndicatedRepo2, DestinationTags = new string[] { "tag2" } } } }, }; platform2.Tags = new Dictionary <string, Tag> { { "tag3", new Tag() } }; File.WriteAllText(command.Options.Manifest, JsonHelper.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); Assert.True(manifest1Found); Assert.True(manifest2Found); manifestToolService .Verify(o => o.PushFromSpec(It.IsAny <string>(), false), Times.Exactly(2)); ImageArtifactDetails expectedImageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile1, simpleTags: new List <string> { "tag1", "tag2" }) }, Manifest = new ManifestData { Digest = "mcr.microsoft.com/repo@digest", Created = manifestCreatedDate, SyndicatedDigests = new List <string> { "mcr.microsoft.com/repo2@digest" }, SharedTags = { "sharedtag1", "sharedtag2" } } } } } } }; string expectedOutput = JsonHelper.SerializeObject(expectedImageArtifactDetails); string actualOutput = File.ReadAllText(command.Options.ImageInfoPath); Assert.Equal(expectedOutput, actualOutput); }
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 ImageInfoTagOutput() { Mock <IManifestService> manifestToolService = new Mock <IManifestService>(); manifestToolService .Setup(o => o.GetManifestAsync("repo1:sharedtag2", It.IsAny <IRegistryCredentialsHost>(), false)) .ReturnsAsync(new ManifestQueryResult("digest1", new JsonObject())); manifestToolService .Setup(o => o.GetManifestAsync("repo2:sharedtag3", It.IsAny <IRegistryCredentialsHost>(), false)) .ReturnsAsync(new ManifestQueryResult("digest2", new JsonObject())); DateTime manifestCreatedDate = DateTime.UtcNow; IDateTimeService dateTimeService = Mock.Of <IDateTimeService>(o => o.UtcNow == manifestCreatedDate); PublishManifestCommand command = new PublishManifestCommand( manifestToolService.Object, Mock.Of <ILoggerService>(), dateTimeService); using TempFolderContext tempFolderContext = new TempFolderContext(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.ImageInfoPath = Path.Combine(tempFolderContext.Path, "image-info.json"); string dockerfile1 = CreateDockerfile("1.0/repo1/os", tempFolderContext); string dockerfile2 = CreateDockerfile("1.0/repo2/os", tempFolderContext); string dockerfile3 = CreateDockerfile("1.0/repo3/os", tempFolderContext); const string digest1 = "sha256:123"; const string digest2 = "sha256:ABC"; const string digest3 = "sha256:DEF"; ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile1, digest: digest1, simpleTags: new List <string>{ "tag1" }), new PlatformData { } }, Manifest = new ManifestData { SharedTags = { "sharedtag1", "sharedtag2" } } } } }, new RepoData { Repo = "repo2", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile2, digest: digest2, simpleTags: new List <string>{ "tag2" }) }, Manifest = new ManifestData { SharedTags = { "sharedtag1", "sharedtag3" } } } } }, new RepoData { Repo = "repo3", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile3, digest: digest3, simpleTags: new List <string>{ "tag3" }) } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonHelper.SerializeObject(imageArtifactDetails)); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform(dockerfile1, new string[] { "tag1" }) }, new Dictionary <string, Tag> { { "sharedtag2", new Tag() }, { "sharedtag1", new Tag() } })), CreateRepo("repo2", CreateImage( new Platform[] { CreatePlatform(dockerfile2, new string[] { "tag2" }) }, new Dictionary <string, Tag> { { "sharedtag3", new Tag() }, { "sharedtag1", new Tag() } })), CreateRepo("repo3", CreateImage( new Platform[] { CreatePlatform(dockerfile3, new string[] { "tag3" }) })), CreateRepo("unpublishedrepo", CreateImage( new Platform[] { CreatePlatform( CreateDockerfile("1.0/unpublishedrepo/os", tempFolderContext), new string[] { "tag" }) }, new Dictionary <string, Tag> { { "sharedtag", new Tag() } })) ); File.WriteAllText(command.Options.Manifest, JsonHelper.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); string actualOutput = File.ReadAllText(command.Options.ImageInfoPath); ImageArtifactDetails actualImageArtifactDetails = JsonConvert.DeserializeObject <ImageArtifactDetails>(actualOutput); ImageArtifactDetails expectedImageArtifactDetails = new() { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { new PlatformData { Dockerfile = "1.0/repo1/os/Dockerfile", OsType = "Linux", OsVersion = "focal", Architecture = "amd64", Digest = digest1, SimpleTags = new List <string> { "tag1" } }, new PlatformData() }, Manifest = new ManifestData { Created = manifestCreatedDate, Digest = "repo1@digest1", SharedTags = { "sharedtag1", "sharedtag2" } } } } }, new RepoData { Repo = "repo2", Images = { new ImageData { Platforms = { new PlatformData { Dockerfile = "1.0/repo2/os/Dockerfile", OsType = "Linux", OsVersion = "focal", Architecture = "amd64", Digest = digest2, SimpleTags = new List <string> { "tag2" } } }, Manifest = new ManifestData { Created = manifestCreatedDate, Digest = "repo2@digest2", SharedTags = { "sharedtag1", "sharedtag3" } } } } }, new RepoData { Repo = "repo3", Images = { new ImageData { Platforms = { new PlatformData { Dockerfile = "1.0/repo3/os/Dockerfile", OsType = "Linux", OsVersion = "focal", Architecture = "amd64", Digest = digest3, SimpleTags = new List <string> { "tag3" } } } } } } } }; string expectedOutput = JsonHelper.SerializeObject(expectedImageArtifactDetails); Assert.Equal(expectedOutput, actualOutput); }
public async Task DuplicatePlatform() { string expectedManifest1 = @"image: mcr.microsoft.com/repo1:sharedtag2 tags: [sharedtag1] manifests: - image: mcr.microsoft.com/repo1:tag1 platform: architecture: amd64 os: linux "; string expectedManifest2 = @"image: mcr.microsoft.com/repo1:sharedtag3 manifests: - image: mcr.microsoft.com/repo1:tag1 platform: architecture: amd64 os: linux "; bool manifest1Found = false; bool manifest2Found = false; Mock <IManifestService> manifestToolService = new Mock <IManifestService>(); manifestToolService .Setup(o => o.PushFromSpec(It.IsAny <string>(), false)) .Callback((string manifestFile, bool isDryRun) => { string manifestContents = File.ReadAllText(manifestFile); if (manifestContents.NormalizeLineEndings(expectedManifest1) == expectedManifest1) { manifest1Found = true; } else if (manifestContents.NormalizeLineEndings(expectedManifest2) == expectedManifest2) { manifest2Found = true; } }); manifestToolService .Setup(o => o.GetManifestAsync(It.IsAny <string>(), It.IsAny <IRegistryCredentialsHost>(), false)) .ReturnsAsync(new ManifestQueryResult("digest", new JsonObject())); PublishManifestCommand command = new PublishManifestCommand( manifestToolService.Object, Mock.Of <ILoggerService>(), Mock.Of <IDateTimeService>()); using TempFolderContext tempFolderContext = new TempFolderContext(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.ImageInfoPath = Path.Combine(tempFolderContext.Path, "image-info.json"); string dockerfile = CreateDockerfile("1.0/repo1/os", tempFolderContext); ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { new RepoData { Repo = "repo1", Images = { new ImageData { Platforms = { CreatePlatform(dockerfile, simpleTags: new List <string> { "tag1", "tag2" }) }, Manifest = new ManifestData { SharedTags = { "sharedtag1", "sharedtag2" } } }, new ImageData { Platforms = { CreatePlatform(dockerfile) }, Manifest = new ManifestData { SharedTags = { "sharedtag3" } } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonHelper.SerializeObject(imageArtifactDetails)); Manifest manifest = CreateManifest( CreateRepo("repo1", CreateImage( new Platform[] { CreatePlatform(dockerfile, new string[] { "tag1", "tag2" }) }, new Dictionary <string, Tag> { { "sharedtag2", new Tag() }, { "sharedtag1", new Tag() } }), CreateImage( new Platform[] { CreatePlatform(dockerfile, Array.Empty <string>()) }, new Dictionary <string, Tag> { { "sharedtag3", new Tag() } })) ); manifest.Registry = "mcr.microsoft.com"; File.WriteAllText(command.Options.Manifest, JsonHelper.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); Assert.True(manifest1Found); Assert.True(manifest2Found); manifestToolService .Verify(o => o.PushFromSpec(It.IsAny <string>(), false), Times.Exactly(2)); }
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 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", 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", 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 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" }) }, productVersion: "1.0")), CreateRepo("repo2", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo2/os", tempFolderContext), new string[] { "tag" }, 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" }) }, productVersion: "1.0")), CreateRepo("repo4", CreateImage( new Platform[] { CreatePlatform( DockerfileHelper.CreateDockerfile("1.0/repo4/os", tempFolderContext), new string[] { "tag" }, 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 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: "buster") }, 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 customBuildLegGroup = "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.CustomBuildLegGroups = new string[] { customBuildLegGroup }; 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", customBuildLegGroups: new CustomBuildLegGroup[] { new CustomBuildLegGroup { Name = customBuildLegGroup, Type = CustomBuildLegDependencyType.Supplemental, 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 void GenerateBuildMatrixCommand_CustomBuildLegGroupingParentGraph(CustomBuildLegDependencyType dependencyType) { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { const string customBuildLegGroup = "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.CustomBuildLegGroups = new string[] { customBuildLegGroup }; 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" }, customBuildLegGroups: new CustomBuildLegGroup[] { new CustomBuildLegGroup { Name = customBuildLegGroup, Type = dependencyType, 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 focal --os-version buster --os-version buster-slim", osVersions); if (dependencyType == CustomBuildLegDependencyType.Integral) { Assert.Single(matrixInfo.Legs); } else { Assert.Equal(2, matrixInfo.Legs.Count); 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 async Task CopyAcrImagesCommand_CustomDockerfileName() { const string subscriptionId = "my subscription"; using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { Mock <IRegistriesOperations> registriesOperationsMock = CreateRegistriesOperationsMock(); IAzure azure = CreateAzureMock(registriesOperationsMock); Mock <IAzureManagementFactory> azureManagementFactoryMock = CreateAzureManagementFactoryMock(subscriptionId, azure); Mock <IEnvironmentService> environmentServiceMock = new Mock <IEnvironmentService>(); CopyAcrImagesCommand command = new CopyAcrImagesCommand( azureManagementFactoryMock.Object, environmentServiceMock.Object); 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"; const string runtimeRelativeDir = "1.0/runtime/os"; Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile.custom"); File.WriteAllText(Path.Combine(tempFolderContext.Path, dockerfileRelativePath), "FROM repo:tag"); Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo("runtime", ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(dockerfileRelativePath, new string[] { "runtime" }))) ); manifest.Registry = "mcr.microsoft.com"; File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); RepoData runtimeRepo; RepoData[] repos = new RepoData[] { runtimeRepo = new RepoData { Repo = "runtime", Images = new SortedDictionary <string, ImageData> { { PathHelper.NormalizePath(dockerfileRelativePath), new ImageData { SimpleTags = { "tag1", "tag2" } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonConvert.SerializeObject(repos)); command.LoadManifest(); await command.ExecuteAsync(); IList <string> expectedTags = runtimeRepo.Images.First().Value.SimpleTags .Select(tag => $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:{tag}") .ToList(); 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>())); } environmentServiceMock.Verify(o => o.Exit(It.IsAny <int>()), Times.Never); } }