diff --git a/Mittons.Fixtures.Tests.Integration/Docker/Fixtures/DockerEnvironmentFixtureTests.cs b/Mittons.Fixtures.Tests.Integration/Docker/Fixtures/DockerEnvironmentFixtureTests.cs index f5f1bc9..0947979 100644 --- a/Mittons.Fixtures.Tests.Integration/Docker/Fixtures/DockerEnvironmentFixtureTests.cs +++ b/Mittons.Fixtures.Tests.Integration/Docker/Fixtures/DockerEnvironmentFixtureTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Text.Json; @@ -124,6 +123,31 @@ public void ExpectAlpineContainerToBeConnectedToNetwork1() } } + [Fact] + public void ExpectAlpineContainerToHaveRunLabel() + { + Assert.NotNull(_dockerEnvironmentFixture.AlpineContainer); + + if (_dockerEnvironmentFixture.AlpineContainer is not null) + { + using var proc = new Process(); + proc.StartInfo.FileName = "docker"; + proc.StartInfo.Arguments = $"inspect {_dockerEnvironmentFixture.AlpineContainer.Id} --format \"{{{{json .Config.Labels}}}}\""; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = true; + + proc.Start(); + proc.WaitForExit(); + + var output = proc.StandardOutput.ReadToEnd(); + + var labels = JsonSerializer.Deserialize>(output) ?? new Dictionary(); + + Assert.True(labels.ContainsKey("mittons.fixtures.run.id")); + Assert.Equal(Run.DefaultId, labels["mittons.fixtures.run.id"]); + } + } + [Fact] public void ExpectSftpContainerToBeCreated() { @@ -207,5 +231,30 @@ public void ExpectSftpContainerToBeConnectedToNetwork2() Assert.Contains(connectedNetworks, x => x.StartsWith($"network2-")); } } + + [Fact] + public void ExpectSftpContainerToHaveRunLabel() + { + Assert.NotNull(_dockerEnvironmentFixture.SftpContainer); + + if (_dockerEnvironmentFixture.SftpContainer is not null) + { + using var proc = new Process(); + proc.StartInfo.FileName = "docker"; + proc.StartInfo.Arguments = $"inspect {_dockerEnvironmentFixture.SftpContainer.Id} --format \"{{{{json .Config.Labels}}}}\""; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = true; + + proc.Start(); + proc.WaitForExit(); + + var output = proc.StandardOutput.ReadToEnd(); + + var labels = JsonSerializer.Deserialize>(output) ?? new Dictionary(); + + Assert.True(labels.ContainsKey("mittons.fixtures.run.id")); + Assert.Equal(Run.DefaultId, labels["mittons.fixtures.run.id"]); + } + } } } \ No newline at end of file diff --git a/Mittons.Fixtures.Tests.Integration/Docker/Gateways/DefaultDockerGatewayTests.cs b/Mittons.Fixtures.Tests.Integration/Docker/Gateways/DefaultDockerGatewayTests.cs index 74c48ae..aeb1d66 100644 --- a/Mittons.Fixtures.Tests.Integration/Docker/Gateways/DefaultDockerGatewayTests.cs +++ b/Mittons.Fixtures.Tests.Integration/Docker/Gateways/DefaultDockerGatewayTests.cs @@ -38,6 +38,46 @@ public void Dispose() } } + [Fact] + public void ContainerRun_WhenCalledWithLabels_ExpectContainerToHaveTheLabelsApplied() + { + // Arrange + var imageName = "alpine:3.15"; + var gateway = new DefaultDockerGateway(); + + // Act + var containerId = gateway.ContainerRun( + imageName, + string.Empty, + new Dictionary + { + { "first", "second" }, + { "third", "fourth" } + } + ); + + _containerIds.Add(containerId); + + // Assert + using var proc = new Process(); + proc.StartInfo.FileName = "docker"; + proc.StartInfo.Arguments = $"inspect {containerId} --format \"{{{{json .Config.Labels}}}}\""; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = true; + + proc.Start(); + proc.WaitForExit(); + + var output = proc.StandardOutput.ReadToEnd(); + + var actualLabels = JsonSerializer.Deserialize>(output) ?? new Dictionary(); + + Assert.True(actualLabels.ContainsKey("first")); + Assert.True(actualLabels.ContainsKey("third")); + Assert.Equal("second", actualLabels["first"]); + Assert.Equal("fourth", actualLabels["third"]); + } + [Theory] [InlineData("alpine:3.15")] [InlineData("alpine:3.14")] @@ -47,7 +87,7 @@ public void ContainerRun_WhenCalledWithAnImage_ExpectContainerToBeForTheRequeste var gateway = new DefaultDockerGateway(); // Act - var containerId = gateway.ContainerRun(imageName, string.Empty); + var containerId = gateway.ContainerRun(imageName, string.Empty, new Dictionary()); _containerIds.Add(containerId); // Assert @@ -78,7 +118,7 @@ public void ContainerRun_WhenCalledForAlpineWithNoCommand_ExpectContainerToHaveS var gateway = new DefaultDockerGateway(); // Act - var containerId = gateway.ContainerRun("alpine:3.15", string.Empty); + var containerId = gateway.ContainerRun("alpine:3.15", string.Empty, new Dictionary()); _containerIds.Add(containerId); // Assert @@ -109,7 +149,7 @@ public void ContainerRun_WhenCalledForAlpineWithACommand_ExpectContainerToHaveSt var gateway = new DefaultDockerGateway(); // Act - var containerId = gateway.ContainerRun("alpine:3.15", "/bin/bash"); + var containerId = gateway.ContainerRun("alpine:3.15", "/bin/bash", new Dictionary()); _containerIds.Add(containerId); // Assert @@ -150,7 +190,7 @@ public void ContainerRemove_WhenTheContainerExists_ExpectTheContainerToBeRemoved // Arrange var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("alpine:3.15", string.Empty); + var containerId = gateway.ContainerRun("alpine:3.15", string.Empty, new Dictionary()); _containerIds.Add(containerId); // Act @@ -177,7 +217,7 @@ public void ContainerGetDefaultNetworkIpAddress_WhenTheContainerIsOnOneNetwork_R // Arrange var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest", new Dictionary()); _containerIds.Add(containerId); // Act @@ -213,7 +253,7 @@ public void ContainerAddFile_WhenCalled_ExpectFileToBeCopiedToTheContainer(strin var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest", new Dictionary()); _containerIds.Add(containerId); // Act @@ -249,7 +289,7 @@ public void ContainerAddFile_WhenCalledWithPermissions_ExpectThePermissionsToBeS var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest", new Dictionary()); _containerIds.Add(containerId); // Act @@ -285,7 +325,7 @@ public void ContainerAddFile_WhenCalledWithAnOwner_ExpectThePermissionsToBeSet(s var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest tester:tester"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest tester:tester", new Dictionary()); _containerIds.Add(containerId); // Act @@ -321,7 +361,7 @@ public void ContainerRemoveFile_WhenCalled_ExpectFileToBeRemoved(string containe var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest tester:tester"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest tester:tester", new Dictionary()); _containerIds.Add(containerId); gateway.ContainerAddFile(containerId, temporaryFilename, containerFilename, default(string), default(string)); @@ -487,7 +527,7 @@ public void NetworkConnect_WhenCalled_ExpectContainerToBeConnectedToNetwork() var gateway = new DefaultDockerGateway(); - var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest"); + var containerId = gateway.ContainerRun("atmoz/sftp:alpine", "guest:guest", new Dictionary()); _containerIds.Add(containerId); _networkNames.Add(uniqueName); diff --git a/Mittons.Fixtures.Tests.Unit/Docker/Containers/ContainerTests.cs b/Mittons.Fixtures.Tests.Unit/Docker/Containers/ContainerTests.cs index 89dac6d..113a02c 100644 --- a/Mittons.Fixtures.Tests.Unit/Docker/Containers/ContainerTests.cs +++ b/Mittons.Fixtures.Tests.Unit/Docker/Containers/ContainerTests.cs @@ -7,6 +7,7 @@ using System.Net; using System.IO; using System.Text; +using System.Collections.Generic; namespace Mittons.Fixtures.Tests.Unit.Docker.Containers { @@ -24,7 +25,7 @@ public void Ctor_WhenInitializedWithAnImageName_ExpectTheImageNameToBePassedToTh using var container = new Container(gatewayMock.Object, new Attribute[] { new Image(imageName), new Command(string.Empty) }); // Assert - gatewayMock.Verify(x => x.ContainerRun(imageName, string.Empty), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(imageName, string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } [Theory] @@ -39,7 +40,40 @@ public void Ctor_WhenInitializedWithACommand_ExpectTheCommandToBePassedToTheDock using var container = new Container(gatewayMock.Object, new Attribute[] { new Image(string.Empty), new Command(command) }); // Assert - gatewayMock.Verify(x => x.ContainerRun(string.Empty, command), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(string.Empty, command, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); + } + + [Theory] + [InlineData("192.168.0.0")] + [InlineData("192.168.0.1")] + [InlineData("127.0.0.1")] + public void Ctor_WhenCreated_ExpectTheDefaultIpAddressToBeSet(string ipAddress) + { + // Arrange + var parsed = IPAddress.Parse(ipAddress); + + var gatewayMock = new Mock(); + gatewayMock.Setup(x => x.ContainerGetDefaultNetworkIpAddress(It.IsAny())).Returns(parsed); + + // Act + using var container = new Container(gatewayMock.Object, new Attribute[] { new Image(string.Empty), new Command(string.Empty) }); + + // Assert + Assert.Equal(parsed, container.IpAddress); + } + + [Fact] + public void Ctor_WhenCreatedWithARun_ExpectLabelsToBePassedToTheGateway() + { + // Arrange + var gatewayMock = new Mock(); + var run = new Run(); + + // Act + using var container = new Container(gatewayMock.Object, new Attribute[] { new Image(string.Empty), new Command(string.Empty), run }); + + // Assert + gatewayMock.Verify(x => x.ContainerRun(string.Empty, string.Empty, It.Is>(x => x.ContainsKey("mittons.fixtures.run.id") && x["mittons.fixtures.run.id"] == run.Id))); } [Fact] @@ -62,8 +96,10 @@ public void Dispose_WhenCalledWhileAnotherContainerIsRunning_ExpectOnlyTheCalled { // Arrange var gatewayMock = new Mock(); - gatewayMock.Setup(x => x.ContainerRun("runningimage", string.Empty)).Returns("runningid"); - gatewayMock.Setup(x => x.ContainerRun("disposingimage", string.Empty)).Returns("disposingid"); + gatewayMock.Setup(x => x.ContainerRun("runningimage", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))) + .Returns("runningid"); + gatewayMock.Setup(x => x.ContainerRun("disposingimage", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))) + .Returns("disposingid"); using var runningContainer = new Container(gatewayMock.Object, new Attribute[] { new Image("runningimage"), new Command(string.Empty) }); using var disposingContainer = new Container(gatewayMock.Object, new Attribute[] { new Image("disposingimage"), new Command(string.Empty) }); @@ -76,25 +112,6 @@ public void Dispose_WhenCalledWhileAnotherContainerIsRunning_ExpectOnlyTheCalled gatewayMock.Verify(x => x.ContainerRemove(runningContainer.Id), Times.Never); } - [Theory] - [InlineData("192.168.0.0")] - [InlineData("192.168.0.1")] - [InlineData("127.0.0.1")] - public void Ctor_WhenCreated_ExpectTheDefaultIpAddressToBeSet(string ipAddress) - { - // Arrange - var parsed = IPAddress.Parse(ipAddress); - - var gatewayMock = new Mock(); - gatewayMock.Setup(x => x.ContainerGetDefaultNetworkIpAddress(It.IsAny())).Returns(parsed); - - // Act - using var container = new Container(gatewayMock.Object, new Attribute[] { new Image(string.Empty), new Command(string.Empty) }); - - // Assert - Assert.Equal(parsed, container.IpAddress); - } - [Theory] [InlineData("file/one", "destination/one", "testowner", "testpermissions")] [InlineData("two", "two", "owner", "permissions")] diff --git a/Mittons.Fixtures.Tests.Unit/Docker/Containers/SftpContainerTests.cs b/Mittons.Fixtures.Tests.Unit/Docker/Containers/SftpContainerTests.cs index bf4636f..edc3ebc 100644 --- a/Mittons.Fixtures.Tests.Unit/Docker/Containers/SftpContainerTests.cs +++ b/Mittons.Fixtures.Tests.Unit/Docker/Containers/SftpContainerTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System; using Mittons.Fixtures.Docker.Attributes; +using System.Collections.Generic; namespace Mittons.Fixtures.Tests.Unit.Docker.Containers { @@ -22,7 +23,7 @@ public void Ctor_WhenCalled_ExpectTheContainerToUseTheAtmozImage() using var container = new SftpContainer(gatewayMock.Object, Enumerable.Empty()); // Assert - gatewayMock.Verify(x => x.ContainerRun(sftpImageName, It.IsAny()), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(sftpImageName, It.IsAny(), It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } [Fact] @@ -35,7 +36,7 @@ public void Ctor_InitializedWithNoCredentials_ExpectTheCommandToSetupTheGuestAcc using var container = new SftpContainer(gatewayMock.Object, Enumerable.Empty()); // Assert - gatewayMock.Verify(x => x.ContainerRun(sftpImageName, "guest:guest"), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(sftpImageName, "guest:guest", It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } [Theory] @@ -57,7 +58,7 @@ public void Ctor_InitializedWithOneSetOfCredentials_ExpectTheCommandToSetupTheCr ); // Assert - gatewayMock.Verify(x => x.ContainerRun(sftpImageName, $"{username}:{password}"), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(sftpImageName, $"{username}:{password}", It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } [Fact] @@ -78,7 +79,7 @@ public void Ctor_InitializedWithMultipleSetOfCredentials_ExpectTheCommandToSetup ); // Assert - gatewayMock.Verify(x => x.ContainerRun(sftpImageName, $"testuser1:testpassword1 testuser2:testpassword2 guest:guest"), Times.Once); + gatewayMock.Verify(x => x.ContainerRun(sftpImageName, $"testuser1:testpassword1 testuser2:testpassword2 guest:guest", It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } } } \ No newline at end of file diff --git a/Mittons.Fixtures.Tests.Unit/Docker/Fixtures/DockerEnvironmentTests.cs b/Mittons.Fixtures.Tests.Unit/Docker/Fixtures/DockerEnvironmentTests.cs index 03dc5c0..d833955 100644 --- a/Mittons.Fixtures.Tests.Unit/Docker/Fixtures/DockerEnvironmentTests.cs +++ b/Mittons.Fixtures.Tests.Unit/Docker/Fixtures/DockerEnvironmentTests.cs @@ -99,12 +99,30 @@ public void Ctor_WhenInitializedWithRunDetailsFromBuildId_ExpectTheRunIdToBeSet( // Arrange var gatewayMock = new Mock(); + // Act + using var fixture = new BuildEnvironmentFixture(gatewayMock.Object); + + // Assert + gatewayMock.Verify(x => x.NetworkCreate($"network1-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == _buildId)), Times.Once); + gatewayMock.Verify(x => x.NetworkCreate($"network2-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == _buildId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", "", It.Is>(y => y["mittons.fixtures.run.id"] == _buildId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("redis:alpine", "", It.Is>(y => y["mittons.fixtures.run.id"] == _buildId)), Times.Once); + } + + [Fact] + public void Ctor_WhenInitializedWithRunDetailsFromReleaseId_ExpectTheRunIdToBeSet() + { + // Arrange + var gatewayMock = new Mock(); + // Act using var fixture = new ReleaseEnvironmentFixture(gatewayMock.Object); // Assert gatewayMock.Verify(x => x.NetworkCreate($"network1-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == _releaseId)), Times.Once); gatewayMock.Verify(x => x.NetworkCreate($"network2-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == _releaseId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", "", It.Is>(y => y["mittons.fixtures.run.id"] == _releaseId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("redis:alpine", "", It.Is>(y => y["mittons.fixtures.run.id"] == _releaseId)), Times.Once); } [Fact] @@ -119,6 +137,8 @@ public void Ctor_WhenInitializedWithRunDetailsFromUnsetEnvironmentVariables_Expe // Assert gatewayMock.Verify(x => x.NetworkCreate($"network1-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); gatewayMock.Verify(x => x.NetworkCreate($"network2-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", "", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("redis:alpine", "", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); } [Fact] @@ -133,6 +153,8 @@ public void Ctor_WhenInitializedWithoutRunDetails_ExpectTheRunIdToBeDefault() // Assert gatewayMock.Verify(x => x.NetworkCreate($"network1-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); gatewayMock.Verify(x => x.NetworkCreate($"network2-{fixture.InstanceId}", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", "", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("redis:alpine", "", It.Is>(y => y["mittons.fixtures.run.id"] == Run.DefaultId)), Times.Once); } } @@ -162,8 +184,8 @@ public void Ctor_WhenInitializedWithContainerDefinitions_ExpectContainersToRunUs using var fixture = new ContainerTestEnvironmentFixture(gatewayMock.Object); // Assert - gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", string.Empty), Times.Once); - gatewayMock.Verify(x => x.ContainerRun("redis:alpine", string.Empty), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("alpine:3.15", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); + gatewayMock.Verify(x => x.ContainerRun("redis:alpine", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Once); } [Fact] @@ -171,8 +193,8 @@ public void Dispose_WhenCalled_ExpectAllContainersToBeRemoved() { // Arrange var gatewayMock = new Mock(); - gatewayMock.Setup(x => x.ContainerRun("alpine:3.15", string.Empty)).Returns("runningid"); - gatewayMock.Setup(x => x.ContainerRun("redis:alpine", string.Empty)).Returns("disposingid"); + gatewayMock.Setup(x => x.ContainerRun("alpine:3.15", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))).Returns("runningid"); + gatewayMock.Setup(x => x.ContainerRun("redis:alpine", string.Empty, It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))).Returns("disposingid"); using var fixture = new ContainerTestEnvironmentFixture(gatewayMock.Object); @@ -219,7 +241,7 @@ public void Ctor_WhenInitializedWithSftpContainerDefinitions_ExpectContainersToR using var fixture = new SftpContainerTestEnvironmentFixture(gatewayMock.Object); // Assert - gatewayMock.Verify(x => x.ContainerRun("atmoz/sftp:alpine", It.IsAny()), Times.Exactly(2)); + gatewayMock.Verify(x => x.ContainerRun("atmoz/sftp:alpine", It.IsAny(), It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id"))), Times.Exactly(2)); } [Fact] @@ -227,8 +249,8 @@ public void Dispose_WhenCalled_ExpectAllContainersToBeRemoved() { // Arrange var gatewayMock = new Mock(); - gatewayMock.Setup(x => x.ContainerRun("atmoz/sftp:alpine", "guest:guest")).Returns("guest"); - gatewayMock.Setup(x => x.ContainerRun("atmoz/sftp:alpine", "testuser1:testpassword1 testuser2:testpassword2")).Returns("account"); + gatewayMock.Setup(x => x.ContainerRun("atmoz/sftp:alpine", "guest:guest", It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))).Returns("guest"); + gatewayMock.Setup(x => x.ContainerRun("atmoz/sftp:alpine", "testuser1:testpassword1 testuser2:testpassword2", It.Is>(x => x.Count == 1 && x.ContainsKey("mittons.fixtures.run.id")))).Returns("account"); using var fixture = new SftpContainerTestEnvironmentFixture(gatewayMock.Object); diff --git a/Mittons.Fixtures/Docker/Containers/Container.cs b/Mittons.Fixtures/Docker/Containers/Container.cs index e01634f..4a3a577 100644 --- a/Mittons.Fixtures/Docker/Containers/Container.cs +++ b/Mittons.Fixtures/Docker/Containers/Container.cs @@ -20,7 +20,13 @@ public Container(IDockerGateway dockerGateway, IEnumerable attributes { _dockerGateway = dockerGateway; - Id = _dockerGateway.ContainerRun(attributes.OfType().Single().Name, attributes.OfType().SingleOrDefault()?.Value ?? string.Empty); + var run = attributes.OfType().SingleOrDefault() ?? new Run(); + + Id = _dockerGateway.ContainerRun( + attributes.OfType().Single().Name, + attributes.OfType().SingleOrDefault()?.Value ?? string.Empty, + (attributes.OfType().SingleOrDefault() ?? new Run()).Labels + ); IpAddress = _dockerGateway.ContainerGetDefaultNetworkIpAddress(Id); } diff --git a/Mittons.Fixtures/Docker/Fixtures/DockerEnvironmentFixture.cs b/Mittons.Fixtures/Docker/Fixtures/DockerEnvironmentFixture.cs index f9c6e93..a4805de 100644 --- a/Mittons.Fixtures/Docker/Fixtures/DockerEnvironmentFixture.cs +++ b/Mittons.Fixtures/Docker/Fixtures/DockerEnvironmentFixture.cs @@ -39,15 +39,15 @@ public DockerEnvironmentFixture(IDockerGateway dockerGateway) _containers = new List(); - foreach(var propertyInfo in this.GetType().GetProperties().Where(x => typeof(Container).IsAssignableFrom(x.PropertyType))) + foreach (var propertyInfo in this.GetType().GetProperties().Where(x => typeof(Container).IsAssignableFrom(x.PropertyType))) { - var attributes = propertyInfo.GetCustomAttributes(false).OfType(); + var attributes = propertyInfo.GetCustomAttributes(false).OfType().Concat(new[] { run }); - var container = (Container)Activator.CreateInstance(propertyInfo.PropertyType, new object[] { dockerGateway, attributes}); + var container = (Container)Activator.CreateInstance(propertyInfo.PropertyType, new object[] { dockerGateway, attributes }); propertyInfo.SetValue(this, container); _containers.Add(container); - foreach(var networkAlias in attributes.OfType()) + foreach (var networkAlias in attributes.OfType()) { dockerGateway.NetworkConnect($"{networkAlias.NetworkName}-{InstanceId}", container.Id, networkAlias.Alias); } @@ -56,12 +56,12 @@ public DockerEnvironmentFixture(IDockerGateway dockerGateway) public void Dispose() { - foreach(var container in _containers) + foreach (var container in _containers) { container.Dispose(); } - foreach(var network in _networks) + foreach (var network in _networks) { network.Dispose(); } diff --git a/Mittons.Fixtures/Docker/Gateways/DefaultDockerGateway.cs b/Mittons.Fixtures/Docker/Gateways/DefaultDockerGateway.cs index f6f06b3..68a9052 100644 --- a/Mittons.Fixtures/Docker/Gateways/DefaultDockerGateway.cs +++ b/Mittons.Fixtures/Docker/Gateways/DefaultDockerGateway.cs @@ -7,12 +7,14 @@ namespace Mittons.Fixtures.Docker.Gateways { public class DefaultDockerGateway : IDockerGateway { - public string ContainerRun(string imageName, string command) + public string ContainerRun(string imageName, string command, Dictionary labels) { + var labelStrings = labels.Select(x => $"--label \"{x.Key}={x.Value}\""); + using (var proc = new Process()) { proc.StartInfo.FileName = "docker"; - proc.StartInfo.Arguments = $"run -d {imageName} {command}"; + proc.StartInfo.Arguments = $"run -d {string.Join(" ", labelStrings)} {imageName} {command}"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; diff --git a/Mittons.Fixtures/Docker/Gateways/IDockerGateway.cs b/Mittons.Fixtures/Docker/Gateways/IDockerGateway.cs index 96c6975..5d23c86 100644 --- a/Mittons.Fixtures/Docker/Gateways/IDockerGateway.cs +++ b/Mittons.Fixtures/Docker/Gateways/IDockerGateway.cs @@ -5,7 +5,7 @@ namespace Mittons.Fixtures.Docker.Gateways { public interface IDockerGateway { - string ContainerRun(string imageName, string command); + string ContainerRun(string imageName, string command, Dictionary labels); void ContainerRemove(string containerId);