public async Task BuildCommand_ImageInfoOutput_CustomDockerfile() { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { Mock <IDockerService> dockerServiceMock = new Mock <IDockerService>(); dockerServiceMock .SetupGet(o => o.Architecture) .Returns(Architecture.AMD64); BuildCommand command = new BuildCommand(dockerServiceMock.Object); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.ImageInfoOutputPath = Path.Combine(tempFolderContext.Path, "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" }))) ); File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); command.LoadManifest(); await command.ExecuteAsync(); RepoData[] repos = JsonConvert.DeserializeObject <RepoData[]>(File.ReadAllText(command.Options.ImageInfoOutputPath)); Assert.Equal(PathHelper.NormalizePath(dockerfileRelativePath), repos[0].Images.First().Key); } }
public void GenerateBuildMatrixCommand_PlatformDependencyGraph(string filterPaths, string expectedPaths) { using (TempFolderContext tempFolderContext = TestHelper.UseTempFolder()) { GenerateBuildMatrixCommand command = new GenerateBuildMatrixCommand(); command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); command.Options.MatrixType = MatrixType.PlatformDependencyGraph; if (filterPaths != null) { command.Options.FilterOptions.Paths = filterPaths.Replace("--path ", "").Split(" "); } const string runtimeDepsRelativeDir = "1.0/runtimedeps/os/amd64"; DirectoryInfo runtimeDepsDir = Directory.CreateDirectory( Path.Combine(tempFolderContext.Path, runtimeDepsRelativeDir)); string dockerfileRuntimeDepsFullPath = Path.Combine(runtimeDepsDir.FullName, "Dockerfile"); File.WriteAllText(dockerfileRuntimeDepsFullPath, "FROM base"); const string sdkRelativeDir = "1.0/sdk/os/amd64"; DirectoryInfo sdkDir = Directory.CreateDirectory( Path.Combine(tempFolderContext.Path, sdkRelativeDir)); string dockerfileSdkPath = Path.Combine(sdkDir.FullName, "Dockerfile"); File.WriteAllText(dockerfileSdkPath, "FROM runtime-deps:tag"); const string sampleRelativeDir = "1.0/sample/os/amd64"; DirectoryInfo sampleDir = Directory.CreateDirectory( Path.Combine(tempFolderContext.Path, sampleRelativeDir)); string dockerfileSamplePath = Path.Combine(sampleDir.FullName, "Dockerfile"); File.WriteAllText(dockerfileSamplePath, "FROM sdk:tag"); Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo("runtime-deps", ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(runtimeDepsRelativeDir, new string[] { "tag" }))), ManifestHelper.CreateRepo("sdk", ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(sdkRelativeDir, new string[] { "tag" }))), ManifestHelper.CreateRepo("sample", ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(sampleRelativeDir, new string[] { "tag" }))) ); 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(expectedPaths, imageBuilderPaths); } }
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 SyndicatedTags() { 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"; const string runtimeRelativeDir = "1.0/runtime/os"; Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile"); File.WriteAllText(Path.Combine(tempFolderContext.Path, dockerfileRelativePath), "FROM repo:tag"); Manifest manifest = ManifestHelper.CreateManifest( ManifestHelper.CreateRepo("runtime", ManifestHelper.CreateImage( ManifestHelper.CreatePlatform(dockerfileRelativePath, new string[] { "tag1", "tag2", "tag3" }))) ); manifest.Registry = "mcr.microsoft.com"; const string syndicatedRepo2 = "runtime2"; const string syndicatedRepo3 = "runtime3"; Platform platform = manifest.Repos.First().Images.First().Platforms.First(); platform.Tags["tag2"].Syndication = new TagSyndication { Repo = syndicatedRepo2, }; platform.Tags["tag3"].Syndication = new TagSyndication { Repo = syndicatedRepo3, DestinationTags = new string[] { "tag3a", "tag3b" } }; File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); RepoData runtimeRepo; ImageArtifactDetails imageArtifactDetails = new ImageArtifactDetails { Repos = { { runtimeRepo = new RepoData { Repo = "runtime", Images = { new ImageData { Platforms = { CreatePlatform( PathHelper.NormalizePath(dockerfileRelativePath), simpleTags: new List <string> { "tag1", "tag2", "tag3" }) } } } } } } }; File.WriteAllText(command.Options.ImageInfoPath, JsonConvert.SerializeObject(imageArtifactDetails)); command.LoadManifest(); await command.ExecuteAsync(); List <string> expectedTags = new List <string> { $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:tag1", $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:tag2", $"{command.Options.RepoPrefix}{runtimeRepo.Repo}:tag3", $"{command.Options.RepoPrefix}{syndicatedRepo2}:tag2", $"{command.Options.RepoPrefix}{syndicatedRepo3}:tag3a", $"{command.Options.RepoPrefix}{syndicatedRepo3}:tag3b" }; 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 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 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 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); } }