123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- using System.Runtime.CompilerServices;
- using Microsoft.DotNet.Cli.Utils;
- using Microsoft.NET.Build.Containers.LocalDaemons;
- using Microsoft.NET.Build.Containers.Resources;
- using Microsoft.NET.Build.Containers.UnitTests;
- using ILogger = Microsoft.Extensions.Logging.ILogger;
- namespace Microsoft.NET.Build.Containers.IntegrationTests;
- [Collection("Docker tests")]
- public class EndToEndTests : IDisposable
- {
- private ITestOutputHelper _testOutput;
- private readonly TestLoggerFactory _loggerFactory;
- public EndToEndTests(ITestOutputHelper testOutput)
- {
- _testOutput = testOutput;
- _loggerFactory = new TestLoggerFactory(testOutput);
- }
- public static string NewImageName([CallerMemberName] string callerMemberName = "")
- {
- var (normalizedName, warning, error) = ContainerHelpers.NormalizeRepository(callerMemberName);
- if (error is (var format, var args))
- {
- throw new ArgumentException(string.Format(Strings.ResourceManager.GetString(format)!, args));
- }
- return normalizedName!; // non-null if error is null
- }
- public void Dispose()
- {
- _loggerFactory.Dispose();
- }
- [DockerAvailableFact()]
- public async Task ApiEndToEndWithRegistryPushAndPull()
- {
- ILogger logger = _loggerFactory.CreateLogger(nameof(ApiEndToEndWithRegistryPushAndPull));
- string publishDirectory = BuildLocalApp();
- // Build the image
- Registry registry = new(DockerRegistryManager.LocalRegistry, logger);
- ImageBuilder imageBuilder = await registry.GetImageManifestAsync(
- DockerRegistryManager.RuntimeBaseImage,
- DockerRegistryManager.Net9PreviewImageTag,
- "linux-x64",
- ToolsetUtils.RidGraphManifestPicker,
- cancellationToken: default).ConfigureAwait(false);
- Assert.NotNull(imageBuilder);
- Layer l = Layer.FromDirectory(publishDirectory, "/app", false, imageBuilder.ManifestMediaType);
- imageBuilder.AddLayer(l);
- imageBuilder.SetEntrypointAndCmd(new[] { "/app/MinimalTestApp" }, Array.Empty<string>());
- BuiltImage builtImage = imageBuilder.Build();
- // Push the image back to the local registry
- var sourceReference = new SourceImageReference(registry, DockerRegistryManager.RuntimeBaseImage, DockerRegistryManager.Net9PreviewImageTag);
- var destinationReference = new DestinationImageReference(registry, NewImageName(), new[] { "latest", "1.0" });
- await registry.PushAsync(builtImage, sourceReference, destinationReference, cancellationToken: default).ConfigureAwait(false);
- foreach (string tag in destinationReference.Tags)
- {
- // pull it back locally
- ContainerCli.PullCommand(_testOutput, $"{DockerRegistryManager.LocalRegistry}/{NewImageName()}:{tag}")
- .Execute()
- .Should().Pass();
- // Run the image
- ContainerCli.RunCommand(_testOutput, "--rm", "--tty", $"{DockerRegistryManager.LocalRegistry}/{NewImageName()}:{tag}")
- .Execute()
- .Should().Pass();
- }
- }
- [DockerAvailableFact()]
- public async Task ApiEndToEndWithLocalLoad()
- {
- ILogger logger = _loggerFactory.CreateLogger(nameof(ApiEndToEndWithLocalLoad));
- string publishDirectory = BuildLocalApp(tfm: ToolsetInfo.CurrentTargetFramework);
- // Build the image
- Registry registry = new(DockerRegistryManager.LocalRegistry, logger);
- ImageBuilder imageBuilder = await registry.GetImageManifestAsync(
- DockerRegistryManager.RuntimeBaseImage,
- DockerRegistryManager.Net9PreviewImageTag,
- "linux-x64",
- ToolsetUtils.RidGraphManifestPicker,
- cancellationToken: default).ConfigureAwait(false);
- Assert.NotNull(imageBuilder);
- Layer l = Layer.FromDirectory(publishDirectory, "/app", false, imageBuilder.ManifestMediaType);
- imageBuilder.AddLayer(l);
- imageBuilder.SetEntrypointAndCmd(new[] { "/app/MinimalTestApp" }, Array.Empty<string>());
- BuiltImage builtImage = imageBuilder.Build();
- // Load the image into the local registry
- var sourceReference = new SourceImageReference(registry, DockerRegistryManager.RuntimeBaseImage, DockerRegistryManager.Net9PreviewImageTag);
- var destinationReference = new DestinationImageReference(registry, NewImageName(), new[] { "latest", "1.0" });
- await new DockerCli(_loggerFactory).LoadAsync(builtImage, sourceReference, destinationReference, default).ConfigureAwait(false);
- // Run the image
- foreach (string tag in destinationReference.Tags)
- {
- ContainerCli.RunCommand(_testOutput, "--rm", "--tty", $"{NewImageName()}:{tag}")
- .Execute()
- .Should().Pass();
- }
- }
- [DockerAvailableFact()]
- public async Task ApiEndToEndWithArchiveWritingAndLoad()
- {
- ILogger logger = _loggerFactory.CreateLogger(nameof(ApiEndToEndWithArchiveWritingAndLoad));
- string publishDirectory = BuildLocalApp(tfm: ToolsetInfo.CurrentTargetFramework);
- // Build the image
- Registry registry = new(DockerRegistryManager.LocalRegistry, logger);
- ImageBuilder imageBuilder = await registry.GetImageManifestAsync(
- DockerRegistryManager.RuntimeBaseImage,
- DockerRegistryManager.Net9PreviewImageTag,
- "linux-x64",
- ToolsetUtils.RidGraphManifestPicker,
- cancellationToken: default).ConfigureAwait(false);
- Assert.NotNull(imageBuilder);
- Layer l = Layer.FromDirectory(publishDirectory, "/app", false, imageBuilder.ManifestMediaType);
- imageBuilder.AddLayer(l);
- imageBuilder.SetEntrypointAndCmd(new[] { "/app/MinimalTestApp" }, Array.Empty<string>());
- BuiltImage builtImage = imageBuilder.Build();
- // Write the image to disk
- var archiveFile = Path.Combine(TestSettings.TestArtifactsDirectory,
- nameof(ApiEndToEndWithArchiveWritingAndLoad), "app.tar.gz");
- var sourceReference = new SourceImageReference(registry, DockerRegistryManager.RuntimeBaseImage, DockerRegistryManager.Net9PreviewImageTag);
- var destinationReference = new DestinationImageReference(new ArchiveFileRegistry(archiveFile), NewImageName(), new[] { "latest", "1.0" });
- await destinationReference.LocalRegistry!.LoadAsync(builtImage, sourceReference, destinationReference, default).ConfigureAwait(false);
- Assert.True(File.Exists(archiveFile), $"File.Exists({archiveFile})");
- // Load the archive
- ContainerCli.LoadCommand(_testOutput, "--input", archiveFile)
- .Execute()
- .Should().Pass();
- // Run the image
- foreach (string tag in destinationReference.Tags)
- {
- ContainerCli.RunCommand(_testOutput, "--rm", "--tty", $"{NewImageName()}:{tag}")
- .Execute()
- .Should().Pass();
- }
- }
- private string BuildLocalApp([CallerMemberName] string testName = "TestName", string tfm = ToolsetInfo.CurrentTargetFramework, string rid = "linux-x64")
- {
- string workingDirectory = Path.Combine(TestSettings.TestArtifactsDirectory, testName);
- DirectoryInfo d = new(Path.Combine(workingDirectory, "MinimalTestApp"));
- if (d.Exists)
- {
- d.Delete(recursive: true);
- }
- Directory.CreateDirectory(workingDirectory);
- new DotnetNewCommand(_testOutput, "console", "-f", tfm, "-o", "MinimalTestApp")
- .WithVirtualHive()
- .WithWorkingDirectory(workingDirectory)
- .Execute()
- .Should().Pass();
- var publishCommand =
- new DotnetCommand(_testOutput, "publish", "-bl", "MinimalTestApp", "-r", rid, "-f", tfm, "-c", "Debug")
- .WithWorkingDirectory(workingDirectory);
- if (tfm == ToolsetInfo.CurrentTargetFramework)
- {
- publishCommand.Arguments.AddRange(new[] { "-p", $"RuntimeFrameworkVersion={DockerRegistryManager.RuntimeFrameworkVersion}" });
- }
- publishCommand.Execute()
- .Should().Pass();
- string publishDirectory = Path.Join(workingDirectory, "MinimalTestApp", "bin", "Debug", tfm, rid, "publish");
- return publishDirectory;
- }
- [DockerAvailableFact()]
- public async Task EndToEnd_MultiProjectSolution()
- {
- ILogger logger = _loggerFactory.CreateLogger(nameof(EndToEnd_MultiProjectSolution));
- DirectoryInfo newSolutionDir = new(Path.Combine(TestSettings.TestArtifactsDirectory, $"CreateNewImageTest_EndToEnd_MultiProjectSolution"));
- if (newSolutionDir.Exists)
- {
- newSolutionDir.Delete(recursive: true);
- }
- newSolutionDir.Create();
- // Create solution with projects
- new DotnetNewCommand(_testOutput, "sln", "-n", nameof(EndToEnd_MultiProjectSolution))
- .WithVirtualHive()
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute()
- .Should().Pass();
- new DotnetNewCommand(_testOutput, "console", "-n", "ConsoleApp")
- .WithVirtualHive()
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute()
- .Should().Pass();
- new DotnetCommand(_testOutput, "sln", "add", Path.Combine("ConsoleApp", "ConsoleApp.csproj"))
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute()
- .Should().Pass();
- new DotnetNewCommand(_testOutput, "web", "-n", "WebApp")
- .WithVirtualHive()
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute()
- .Should().Pass();
- new DotnetCommand(_testOutput, "sln", "add", Path.Combine("WebApp", "WebApp.csproj"))
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute()
- .Should().Pass();
- // Add 'EnableSdkContainerSupport' property to the ConsoleApp and set TFM
- using (FileStream stream = File.Open(Path.Join(newSolutionDir.FullName, "ConsoleApp", "ConsoleApp.csproj"), FileMode.Open, FileAccess.ReadWrite))
- {
- XDocument document = await XDocument.LoadAsync(stream, LoadOptions.None, CancellationToken.None);
- document
- .Descendants()
- .First(e => e.Name.LocalName == "PropertyGroup")?
- .Add(new XElement("EnableSdkContainerSupport", "true"));
- document
- .Descendants()
- .First(e => e.Name.LocalName == "TargetFramework")
- .Value = ToolsetInfo.CurrentTargetFramework;
- stream.SetLength(0);
- await document.SaveAsync(stream, SaveOptions.None, CancellationToken.None);
- }
- // Set TFM for WebApp
- using (FileStream stream = File.Open(Path.Join(newSolutionDir.FullName, "WebApp", "WebApp.csproj"), FileMode.Open, FileAccess.ReadWrite))
- {
- XDocument document = await XDocument.LoadAsync(stream, LoadOptions.None, CancellationToken.None);
- document
- .Descendants()
- .First(e => e.Name.LocalName == "TargetFramework")
- .Value = ToolsetInfo.CurrentTargetFramework;
- stream.SetLength(0);
- await document.SaveAsync(stream, SaveOptions.None, CancellationToken.None);
- }
- // Publish
- CommandResult commandResult = new DotnetCommand(_testOutput, "publish", "/t:PublishContainer")
- .WithWorkingDirectory(newSolutionDir.FullName)
- .Execute();
- commandResult.Should().Pass();
- commandResult.Should().HaveStdOutContaining("Pushed image 'webapp:latest'");
- commandResult.Should().HaveStdOutContaining("Pushed image 'consoleapp:latest'");
- }
- [DockerAvailableTheory()]
- [InlineData("webapi", false)]
- [InlineData("webapi", true)]
- [InlineData("worker", false)]
- [InlineData("worker", true)]
- public async Task EndToEnd_NoAPI_ProjectType(string projectType, bool addPackageReference)
- {
- DirectoryInfo newProjectDir = new(Path.Combine(TestSettings.TestArtifactsDirectory, $"CreateNewImageTest_{projectType}_{addPackageReference}"));
- DirectoryInfo privateNuGetAssets = new(Path.Combine(TestSettings.TestArtifactsDirectory, "ContainerNuGet"));
- if (newProjectDir.Exists)
- {
- newProjectDir.Delete(recursive: true);
- }
- if (privateNuGetAssets.Exists)
- {
- privateNuGetAssets.Delete(recursive: true);
- }
- newProjectDir.Create();
- privateNuGetAssets.Create();
- new DotnetNewCommand(_testOutput, projectType, "-f", ToolsetInfo.CurrentTargetFramework)
- .WithVirtualHive()
- .WithWorkingDirectory(newProjectDir.FullName)
- // do not pollute the primary/global NuGet package store with the private package(s)
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .Execute()
- .Should().Pass();
- if (addPackageReference)
- {
- File.Copy(Path.Combine(TestContext.Current.TestExecutionDirectory, "NuGet.config"), Path.Combine(newProjectDir.FullName, "NuGet.config"));
- (string packagePath, string packageVersion) = ToolsetUtils.GetContainersPackagePath();
- new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath), "--name", "local-temp")
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute()
- .Should().Pass();
- // Add package to the project
- new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", ToolsetInfo.CurrentTargetFramework, "-v", packageVersion)
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute()
- .Should().Pass();
- }
- else
- {
- string projectPath = Path.Combine(newProjectDir.FullName, newProjectDir.Name + ".csproj");
- var project = XDocument.Load(projectPath);
- var ns = project.Root?.Name.Namespace ?? throw new InvalidOperationException("Project file is empty");
- project.Root?.Add(new XElement("PropertyGroup", new XElement("EnableSDKContainerSupport", "true")));
- project.Save(projectPath);
- }
- string imageName = NewImageName();
- string imageTag = $"1.0-{projectType}-{addPackageReference}";
- // Build & publish the project
- CommandResult commandResult = new DotnetCommand(
- _testOutput,
- "publish",
- "/p:PublishProfile=DefaultContainer",
- "/p:RuntimeIdentifier=linux-x64",
- $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
- $"/p:ContainerRegistry={DockerRegistryManager.LocalRegistry}",
- $"/p:ContainerRepository={imageName}",
- $"/p:ContainerImageTag={imageTag}",
- "/p:UseRazorSourceGenerator=false",
- $"/p:RuntimeFrameworkVersion={DockerRegistryManager.RuntimeFrameworkVersion}")
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute();
- commandResult.Should().Pass();
- if (addPackageReference)
- {
- commandResult.Should().HaveStdOutContaining("warning : The Microsoft.NET.Build.Containers NuGet package is explicitly referenced but the current SDK can natively publish the project as a container. Consider removing the package reference to Microsoft.NET.Build.Containers because it is no longer needed.");
- }
- else
- {
- commandResult.Should().NotHaveStdOutContaining("warning");
- }
- ContainerCli.PullCommand(_testOutput, $"{DockerRegistryManager.LocalRegistry}/{imageName}:{imageTag}")
- .Execute()
- .Should().Pass();
- var containerName = $"test-container-1-{projectType}-{addPackageReference}";
- CommandResult processResult = ContainerCli.RunCommand(
- _testOutput,
- "--rm",
- "--name",
- containerName,
- "-P",
- "--detach",
- $"{DockerRegistryManager.LocalRegistry}/{imageName}:{imageTag}")
- .Execute();
- processResult.Should().Pass();
- Assert.NotNull(processResult.StdOut);
- string appContainerId = processResult.StdOut.Trim();
- bool everSucceeded = false;
- if (projectType == "webapi")
- {
- var portCommand =
- ContainerCli.PortCommand(_testOutput, containerName, 8080)
- .Execute();
- portCommand.Should().Pass();
- var port = portCommand.StdOut.Trim().Split("\n")[0]; // only take the first port, which should be 0.0.0.0:PORT. the second line will be an ip6 port, if any.
- _testOutput.WriteLine($"Discovered port was '{port}'");
- var tempUri = new Uri($"http://{port}", UriKind.Absolute);
- var appUri = new UriBuilder(tempUri)
- {
- Host = "localhost"
- }.Uri;
- HttpClient client = new();
- client.BaseAddress = appUri;
- // Give the server a moment to catch up, but no more than necessary.
- for (int retry = 0; retry < 10; retry++)
- {
- try
- {
- var response = await client.GetAsync($"weatherforecast").ConfigureAwait(false);
- if (response.IsSuccessStatusCode)
- {
- everSucceeded = true;
- break;
- }
- }
- catch { }
- await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
- }
- ContainerCli.LogsCommand(_testOutput, appContainerId)
- .Execute()
- .Should().Pass();
- Assert.True(everSucceeded, $"{appUri}weatherforecast never responded.");
- ContainerCli.StopCommand(_testOutput, appContainerId)
- .Execute()
- .Should().Pass();
- }
- else if (projectType == "worker")
- {
- // the worker template needs a second to start up and emit the logs we are looking for
- await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
- var containerLogs =
- ContainerCli.LogsCommand(_testOutput, appContainerId)
- .Execute()
- .Should().Pass()
- .And.HaveStdOutContaining("Worker running at");
- ContainerCli.StopCommand(_testOutput, appContainerId)
- .Execute()
- .Should().Pass();
- }
- else
- {
- throw new NotImplementedException("Unknown project type");
- }
- newProjectDir.Delete(true);
- privateNuGetAssets.Delete(true);
- }
- [DockerAvailableFact()]
- public void EndToEnd_NoAPI_Console()
- {
- DirectoryInfo newProjectDir = new(Path.Combine(TestSettings.TestArtifactsDirectory, "CreateNewImageTest"));
- DirectoryInfo privateNuGetAssets = new(Path.Combine(TestSettings.TestArtifactsDirectory, "ContainerNuGet"));
- if (newProjectDir.Exists)
- {
- newProjectDir.Delete(recursive: true);
- }
- if (privateNuGetAssets.Exists)
- {
- privateNuGetAssets.Delete(recursive: true);
- }
- newProjectDir.Create();
- privateNuGetAssets.Create();
- new DotnetNewCommand(_testOutput, "console", "-f", ToolsetInfo.CurrentTargetFramework)
- .WithVirtualHive()
- .WithWorkingDirectory(newProjectDir.FullName)
- // do not pollute the primary/global NuGet package store with the private package(s)
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .Execute()
- .Should().Pass();
- File.Copy(Path.Combine(TestContext.Current.TestExecutionDirectory, "NuGet.config"), Path.Combine(newProjectDir.FullName, "NuGet.config"));
- (string packagePath, string packageVersion) = ToolsetUtils.GetContainersPackagePath();
- new DotnetCommand(_testOutput, "nuget", "add", "source", Path.GetDirectoryName(packagePath), "--name", "local-temp")
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute()
- .Should().Pass();
- // Add package to the project
- new DotnetCommand(_testOutput, "add", "package", "Microsoft.NET.Build.Containers", "-f", ToolsetInfo.CurrentTargetFramework, "-v", packageVersion)
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute()
- .Should().Pass();
- string imageName = NewImageName();
- string imageTag = "1.0";
- // Build & publish the project
- new DotnetCommand(
- _testOutput,
- "publish",
- "/t:PublishContainer",
- "/p:runtimeidentifier=linux-x64",
- $"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
- $"/p:ContainerRegistry={DockerRegistryManager.LocalRegistry}",
- $"/p:ContainerRepository={imageName}",
- $"/p:ContainerImageTag={imageTag}",
- "/p:EnableSdkContainerSupport=true",
- $"/p:RuntimeFrameworkVersion={DockerRegistryManager.RuntimeFrameworkVersion}")
- .WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
- .WithWorkingDirectory(newProjectDir.FullName)
- .Execute()
- .Should().Pass();
- ContainerCli.PullCommand(_testOutput, $"{DockerRegistryManager.LocalRegistry}/{imageName}:{imageTag}")
- .Execute()
- .Should().Pass();
- var containerName = "test-container-2";
- CommandResult processResult = ContainerCli.RunCommand(
- _testOutput,
- "--rm",
- "--name",
- containerName,
- $"{DockerRegistryManager.LocalRegistry}/{imageName}:{imageTag}")
- .Execute();
- processResult.Should().Pass().And.HaveStdOut("Hello, World!");
- newProjectDir.Delete(true);
- privateNuGetAssets.Delete(true);
- }
- [DockerSupportsArchInlineData("linux/arm/v7", "linux-arm", "/app")]
- [DockerSupportsArchInlineData("linux/arm64/v8", "linux-arm64", "/app")]
- [DockerSupportsArchInlineData("linux/386", "linux-x86", "/app", Skip = "There's no apphost for linux-x86 so we can't execute self-contained, and there's no .NET runtime base image for linux-x86 so we can't execute framework-dependent.")]
- [DockerSupportsArchInlineData("windows/amd64", "win-x64", "C:\\app")]
- [DockerSupportsArchInlineData("linux/amd64", "linux-x64", "/app")]
- [DockerAvailableTheory()]
- public async Task CanPackageForAllSupportedContainerRIDs(string dockerPlatform, string rid, string workingDir)
- {
- ILogger logger = _loggerFactory.CreateLogger(nameof(CanPackageForAllSupportedContainerRIDs));
- string publishDirectory = BuildLocalApp(tfm: ToolsetInfo.CurrentTargetFramework, rid: rid);
- // Build the image
- Registry registry = new(DockerRegistryManager.BaseImageSource, logger);
- var isWin = rid.StartsWith("win");
- ImageBuilder? imageBuilder = await registry.GetImageManifestAsync(
- DockerRegistryManager.RuntimeBaseImage,
- isWin ? DockerRegistryManager.Net8PreviewWindowsSpecificImageTag : DockerRegistryManager.Net9PreviewImageTag,
- rid,
- ToolsetUtils.RidGraphManifestPicker,
- cancellationToken: default).ConfigureAwait(false);
- Assert.NotNull(imageBuilder);
- Layer l = Layer.FromDirectory(publishDirectory, isWin ? "C:\\app" : "/app", isWin, imageBuilder.ManifestMediaType);
- imageBuilder.AddLayer(l);
- imageBuilder.SetWorkingDirectory(workingDir);
- string[] entryPoint = DecideEntrypoint(rid, "MinimalTestApp", workingDir);
- imageBuilder.SetEntrypointAndCmd(entryPoint, Array.Empty<string>());
- BuiltImage builtImage = imageBuilder.Build();
- // Load the image into the local registry
- var sourceReference = new SourceImageReference(registry, DockerRegistryManager.RuntimeBaseImage, DockerRegistryManager.Net9PreviewImageTag);
- var destinationReference = new DestinationImageReference(registry, NewImageName(), new[] { rid });
- await new DockerCli(_loggerFactory).LoadAsync(builtImage, sourceReference, destinationReference, default).ConfigureAwait(false);
- // Run the image
- ContainerCli.RunCommand(
- _testOutput,
- "--rm",
- "--tty",
- "--platform",
- dockerPlatform,
- $"{NewImageName()}:{rid}")
- .Execute()
- .Should()
- .Pass();
- static string[] DecideEntrypoint(string rid, string appName, string workingDir)
- {
- var binary = rid.StartsWith("win", StringComparison.Ordinal) ? $"{appName}.exe" : appName;
- return new[] { $"{workingDir}/{binary}" };
- }
- }
- }
|