Пример #1
0
        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);
        }
Пример #4
0
        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>()));
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
            }
        }