From 45a8935f3783f9f70770506d30672a35eaed686a Mon Sep 17 00:00:00 2001
From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
Date: Fri, 25 Nov 2022 12:09:10 +0100
Subject: [PATCH] feat: Add Docker host and socket override custom
configuration (#691)
---
docs/custom_configuration/index.md | 24 +++++-----
.../Configurations/CustomConfiguration.cs | 10 +++++
.../EnvironmentConfiguration.cs | 18 ++++++++
.../Configurations/ICustomConfiguration.cs | 34 ++++++++++----
.../PropertiesFileConfiguration.cs | 14 ++++++
.../Containers/ResourceReaper.cs | 5 ++-
.../Configurations/CustomConfigurationTest.cs | 44 +++++++++++++++++++
7 files changed, 128 insertions(+), 21 deletions(-)
diff --git a/docs/custom_configuration/index.md b/docs/custom_configuration/index.md
index 7127ade54..1d83715bb 100644
--- a/docs/custom_configuration/index.md
+++ b/docs/custom_configuration/index.md
@@ -2,17 +2,19 @@
Testcontainers supports various configurations to set up your test environment. It automatically discovers the Docker environment and applies the configuration. You can set or override the default values either with the Testcontainers [properties file][properties-file-format] (`~/testcontainers.properties`) or with environment variables. If you prefer to configure your test environment at runtime, you can set or override the configuration through the `TestcontainersSettings` class. The following configurations are available:
-| Properties File | Environment Variable | Description | Default |
-|-------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------------------|-----------------------------|
-| `docker.config` | `DOCKER_CONFIG` | The directory path that contains the Docker configuration (`config.json`) file. | `~/.docker/` |
-| `docker.host` | `DOCKER_HOST` | The Docker daemon socket to connect to. | - |
-| `docker.auth.config` | `DOCKER_AUTH_CONFIG` | The Docker configuration file content (GitLab: [Use statically-defined credentials][use-statically-defined-credentials]). | - |
-| `docker.cert.path` | `DOCKER_CERT_PATH` | The directory path that contains the client certificate (`{ca,cert,key}.pem`) files. | `~/.docker/` |
-| `docker.tls` | `DOCKER_TLS` | Enables TLS. | false |
-| `docker.tls.verify` | `DOCKER_TLS_VERIFY` | Enables TLS verify. | false |
-| `ryuk.disabled` | `TESTCONTAINERS_RYUK_DISABLED` | Disables Ryuk (resource reaper). | false |
-| `ryuk.container.image` | `TESTCONTAINERS_RYUK_CONTAINER_IMAGE` | The Ryuk (resource reaper) Docker image. | `testcontainers/ryuk:0.3.4` |
-| `hub.image.name.prefix` | `TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX` | The name to use for substituting the Docker Hub registry part of the image name. | - |
+| Properties File | Environment Variable | Description | Default |
+|--------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------|-----------------------------|
+| `docker.config` | `DOCKER_CONFIG` | The directory path that contains the Docker configuration (`config.json`) file. | `~/.docker/` |
+| `docker.host` | `DOCKER_HOST` | The Docker daemon socket to connect to. | - |
+| `docker.auth.config` | `DOCKER_AUTH_CONFIG` | The Docker configuration file content (GitLab: [Use statically-defined credentials][use-statically-defined-credentials]). | - |
+| `docker.cert.path` | `DOCKER_CERT_PATH` | The directory path that contains the client certificate (`{ca,cert,key}.pem`) files. | `~/.docker/` |
+| `docker.tls` | `DOCKER_TLS` | Enables TLS. | `false` |
+| `docker.tls.verify` | `DOCKER_TLS_VERIFY` | Enables TLS verify. | `false` |
+| `host.override` | `TESTCONTAINERS_HOST_OVERRIDE` | The host that exposes Docker's ports. | - |
+| `docker.socket.override` | `TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE` | The file path to the Docker daemon socket that is used by Ryuk (resource reaper). | `/var/run/docker.sock` |
+| `ryuk.disabled` | `TESTCONTAINERS_RYUK_DISABLED` | Disables Ryuk (resource reaper). | `false` |
+| `ryuk.container.image` | `TESTCONTAINERS_RYUK_CONTAINER_IMAGE` | The Ryuk (resource reaper) Docker image. | `testcontainers/ryuk:0.3.4` |
+| `hub.image.name.prefix` | `TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX` | The name to use for substituting the Docker Hub registry part of the image name. | - |
## Enable logging
diff --git a/src/Testcontainers/Configurations/CustomConfiguration.cs b/src/Testcontainers/Configurations/CustomConfiguration.cs
index 23b818dd8..86a754d43 100644
--- a/src/Testcontainers/Configurations/CustomConfiguration.cs
+++ b/src/Testcontainers/Configurations/CustomConfiguration.cs
@@ -24,6 +24,16 @@ protected Uri GetDockerHost(string propertyName)
return this.properties.TryGetValue(propertyName, out var propertyValue) && Uri.TryCreate(propertyValue, UriKind.RelativeOrAbsolute, out var dockerHost) ? dockerHost : null;
}
+ protected string GetDockerHostOverride(string propertyName)
+ {
+ return this.GetPropertyValue(propertyName);
+ }
+
+ protected string GetDockerSocketOverride(string propertyName)
+ {
+ return this.GetPropertyValue(propertyName);
+ }
+
protected JsonDocument GetDockerAuthConfig(string propertyName)
{
_ = this.properties.TryGetValue(propertyName, out var propertyValue);
diff --git a/src/Testcontainers/Configurations/EnvironmentConfiguration.cs b/src/Testcontainers/Configurations/EnvironmentConfiguration.cs
index 8056df9cc..ef2f84456 100644
--- a/src/Testcontainers/Configurations/EnvironmentConfiguration.cs
+++ b/src/Testcontainers/Configurations/EnvironmentConfiguration.cs
@@ -22,6 +22,10 @@ internal sealed class EnvironmentConfiguration : CustomConfiguration, ICustomCon
private const string DockerTlsVerify = "DOCKER_TLS_VERIFY";
+ private const string DockerHostOverride = "TESTCONTAINERS_HOST_OVERRIDE";
+
+ private const string DockerSocketOverride = "TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE";
+
private const string RyukDisabled = "TESTCONTAINERS_RYUK_DISABLED";
private const string RyukContainerImage = "TESTCONTAINERS_RYUK_CONTAINER_IMAGE";
@@ -44,6 +48,8 @@ public EnvironmentConfiguration()
DockerHost,
DockerTls,
DockerTlsVerify,
+ DockerHostOverride,
+ DockerSocketOverride,
RyukDisabled,
RyukContainerImage,
HubImageNamePrefix,
@@ -70,6 +76,18 @@ public Uri GetDockerHost()
return this.GetDockerHost(DockerHost);
}
+ ///
+ public string GetDockerHostOverride()
+ {
+ return this.GetDockerHostOverride(DockerHostOverride);
+ }
+
+ ///
+ public string GetDockerSocketOverride()
+ {
+ return this.GetDockerSocketOverride(DockerSocketOverride);
+ }
+
///
public JsonDocument GetDockerAuthConfig()
{
diff --git a/src/Testcontainers/Configurations/ICustomConfiguration.cs b/src/Testcontainers/Configurations/ICustomConfiguration.cs
index 2c6b3453e..32edee2d5 100644
--- a/src/Testcontainers/Configurations/ICustomConfiguration.cs
+++ b/src/Testcontainers/Configurations/ICustomConfiguration.cs
@@ -14,7 +14,7 @@ internal interface ICustomConfiguration
/// Gets the Docker config custom configuration.
///
/// The Docker config custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
string GetDockerConfig();
@@ -22,15 +22,31 @@ internal interface ICustomConfiguration
/// Gets the Docker host custom configuration.
///
/// The Docker host custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
Uri GetDockerHost();
+ ///
+ /// Gets the Docker host override custom configuration.
+ ///
+ /// The Docker host override custom configuration.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
+ [CanBeNull]
+ string GetDockerHostOverride();
+
+ ///
+ /// Gets the Docker socket override custom configuration.
+ ///
+ /// The Docker socket override custom configuration.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
+ [CanBeNull]
+ string GetDockerSocketOverride();
+
///
/// Gets the Docker registry authentication custom configuration.
///
/// The Docker authentication custom configuration.
- /// https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#access-an-image-from-a-private-container-registry.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
JsonDocument GetDockerAuthConfig();
@@ -38,7 +54,7 @@ internal interface ICustomConfiguration
/// Gets the Docker certificates path custom configuration.
///
/// The Docker certificates path custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
string GetDockerCertPath();
@@ -46,28 +62,28 @@ internal interface ICustomConfiguration
/// Gets the Docker TLS custom configuration.
///
/// The Docker TLS custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
bool GetDockerTls();
///
/// Gets the Docker TLS verify custom configuration.
///
/// The Docker TLS verify custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
bool GetDockerTlsVerify();
///
/// Gets the Ryuk disabled custom configuration.
///
/// The Ryuk disabled custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-ryuk-resource-reaper.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
bool GetRyukDisabled();
///
/// Gets the Ryuk container image custom configuration.
///
/// The Ryuk container image custom configuration.
- /// https://www.testcontainers.org/features/configuration/#customizing-ryuk-resource-reaper.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
IDockerImage GetRyukContainerImage();
@@ -75,7 +91,7 @@ internal interface ICustomConfiguration
/// Gets the Docker Hub image name prefix custom configuration.
///
/// The Docker Hub image name prefix custom configuration.
- /// https://www.testcontainers.org/features/image_name_substitution/.
+ /// https://dotnet.testcontainers.org/custom_configuration/.
[CanBeNull]
string GetHubImageNamePrefix();
}
diff --git a/src/Testcontainers/Configurations/PropertiesFileConfiguration.cs b/src/Testcontainers/Configurations/PropertiesFileConfiguration.cs
index d77124f0f..81f9f3e2c 100644
--- a/src/Testcontainers/Configurations/PropertiesFileConfiguration.cs
+++ b/src/Testcontainers/Configurations/PropertiesFileConfiguration.cs
@@ -70,6 +70,20 @@ public Uri GetDockerHost()
return this.GetDockerHost(propertyName);
}
+ ///
+ public string GetDockerHostOverride()
+ {
+ const string propertyName = "host.override";
+ return this.GetDockerHostOverride(propertyName);
+ }
+
+ ///
+ public string GetDockerSocketOverride()
+ {
+ const string propertyName = "docker.socket.override";
+ return this.GetDockerSocketOverride(propertyName);
+ }
+
///
public JsonDocument GetDockerAuthConfig()
{
diff --git a/src/Testcontainers/Containers/ResourceReaper.cs b/src/Testcontainers/Containers/ResourceReaper.cs
index aa4de4e6e..b73c0980d 100644
--- a/src/Testcontainers/Containers/ResourceReaper.cs
+++ b/src/Testcontainers/Containers/ResourceReaper.cs
@@ -22,10 +22,13 @@ public sealed class ResourceReaper : IAsyncDisposable
private const ushort RyukPort = 8080;
///
- /// 60 seconds timeout.
+ /// 60 seconds connection timeout.
///
private const int ConnectionTimeoutInSeconds = 60;
+ ///
+ /// 2 seconds retry timeout.
+ ///
private const int RetryTimeoutInSeconds = 2;
private static readonly SemaphoreSlim DefaultLock = new SemaphoreSlim(1, 1);
diff --git a/tests/Testcontainers.Tests/Unit/Configurations/CustomConfigurationTest.cs b/tests/Testcontainers.Tests/Unit/Configurations/CustomConfigurationTest.cs
index 56d9bdae3..5f259234b 100644
--- a/tests/Testcontainers.Tests/Unit/Configurations/CustomConfigurationTest.cs
+++ b/tests/Testcontainers.Tests/Unit/Configurations/CustomConfigurationTest.cs
@@ -21,6 +21,8 @@ static EnvironmentConfigurationTest()
EnvironmentVariables.Add("DOCKER_CERT_PATH");
EnvironmentVariables.Add("DOCKER_TLS");
EnvironmentVariables.Add("DOCKER_TLS_VERIFY");
+ EnvironmentVariables.Add("TESTCONTAINERS_HOST_OVERRIDE");
+ EnvironmentVariables.Add("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE");
EnvironmentVariables.Add("TESTCONTAINERS_RYUK_DISABLED");
EnvironmentVariables.Add("TESTCONTAINERS_RYUK_CONTAINER_IMAGE");
EnvironmentVariables.Add("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX");
@@ -48,6 +50,28 @@ public void GetDockerHostCustomConfiguration(string propertyName, string propert
Assert.Equal(expected, customConfiguration.GetDockerHost()?.ToString());
}
+ [Theory]
+ [InlineData("", "", null)]
+ [InlineData("TESTCONTAINERS_HOST_OVERRIDE", "", null)]
+ [InlineData("TESTCONTAINERS_HOST_OVERRIDE", "docker.svc.local", "docker.svc.local")]
+ public void GetDockerHostOverrideCustomConfiguration(string propertyName, string propertyValue, string expected)
+ {
+ SetEnvironmentVariable(propertyName, propertyValue);
+ ICustomConfiguration customConfiguration = new EnvironmentConfiguration();
+ Assert.Equal(expected, customConfiguration.GetDockerHostOverride());
+ }
+
+ [Theory]
+ [InlineData("", "", null)]
+ [InlineData("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "", null)]
+ [InlineData("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "/var/run/docker.sock", "/var/run/docker.sock")]
+ public void GetDockerSocketOverrideCustomConfiguration(string propertyName, string propertyValue, string expected)
+ {
+ SetEnvironmentVariable(propertyName, propertyValue);
+ ICustomConfiguration customConfiguration = new EnvironmentConfiguration();
+ Assert.Equal(expected, customConfiguration.GetDockerSocketOverride());
+ }
+
[Theory]
[InlineData("", "", null)]
[InlineData("DOCKER_AUTH_CONFIG", "", null)]
@@ -179,6 +203,26 @@ public void GetDockerHostCustomConfiguration(string configuration, string expect
Assert.Equal(expected, customConfiguration.GetDockerHost()?.ToString());
}
+ [Theory]
+ [InlineData("", null)]
+ [InlineData("host.override=", null)]
+ [InlineData("host.override=docker.svc.local", "docker.svc.local")]
+ public void GetDockerHostOverrideCustomConfiguration(string configuration, string expected)
+ {
+ ICustomConfiguration customConfiguration = new PropertiesFileConfiguration(new[] { configuration });
+ Assert.Equal(expected, customConfiguration.GetDockerHostOverride());
+ }
+
+ [Theory]
+ [InlineData("", null)]
+ [InlineData("docker.socket.override=", null)]
+ [InlineData("docker.socket.override=/var/run/docker.sock", "/var/run/docker.sock")]
+ public void GetDockerSocketOverrideCustomConfiguration(string configuration, string expected)
+ {
+ ICustomConfiguration customConfiguration = new PropertiesFileConfiguration(new[] { configuration });
+ Assert.Equal(expected, customConfiguration.GetDockerSocketOverride());
+ }
+
[Theory]
[InlineData("", null)]
[InlineData("docker.auth.config=", null)]