Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 33 additions & 32 deletions src/TestEnvironment.Docker/ContainerOperations/ContainerApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,37 +106,7 @@ public async Task StopContainerAsync(string id, CancellationToken cancellationTo
public async Task RemoveContainerAsync(string id, CancellationToken cancellationToken = default) =>
await _dockerClient.Containers.RemoveContainerAsync(id, new ContainerRemoveParameters { Force = true });

private async Task<ContainerListResponse> CreateContainer(ContainerParameters containerParameters, CancellationToken cancellationToken)
{
// Create new container
var createParams = GetCreateContainerParameters(containerParameters);

var containerInstance = await _dockerClient.Containers.CreateContainerAsync(createParams, cancellationToken);

// Run container
await _dockerClient.Containers.StartContainerAsync(containerInstance.ID, new ContainerStartParameters(), cancellationToken);

// Try to find container in docker session
#pragma warning disable CS8603 // Possible null reference return.
return await GetContainerAsync(containerParameters.Name, cancellationToken);
#pragma warning restore CS8603 // Possible null reference return.
}

private async Task<ContainerListResponse?> GetContainerAsync(string name, CancellationToken cancellationToken)
{
var containerName = $"/{name}";

var containers = await _dockerClient.Containers.ListContainersAsync(
new ContainersListParameters
{
All = true
},
cancellationToken);

return containers?.FirstOrDefault(x => x.Names.Contains(containerName));
}

private CreateContainerParameters GetCreateContainerParameters(ContainerParameters containerParameters)
protected virtual CreateContainerParameters GetCreateContainerParameters(ContainerParameters containerParameters)
{
var (name, imageName, tag, environmentVariables, ports, entrypoint, exposedPorts) =
(containerParameters.Name, containerParameters.ImageName, containerParameters.Tag, containerParameters.EnvironmentVariables, containerParameters.Ports, containerParameters.Entrypoint, containerParameters.ExposedPorts);
Expand All @@ -153,7 +123,8 @@ private CreateContainerParameters GetCreateContainerParameters(ContainerParamete
Hostname = name,
HostConfig = new HostConfig
{
PublishAllPorts = ports == null
PublishAllPorts = ports == null,
Binds = containerParameters.Binds
}
};

Expand All @@ -178,5 +149,35 @@ private CreateContainerParameters GetCreateContainerParameters(ContainerParamete

return createParams;
}

private async Task<ContainerListResponse> CreateContainer(ContainerParameters containerParameters, CancellationToken cancellationToken)
{
// Create new container
var createParams = GetCreateContainerParameters(containerParameters);

var containerInstance = await _dockerClient.Containers.CreateContainerAsync(createParams, cancellationToken);

// Run container
await _dockerClient.Containers.StartContainerAsync(containerInstance.ID, new ContainerStartParameters(), cancellationToken);

// Try to find container in docker session
#pragma warning disable CS8603 // Possible null reference return.
return await GetContainerAsync(containerParameters.Name, cancellationToken);
#pragma warning restore CS8603 // Possible null reference return.
}

private async Task<ContainerListResponse?> GetContainerAsync(string name, CancellationToken cancellationToken)
{
var containerName = $"/{name}";

var containers = await _dockerClient.Containers.ListContainersAsync(
new ContainersListParameters
{
All = true
},
cancellationToken);

return containers?.FirstOrDefault(x => x.Names.Contains(containerName));
}
}
}
2 changes: 2 additions & 0 deletions src/TestEnvironment.Docker/ContainerParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public record ContainerParameters(string Name, string ImageName)

public IList<ushort>? ExposedPorts { get; init; }

public IList<string>? Binds { get; init; }

public IContainerInitializer? ContainerInitializer { get; init; }

public IContainerWaiter? ContainerWaiter { get; init; }
Expand Down
6 changes: 4 additions & 2 deletions src/TestEnvironment.Docker/DockerEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ public DockerEnvironment(string name, Container[] containers, IDockerClient dock
{
}

public DockerEnvironment(string name, Container[] containers, IImageApi imageApi, IContainerApi containerApi, ILogger? logger) =>
(Name, Containers, _imageApi, _containerApi, _logger) = (name, containers, imageApi, containerApi, logger);
public DockerEnvironment(string name, Container[] containers, IImageApi imageApi, IContainerApi containerApi, ILogger? logger)
: this(name, containers, imageApi, containerApi, null, logger)
{
}

public DockerEnvironment(string name, Container[] containers, IImageApi imageApi, IContainerApi containerApi, IDockerInitializer? dockerInitializer, ILogger? logger) =>
(Name, Containers, _imageApi, _containerApi, _dockerInitializer, _logger) = (name, containers, imageApi, containerApi, dockerInitializer, logger);
Expand Down
26 changes: 23 additions & 3 deletions src/TestEnvironment.Docker/DockerEnvironmentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class DockerEnvironmentBuilder : IDockerEnvironmentBuilder
private bool _isWsl2 = false;
private bool _isDockerInDocker = false;
private string _environmentName = Guid.NewGuid().ToString().Substring(0, 10);
private Func<IDockerClient, ILogger?, IContainerApi>? _containerApiFactory;
private Func<IDockerClient, ILogger?, IImageApi>? _imageApiFactory;

public IDockerClient DockerClient { get; private set; }

Expand Down Expand Up @@ -102,13 +104,31 @@ public IDockerEnvironmentBuilder AddContainer<TParams>(TParams containerParamete
return this;
}

public IDockerEnvironmentBuilder WithContainerApi(Func<IDockerClient, ILogger?, IContainerApi> containerApiFactory)
{
_containerApiFactory = containerApiFactory;

return this;
}

public IDockerEnvironmentBuilder WithImageApi(Func<IDockerClient, ILogger?, IImageApi> imageApiFactory)
{
_imageApiFactory = imageApiFactory;

return this;
}

public IDockerEnvironment Build()
{
var containers = _containerFactories.Values.Select(cf => cf()).ToArray();

return _isWsl2
? new DockerEnvironment(_environmentName, containers, DockerClient, new DockerInWs2Initializer(DockerClient, Logger), Logger)
: new DockerEnvironment(_environmentName, containers, DockerClient, Logger);
var containerApi = _containerApiFactory?.Invoke(DockerClient, Logger) ?? new ContainerApi(DockerClient, Logger);

var imageApi = _imageApiFactory?.Invoke(DockerClient, Logger) ?? new ImageApi(DockerClient, Logger);

var dockerInitializer = _isWsl2 ? new DockerInWs2Initializer(DockerClient, Logger) : null;

return new DockerEnvironment(_environmentName, containers, imageApi, containerApi, dockerInitializer, Logger);
}
}
}
6 changes: 6 additions & 0 deletions src/TestEnvironment.Docker/IDockerEnvironmentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using Docker.DotNet;
using Microsoft.Extensions.Logging;
using TestEnvironment.Docker.ContainerOperations;
using TestEnvironment.Docker.ImageOperations;

namespace TestEnvironment.Docker
{
Expand All @@ -24,6 +26,10 @@ public interface IDockerEnvironmentBuilder
IDockerEnvironmentBuilder AddContainer<TParams>(TParams containerParameters, Func<TParams, IDockerClient, ILogger?, Container> containerFactory)
where TParams : ContainerParameters;

IDockerEnvironmentBuilder WithContainerApi(Func<IDockerClient, ILogger?, IContainerApi> containerApiFactory);

IDockerEnvironmentBuilder WithImageApi(Func<IDockerClient, ILogger?, IImageApi> imageApiFactory);

IDockerEnvironment Build();
}
}
32 changes: 32 additions & 0 deletions test/TestEnvironment.Docker.Tests/CustomContainerApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using Microsoft.Extensions.Logging;
using TestEnvironment.Docker.ContainerOperations;

namespace TestEnvironment.Docker.Tests
{
internal class CustomContainerApi : ContainerApi
{
private readonly string _namePrefix;

public CustomContainerApi(string namePrefix, IDockerClient dockerClient, ILogger logger)
: base(dockerClient, logger)
{
_namePrefix = namePrefix;
}

protected override CreateContainerParameters GetCreateContainerParameters(ContainerParameters containerParameters)
{
var createParams = base.GetCreateContainerParameters(containerParameters);

createParams.Name = $"{createParams.Name}-{_namePrefix}";

return createParams;
}
}
}
41 changes: 41 additions & 0 deletions test/TestEnvironment.Docker.Tests/DockerEnvironmentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,47 @@ public async Task AddMsSqlContainer_WhenContainerIsUp_ShouldPrintMsSqlVersion()
await PrintMssqlVersion(mssql);
}

[Fact]
public async Task AddMsSqlContainerWithCustomApi_WhenContainerIsUp_ShouldHaveCustomName()
{
// Arrange
const string nameSuffix = "custom";
const string containerName = "my-mssql";

#if DEBUG
var environment = new DockerEnvironmentBuilder(_logger)
#else
await using var environment = new DockerEnvironmentBuilder(_logger)
#endif
.SetName("test-env")
.WithContainerApi((api, l) => new CustomContainerApi(nameSuffix, api, l))
#if WSL2
.UseWsl2()
#endif
#if DEBUG
.AddMssqlContainer(p => p with
{
Name = containerName,
SAPassword = "HelloK11tt_0",
Reusable = true
})
#else
.AddMssqlContainer(p => p with
{
Name = containerName,
SAPassword = "HelloK11tt_0"
})
#endif
.Build();

// Act
await environment.UpAsync();

// Assert
var mssql = environment.GetContainer<MssqlContainer>(containerName);
Assert.EndsWith(mssql.Name, nameSuffix);
}

[Fact]
public async Task AddMariaDbContainer_WhenContainerIsUp_ShouldPrintMariaDbVersion()
{
Expand Down