From ab8f4e90d617d9c58e1e34e6eb0157fcfcc555fa Mon Sep 17 00:00:00 2001 From: Rasmus Mikkelsen Date: Sat, 14 May 2022 16:13:45 +0200 Subject: [PATCH] Allow naming of containers (#93) --- RELEASE_NOTES.md | 3 +- Source/Bake.Tests/Helpers/DockerHelper.cs | 17 +++++++ .../BakeTests/DockerFileSimpleTests.cs | 50 ++++++++++++++++++- .../Bake/Cooking/Composers/DockerComposer.cs | 35 +++++++++++-- Source/Bake/Cooking/Composers/GoComposer.cs | 2 +- .../ValueObjects/BakeProjects/BakeProject.cs | 3 ++ 6 files changed, 104 insertions(+), 6 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d245686c..6337b209 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,7 @@ # 0.14-beta -* *Nothing yet...* +* New: Allow naming of containers by creating a `bake.yaml` file besides + the `Dockerfile` # 0.13-beta diff --git a/Source/Bake.Tests/Helpers/DockerHelper.cs b/Source/Bake.Tests/Helpers/DockerHelper.cs index 51d8abeb..526ac623 100644 --- a/Source/Bake.Tests/Helpers/DockerHelper.cs +++ b/Source/Bake.Tests/Helpers/DockerHelper.cs @@ -87,5 +87,22 @@ await Client.Containers.StartContainerAsync( CancellationToken.None).Wait(CancellationToken.None); }); } + + public static async Task> ListImagesAsync( + CancellationToken cancellationToken = default) + { + var imageResponse = await Client.Images.ListImagesAsync( + new ImagesListParameters + { + All = true, + }, + cancellationToken); + + return imageResponse + .Where(i => i.RepoTags != null) + .SelectMany(i => i.RepoTags) + .OrderBy(t => t) + .ToArray(); + } } } diff --git a/Source/Bake.Tests/IntegrationTests/BakeTests/DockerFileSimpleTests.cs b/Source/Bake.Tests/IntegrationTests/BakeTests/DockerFileSimpleTests.cs index 435d64ee..b50cf634 100644 --- a/Source/Bake.Tests/IntegrationTests/BakeTests/DockerFileSimpleTests.cs +++ b/Source/Bake.Tests/IntegrationTests/BakeTests/DockerFileSimpleTests.cs @@ -21,11 +21,13 @@ // SOFTWARE. using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using Bake.Core; using Bake.Tests.Helpers; using FluentAssertions; using NUnit.Framework; +using File = System.IO.File; // ReSharper disable StringLiteralTypo @@ -40,12 +42,16 @@ public DockerFileSimpleTests() : base("Dockerfile.Simple") [Test] public async Task Run() { + // Arrange + var version = SemVer.Random.ToString(); + var expectedContainerNameAndTag = $"awesome-container:{version}"; + // Act var returnCode = await ExecuteAsync(TestState.New( "run", "--convention=Release", "--destination=container>localhost:5000", - "--build-version", SemVer.Random.ToString()) + "--build-version", version) .WithEnvironmentVariables(new Dictionary { ["bake_credentials_docker_localhost_username"] = "registryuser", @@ -54,6 +60,48 @@ public async Task Run() // Assert returnCode.Should().Be(0); + var images = await DockerHelper.ListImagesAsync(); + images.Should().Contain(new[] + { + $"bake.local/{expectedContainerNameAndTag}", + $"localhost:5000/{expectedContainerNameAndTag}" + }); + } + + [Test] + public async Task NamedDockerfile() + { + // Arrange + var version = SemVer.Random.ToString(); + var projectFilePath = Path.Combine( + WorkingDirectory, + "Awesome.Container", + "bake.yaml"); + await File.WriteAllTextAsync( + projectFilePath, + "name: \"magic-container\""); + var expectedContainerNameAndTag = $"magic-container:{version}"; + + // Act + var returnCode = await ExecuteAsync(TestState.New( + "run", + "--convention=Release", + "--destination=container>localhost:5000", + "--build-version", version) + .WithEnvironmentVariables(new Dictionary + { + ["bake_credentials_docker_localhost_username"] = "registryuser", + ["bake_credentials_docker_localhost_password"] = "registrypassword", + })); + + // Assert + returnCode.Should().Be(0); + var images = await DockerHelper.ListImagesAsync(); + images.Should().Contain(new [] + { + $"bake.local/{expectedContainerNameAndTag}", + $"localhost:5000/{expectedContainerNameAndTag}" + }); } } } diff --git a/Source/Bake/Cooking/Composers/DockerComposer.cs b/Source/Bake/Cooking/Composers/DockerComposer.cs index 47ccbac6..fb21982a 100644 --- a/Source/Bake/Cooking/Composers/DockerComposer.cs +++ b/Source/Bake/Cooking/Composers/DockerComposer.cs @@ -33,6 +33,7 @@ using Bake.ValueObjects.Recipes; using Bake.ValueObjects.Recipes.Docker; using Microsoft.Extensions.Logging; +using File = System.IO.File; namespace Bake.Cooking.Composers { @@ -52,19 +53,22 @@ public class DockerComposer : Composer private readonly IFileSystem _fileSystem; private readonly IContainerTagParser _containerTagParser; private readonly IConventionInterpreter _conventionInterpreter; + private readonly IBakeProjectParser _bakeProjectParser; public DockerComposer( ILogger logger, IDefaults defaults, IFileSystem fileSystem, IContainerTagParser containerTagParser, - IConventionInterpreter conventionInterpreter) + IConventionInterpreter conventionInterpreter, + IBakeProjectParser bakeProjectParser) { _logger = logger; _defaults = defaults; _fileSystem = fileSystem; _containerTagParser = containerTagParser; _conventionInterpreter = conventionInterpreter; + _bakeProjectParser = bakeProjectParser; } public override async Task> ComposeAsync( @@ -89,8 +93,12 @@ public override async Task> ComposeAsync( _logger.LogInformation( "Located Dockerfile at these locations, scheduling build: {DockerFiles}", dockerFilePaths); - var directoryName = Path.GetFileName(Path.GetDirectoryName(dockerFilePath)); - recipes.AddRange(CreateRecipes(dockerFilePath, directoryName, ingredients.Version, urls)); + + var containerName = await GetContainerNameAsync( + Path.GetDirectoryName(dockerFilePath), + cancellationToken); + + recipes.AddRange(CreateRecipes(dockerFilePath, containerName, ingredients.Version, urls)); } var dockerfileArtifacts = context @@ -124,6 +132,27 @@ public override async Task> ComposeAsync( return recipes; } + private async Task GetContainerNameAsync( + string directory, + CancellationToken cancellationToken) + { + var projectFilePath = Path.Combine( + directory, + "bake.yaml"); // TODO: Rework to align file name + + if (File.Exists(projectFilePath)) + { + var fileContent = await File.ReadAllTextAsync(projectFilePath, cancellationToken); + var bakeProject = await _bakeProjectParser.ParseAsync(fileContent, cancellationToken); + if (!string.IsNullOrEmpty(bakeProject.Name)) + { + return bakeProject.Name; + } + } + + return Path.GetFileName(directory); + } + private IEnumerable CreateRecipes( string path, string name, diff --git a/Source/Bake/Cooking/Composers/GoComposer.cs b/Source/Bake/Cooking/Composers/GoComposer.cs index a39c4680..c2507025 100644 --- a/Source/Bake/Cooking/Composers/GoComposer.cs +++ b/Source/Bake/Cooking/Composers/GoComposer.cs @@ -95,7 +95,7 @@ private async Task> CreateRecipesAsync( var projectType = BakeProjectType.Tool; var servicePort = -1; - var bakeProjectPath = Path.Combine(directoryPath, "bake.yaml"); + var bakeProjectPath = Path.Combine(directoryPath, "bake.yaml"); // TODO: Rework to align file name if (System.IO.File.Exists(bakeProjectPath)) { var bakeProjectContent = await _fileSystem.ReadAllTextAsync( diff --git a/Source/Bake/ValueObjects/BakeProjects/BakeProject.cs b/Source/Bake/ValueObjects/BakeProjects/BakeProject.cs index fc515b64..136331db 100644 --- a/Source/Bake/ValueObjects/BakeProjects/BakeProject.cs +++ b/Source/Bake/ValueObjects/BakeProjects/BakeProject.cs @@ -26,6 +26,9 @@ namespace Bake.ValueObjects.BakeProjects { public class BakeProject { + [YamlMember(Alias = "name")] + public string? Name { get; set; } + [YamlMember] public BakeProjectType Type { get; set; }