Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Cache Docker image full and host name #1043

Merged
merged 1 commit into from
Nov 5, 2023
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
5 changes: 4 additions & 1 deletion docs/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ await moduleNameContainer.StartAsync();
| Azure SQL Edge | `mcr.microsoft.com/azure-sql-edge:1.0.7` | [NuGet](https://www.nuget.org/packages/Testcontainers.SqlEdge) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.SqlEdge) |
| Azurite | `mcr.microsoft.com/azure-storage/azurite:3.24.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.Azurite) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Azurite) |
| ClickHouse | `clickhouse/clickhouse-server:23.6-alpine` | [NuGet](https://www.nuget.org/packages/Testcontainers.ClickHouse) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.ClickHouse) |
| Consul | `consul:1.15` | [NuGet](https://www.nuget.org/packages/Testcontainers.Consul) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Consul) |
| Couchbase | `couchbase:community-7.0.2` | [NuGet](https://www.nuget.org/packages/Testcontainers.Couchbase) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Couchbase) |
| CouchDB | `couchdb:3.3` | [NuGet](https://www.nuget.org/packages/Testcontainers.CouchDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.CouchDb) |
| DynamoDB | `amazon/dynamodb-local:1.21.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.DynamoDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.DynamoDb) |
| Elasticsearch | `elasticsearch:8.6.1` | [NuGet](https://www.nuget.org/packages/Testcontainers.Elasticsearch) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Elasticsearch) |
| EventStoreDB | `eventstore/eventstore:22.10.1-buster-slim` | [NuGet](https://www.nuget.org/packages/Testcontainers.EventStoreDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.EventStoreDb) |
| FakeGcsServer | `fsouza/fake-gcs-server:1.47` | [NuGet](https://www.nuget.org/packages/Testcontainers.FakeGcsServer) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.FakeGcsServer) |
| Firestore | `gcr.io/google.com/cloudsdktool/google-cloud-cli:446.0.1-emulators` | [NuGet](https://www.nuget.org/packages/Testcontainers.Firestore) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Firestore) |
| InfluxDB | `influxdb:2.7` | [NuGet](https://www.nuget.org/packages/Testcontainers.InfluxDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.InfluxDb) |
| K3s | `rancher/k3s:v1.26.2-k3s1` | [NuGet](https://www.nuget.org/packages/Testcontainers.K3s) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.K3s) |
Expand All @@ -41,10 +43,11 @@ await moduleNameContainer.StartAsync();
| MinIO | `minio/minio:RELEASE.2023-01-31T02-24-19Z` | [NuGet](https://www.nuget.org/packages/Testcontainers.Minio) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Minio) |
| MongoDB | `mongo:6.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.MongoDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.MongoDb) |
| MySQL | `mysql:8.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.MySql) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.MySql) |
| NATS | `nats:2.9` | [NuGet](https://www.nuget.org/packages/Testcontainers.Nats) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Nats) |
| NATS | `nats:2.9` | [NuGet](https://www.nuget.org/packages/Testcontainers.Nats) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Nats) |
| Neo4j | `neo4j:5.4` | [NuGet](https://www.nuget.org/packages/Testcontainers.Neo4j) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Neo4j) |
| Oracle | `gvenzl/oracle-xe:21.3.0-slim-faststart` | [NuGet](https://www.nuget.org/packages/Testcontainers.Oracle) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Oracle) |
| PostgreSQL | `postgres:15.1` | [NuGet](https://www.nuget.org/packages/Testcontainers.PostgreSql) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.PostgreSql) |
| PubSub | `gcr.io/google.com/cloudsdktool/google-cloud-cli:446.0.1-emulators` | [NuGet](https://www.nuget.org/packages/Testcontainers.PubSub) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.PubSub) |
| RabbitMQ | `rabbitmq:3.11` | [NuGet](https://www.nuget.org/packages/Testcontainers.RabbitMq) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.RabbitMq) |
| RavenDB | `ravendb/ravendb:5.4-ubuntu-latest` | [NuGet](https://www.nuget.org/packages/Testcontainers.RavenDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.RavenDb) |
| Redis | `redis:7.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.Redis) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Redis) |
Expand Down
64 changes: 45 additions & 19 deletions src/Testcontainers/Images/DockerImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ namespace DotNet.Testcontainers.Images
[PublicAPI]
public sealed class DockerImage : IImage
{
private const string LatestTag = "latest";

private static readonly Func<string, IImage> GetDockerImage = MatchImage.Match;

private static readonly char[] TrimChars = { ' ', ':', '/' };

private readonly string _hubImageNamePrefix;

private readonly Lazy<string> _lazyFullName;

private readonly Lazy<string> _lazyHostname;

/// <summary>
/// Initializes a new instance of the <see cref="DockerImage" /> class.
/// </summary>
Expand Down Expand Up @@ -44,7 +52,7 @@ public DockerImage(string image)
public DockerImage(
string repository,
string name,
string tag,
string tag = null,
string hubImageNamePrefix = null)
{
_ = Guard.Argument(repository, nameof(repository))
Expand All @@ -56,11 +64,38 @@ public DockerImage(
.NotEmpty()
.NotUppercase();

_hubImageNamePrefix = hubImageNamePrefix;
_hubImageNamePrefix = TrimOrDefault(hubImageNamePrefix);

Repository = TrimOrDefault(repository, repository);
Name = TrimOrDefault(name, name);
Tag = TrimOrDefault(tag, LatestTag);

_lazyFullName = new Lazy<string>(() =>
{
var imageComponents = new[] { _hubImageNamePrefix, Repository, Name }
.Where(imageComponent => !string.IsNullOrEmpty(imageComponent));

return string.Join("/", imageComponents) + ":" + Tag;
});

_lazyHostname = new Lazy<string>(() =>
{
var firstSegmentOfRepository = new[] { _hubImageNamePrefix, Repository }
.Where(imageComponent => !string.IsNullOrEmpty(imageComponent))
.DefaultIfEmpty(string.Empty)
.First()
.Split('/')
.First();

Repository = repository;
Name = name;
Tag = string.IsNullOrEmpty(tag) ? "latest" : tag;
if (firstSegmentOfRepository.IndexOfAny(new[] { '.', ':' }) >= 0)
{
return firstSegmentOfRepository;
}
else
{
return null;
}
});
}

/// <inheritdoc />
Expand All @@ -73,23 +108,14 @@ public DockerImage(
public string Tag { get; }

/// <inheritdoc />
public string FullName
{
get
{
var imageComponents = new[] { _hubImageNamePrefix, Repository, Name }
.Where(imageComponent => !string.IsNullOrEmpty(imageComponent))
.Select(imageComponent => imageComponent.Trim('/', ':'))
.Where(imageComponent => !string.IsNullOrEmpty(imageComponent));
return string.Join("/", imageComponents) + ":" + Tag;
}
}
public string FullName => _lazyFullName.Value;

/// <inheritdoc />
public string GetHostname()
public string GetHostname() => _lazyHostname.Value;

private static string TrimOrDefault(string value, string defaultValue = default)
{
var firstSegmentOfRepository = (string.IsNullOrEmpty(_hubImageNamePrefix) ? Repository : _hubImageNamePrefix).Split('/')[0];
return firstSegmentOfRepository.IndexOfAny(new[] { '.', ':' }) >= 0 ? firstSegmentOfRepository : null;
return string.IsNullOrEmpty(value) ? defaultValue : value.Trim(TrimChars);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public sealed class TestcontainersImageTest
public void ShouldThrowArgumentNullExceptionWhenInstantiateDockerImage()
{
Assert.Throws<ArgumentException>(() => new DockerImage((string)null));
Assert.Throws<ArgumentException>(() => new DockerImage(null, null, null));
Assert.Throws<ArgumentException>(() => new DockerImage("fedora", null, null));
Assert.Throws<ArgumentException>(() => new DockerImage(null, null));
Assert.Throws<ArgumentException>(() => new DockerImage("fedora", null));
}

[Fact]
Expand Down