Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion src/Testcontainers.Kafka/KafkaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ protected override void Validate()

base.Validate();

Predicate<KafkaVendor?> vendorNotFound = value => value == null && !VendorConfigurations.Any(v => v.IsImageFromVendor(DockerResourceConfiguration.Image));
Predicate<KafkaVendor?> vendorNotFound = value =>
value == null && !VendorConfigurations.Any(v => v.IsImageFromVendor(DockerResourceConfiguration.Image));

_ = Guard.Argument(DockerResourceConfiguration.Vendor, nameof(DockerResourceConfiguration.Vendor))
.ThrowIf(argument => vendorNotFound(argument.Value), argument => new ArgumentException(message, argument.Name));
Expand Down
14 changes: 14 additions & 0 deletions src/Testcontainers.LocalStack/LocalStackBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ protected override LocalStackBuilder Init()
request.ForPath("/_localstack/health").ForPort(LocalStackPort)));
}

/// <inheritdoc />
protected override void Validate()
{
const string message = "The image '{0}' requires the LOCALSTACK_AUTH_TOKEN environment variable for LocalStack 4.15 and onwards. For more information, see https://blog.localstack.cloud/localstack-single-image-next-steps/.";

base.Validate();

Predicate<LocalStackConfiguration> requiresAuthToken = value =>
!value.Environments.TryGetValue("LOCALSTACK_AUTH_TOKEN", out _) && (value.Image.MatchLatestOrNightly() || value.Image.MatchVersion(v => v.Major > 4 || v.Major == 4 && v.Minor > 14));

_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Image))
.ThrowIf(argument => requiresAuthToken(argument.Value), argument => new ArgumentException(string.Format(message, argument.Value.Image.FullName), argument.Name));
}

/// <inheritdoc />
protected override LocalStackBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
{
Expand Down
1 change: 1 addition & 0 deletions src/Testcontainers.LocalStack/Usings.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
global using System;
global using System.Diagnostics.CodeAnalysis;
global using Docker.DotNet.Models;
global using DotNet.Testcontainers;
global using DotNet.Testcontainers.Builders;
global using DotNet.Testcontainers.Configurations;
global using DotNet.Testcontainers.Containers;
Expand Down
6 changes: 3 additions & 3 deletions src/Testcontainers.Neo4j/Neo4jBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ protected override void Validate()

base.Validate();

Predicate<Neo4jConfiguration> licenseAgreementNotAccepted = value => value.Image.Tag != null && value.Image.Tag.Contains("enterprise")
&& (!value.Environments.TryGetValue(AcceptLicenseAgreementEnvVar, out var licenseAgreementValue) || !AcceptLicenseAgreement.Equals(licenseAgreementValue, StringComparison.Ordinal));
Predicate<Neo4jConfiguration> licenseAgreementNotAccepted = value =>
value.Image.Tag != null && value.Image.Tag.Contains("enterprise") && (!value.Environments.TryGetValue(AcceptLicenseAgreementEnvVar, out var licenseAgreementValue) || !AcceptLicenseAgreement.Equals(licenseAgreementValue, StringComparison.Ordinal));

_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Image))
.ThrowIf(argument => licenseAgreementNotAccepted(argument.Value), argument => new ArgumentException(string.Format(message, DockerResourceConfiguration.Image.FullName), argument.Name));
.ThrowIf(argument => licenseAgreementNotAccepted(argument.Value), argument => new ArgumentException(string.Format(message, argument.Value.Image.FullName), argument.Name));
}

/// <inheritdoc />
Expand Down
6 changes: 3 additions & 3 deletions src/Testcontainers.Oracle/OracleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ protected override OracleBuilder Init()
/// <inheritdoc />
protected override void Validate()
{
base.Validate();

const string message = "The image '{0}' does not support configuring the database. It is only supported on Oracle 18 and onwards.";

base.Validate();

Predicate<OracleConfiguration> databaseConfigurationNotSupported = value =>
value.Database != null && value.Image.MatchVersion(v => v.Major < 18);

_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Database))
.ThrowIf(argument => databaseConfigurationNotSupported(argument.Value), _ => new NotSupportedException(string.Format(message, DockerResourceConfiguration.Image.FullName)));
.ThrowIf(argument => databaseConfigurationNotSupported(argument.Value), argument => new NotSupportedException(string.Format(message, argument.Value.Image.FullName)));

_ = Guard.Argument(DockerResourceConfiguration.Username, nameof(DockerResourceConfiguration.Username))
.NotNull()
Expand Down
6 changes: 3 additions & 3 deletions src/Testcontainers/Builders/AbstractBuilder`4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,14 @@ protected virtual TBuilderEntity Init()
/// <exception cref="ArgumentException">Thrown when a mandatory Docker resource configuration is not set.</exception>
protected virtual void Validate()
{
_ = Guard.Argument(DockerResourceConfiguration.Logger, nameof(IResourceConfiguration<TCreateResourceEntity>.Logger))
_ = Guard.Argument(DockerResourceConfiguration.Logger, nameof(DockerResourceConfiguration.Logger))
.NotNull();

_ = Guard.Argument(DockerResourceConfiguration.DockerEndpointAuthConfig, nameof(IResourceConfiguration<TCreateResourceEntity>.DockerEndpointAuthConfig))
_ = Guard.Argument(DockerResourceConfiguration.DockerEndpointAuthConfig, nameof(DockerResourceConfiguration.DockerEndpointAuthConfig))
.ThrowIf(argument => argument.Value == null, CreateDockerUnavailableException);

const string reuseNotSupported = "Reuse cannot be used in conjunction with WithCleanUp(true).";
_ = Guard.Argument(DockerResourceConfiguration, nameof(IResourceConfiguration<TCreateResourceEntity>.Reuse))
_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Reuse))
.ThrowIf(argument => argument.Value.Reuse.HasValue && argument.Value.Reuse.Value && !Guid.Empty.Equals(argument.Value.SessionId), argument => new ArgumentException(reuseNotSupported, argument.Name));
}

Expand Down
6 changes: 3 additions & 3 deletions src/Testcontainers/Builders/ContainerBuilder`3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,10 +497,10 @@ protected override void Validate()
base.Validate();

const string reuseNotSupported = "Reuse cannot be used in conjunction with WithAutoRemove(true).";
_ = Guard.Argument(DockerResourceConfiguration, nameof(IContainerConfiguration.Reuse))
_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Reuse))
.ThrowIf(argument => argument.Value.Reuse.HasValue && argument.Value.Reuse.Value && argument.Value.AutoRemove.HasValue && argument.Value.AutoRemove.Value, argument => new ArgumentException(reuseNotSupported, argument.Name));

_ = Guard.Argument(DockerResourceConfiguration.Image, nameof(IContainerConfiguration.Image))
_ = Guard.Argument(DockerResourceConfiguration.Image, nameof(DockerResourceConfiguration.Image))
.NotNull();
}

Expand All @@ -516,7 +516,7 @@ protected virtual void ValidateLicenseAgreement()
!value.Environments.TryGetValue(AcceptLicenseAgreementEnvVar, out var licenseAgreementValue) || !AcceptLicenseAgreement.Equals(licenseAgreementValue, StringComparison.Ordinal);

_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Image))
.ThrowIf(argument => licenseAgreementNotAccepted(argument.Value), argument => new ArgumentException(string.Format(message, DockerResourceConfiguration.Image.FullName), argument.Name));
.ThrowIf(argument => licenseAgreementNotAccepted(argument.Value), argument => new ArgumentException(string.Format(message, argument.Value.Image.FullName), argument.Name));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ protected override void Validate()
base.Validate();

const string reuseNotSupported = "Building an image does not support the reuse feature. To keep the built image, disable the cleanup.";
_ = Guard.Argument(DockerResourceConfiguration, nameof(IImageFromDockerfileConfiguration.Reuse))
_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Reuse))
.ThrowIf(argument => argument.Value.Reuse.HasValue && argument.Value.Reuse.Value, argument => new ArgumentException(reuseNotSupported, argument.Name));
}

Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Builders/NetworkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected override void Validate()
{
base.Validate();

_ = Guard.Argument(DockerResourceConfiguration.Name, nameof(INetworkConfiguration.Name))
_ = Guard.Argument(DockerResourceConfiguration.Name, nameof(DockerResourceConfiguration.Name))
.NotNull()
.NotEmpty();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Builders/VolumeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ protected override void Validate()
{
base.Validate();

_ = Guard.Argument(DockerResourceConfiguration.Name, nameof(IVolumeConfiguration.Name))
_ = Guard.Argument(DockerResourceConfiguration.Name, nameof(DockerResourceConfiguration.Name))
.NotNull()
.NotEmpty();
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Testcontainers.LocalStack.Tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
FROM localstack/localstack:2.0.2@sha256:2b4ec60261238bfc9573193380724ed4b9ee9fa0f39726275cd8feb48a254219
FROM localstack/localstack:4.14.0@sha256:3ebc37595918b8accb852f8048fef2aff047d465167edd655528065b07bc364a
FROM localstack/localstack:1.4.0@sha256:7badf31c550f81151c485980e17542592942d7f05acc09723c5f276d41b5927d AS v1_4_0
38 changes: 38 additions & 0 deletions tests/Testcontainers.LocalStack.Tests/LocalStackBuilderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Testcontainers.LocalStack;

public sealed class LocalStackBuilderTest
{
[Fact]
public void LocalStack415WithoutAuthTokenThrowsArgumentException()
{
const string message = "The image 'localstack/localstack:4.15.0' requires the LOCALSTACK_AUTH_TOKEN environment variable for LocalStack 4.15 and onwards.";
ExpectArgEx(message, () => new LocalStackBuilder("localstack/localstack:4.15.0").Build());
}

[Fact]
public void LocalStack500WithoutAuthTokenThrowsArgumentException()
{
const string message = "The image 'localstack/localstack:5.0.0' requires the LOCALSTACK_AUTH_TOKEN environment variable for LocalStack 4.15 and onwards.";
ExpectArgEx(message, () => new LocalStackBuilder("localstack/localstack:5.0.0").Build());
}

[Fact]
public void LocalStack414WithoutAuthTokenDoesNotThrowArgumentException()
{
var exception = Xunit.Record.Exception(() => new LocalStackBuilder("localstack/localstack:4.14.0").Build());
Assert.Null(exception);
}

[Fact]
public void LocalStack415WithAuthTokenDoesNotThrowArgumentException()
{
var exception = Xunit.Record.Exception(() => new LocalStackBuilder("localstack/localstack:4.15.0").WithEnvironment("LOCALSTACK_AUTH_TOKEN", "<auth-token>").Build());
Assert.Null(exception);
}

private static void ExpectArgEx(string expectedStartString, Action testCode)
{
var exception = Assert.Throws<ArgumentException>(testCode);
Assert.StartsWith(expectedStartString, exception.Message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ internal void AuthProviderShouldBeApplicable(IDockerEndpointAuthenticationProvid
[ClassData(typeof(AuthConfigTestData))]
internal void AuthConfigShouldGetDockerClientEndpoint(IDockerEndpointAuthenticationConfiguration authConfig, Uri dockerClientEndpoint)
{
var dockerClient = authConfig.GetDockerClientBuilder().Build();
Assert.Equal(dockerClientEndpoint, authConfig.Endpoint);
Assert.Equal(dockerClientEndpoint, dockerClient.Options.Endpoint);
using (var dockerClient = authConfig.GetDockerClientBuilder().Build())
{
Assert.Equal(dockerClientEndpoint, authConfig.Endpoint);
Assert.Equal(dockerClientEndpoint, dockerClient.Options.Endpoint);
}
}

public sealed class TestcontainersHostEndpointAuthenticationProviderTest
Expand Down
Loading