Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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);
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
                }
            }
        }
Beispiel #12
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);
            }
        }