Skip to content

Commit

Permalink
[#464] #BUGFIX 'assemblyName: DotNet.Testcontainers; function: Resour…
Browse files Browse the repository at this point in the history
…ceReaper'

{Add optional Docker API endpoint.}
  • Loading branch information
s-rech authored and HofmeisterAn committed May 31, 2022
1 parent 3c370b1 commit c0b0997
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/DotNet.Testcontainers/Clients/TestcontainersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public async Task<string> RunAsync(ITestcontainersConfiguration configuration, C

if (!isWindowsEngineEnabled && ResourceReaper.DefaultSessionId.ToString("D").Equals(configuration.Labels[ResourceReaper.ResourceReaperSessionLabel], StringComparison.OrdinalIgnoreCase))
{
_ = await ResourceReaper.GetAndStartDefaultAsync(ct)
_ = await ResourceReaper.GetAndStartDefaultAsync(configuration.Endpoint, ct)
.ConfigureAwait(false);
}

Expand Down
23 changes: 15 additions & 8 deletions src/DotNet.Testcontainers/Containers/ResourceReaper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ public sealed class ResourceReaper : IAsyncDisposable

private bool disposed;

private ResourceReaper(Guid sessionId, string ryukImage)
private ResourceReaper(Guid sessionId, Uri endpoint, string ryukImage)
{
this.resourceReaperContainer = new TestcontainersBuilder<TestcontainersContainer>()
.WithDockerEndpoint((endpoint ?? TestcontainersSettings.OS.DockerApiEndpoint).ToString())
.WithName($"testcontainers-ryuk-{sessionId:D}")
.WithImage(ryukImage)
.WithAutoRemove(true)
Expand All @@ -64,7 +65,7 @@ private ResourceReaper(Guid sessionId, string ryukImage)
/// Gets the default <see cref="ResourceReaper" /> session id.
/// </summary>
/// <remarks>
/// The default <see cref="ResourceReaper" /> will start either on <see cref="GetAndStartDefaultAsync(CancellationToken)" />
/// The default <see cref="ResourceReaper" /> will start either on <see cref="GetAndStartDefaultAsync(Uri, CancellationToken)" />
/// or if a <see cref="ITestcontainersContainer" /> is configured with <see cref="ITestcontainersBuilder{TDockerContainer}.WithCleanUp" />.
/// </remarks>
[PublicAPI]
Expand All @@ -80,10 +81,12 @@ private ResourceReaper(Guid sessionId, string ryukImage)
/// <summary>
/// Starts and returns the default <see cref="ResourceReaper" /> instance.
/// </summary>
/// <param name="endpoint">The Docker API endpoint.</param>
/// <param name="ct">The cancellation token to cancel the <see cref="ResourceReaper" /> initialization.</param>
/// <returns>Task that completes when the <see cref="ResourceReaper" /> has been started.</returns>
/// <remarks>If <paramref name="endpoint" /> is null, the resource reaper will fallback to the default Docker API endpoint.</remarks>
[PublicAPI]
public static async Task<ResourceReaper> GetAndStartDefaultAsync(CancellationToken ct = default)
public static async Task<ResourceReaper> GetAndStartDefaultAsync(Uri endpoint = null, CancellationToken ct = default)
{
if (defaultInstance != null && !defaultInstance.disposed)
{
Expand All @@ -101,7 +104,7 @@ await DefaultLock.WaitAsync(ct)

try
{
defaultInstance = await GetAndStartNewAsync(DefaultSessionId, RyukImage, default, ct)
defaultInstance = await GetAndStartNewAsync(DefaultSessionId, endpoint, RyukImage, default, ct)
.ConfigureAwait(false);

return defaultInstance;
Expand All @@ -115,30 +118,34 @@ await DefaultLock.WaitAsync(ct)
/// <summary>
/// Starts and returns a new <see cref="ResourceReaper" /> instance.
/// </summary>
/// <param name="endpoint">The Docker API endpoint.</param>
/// <param name="ryukImage">The Ryuk image.</param>
/// <param name="initTimeout">The timeout to initialize the Ryuk connection (Default: 10 seconds).</param>
/// <param name="ct">The cancellation token to cancel the <see cref="ResourceReaper" /> initialization.</param>
/// <returns>Task that completes when the <see cref="ResourceReaper" /> has been started.</returns>
/// <remarks>If <paramref name="endpoint" /> is null, the resource reaper will fallback to the default Docker API endpoint.</remarks>
[PublicAPI]
public static Task<ResourceReaper> GetAndStartNewAsync(string ryukImage = RyukImage, TimeSpan initTimeout = default, CancellationToken ct = default)
public static Task<ResourceReaper> GetAndStartNewAsync(Uri endpoint = null, string ryukImage = RyukImage, TimeSpan initTimeout = default, CancellationToken ct = default)
{
return GetAndStartNewAsync(Guid.NewGuid(), ryukImage, initTimeout, ct);
return GetAndStartNewAsync(Guid.NewGuid(), endpoint, ryukImage, initTimeout, ct);
}

/// <summary>
/// Starts and returns a new <see cref="ResourceReaper" /> instance.
/// </summary>
/// <param name="sessionId">The session id.</param>
/// <param name="endpoint">The Docker API endpoint.</param>
/// <param name="ryukImage">The Ryuk image.</param>
/// <param name="initTimeout">The timeout to initialize the Ryuk connection (Default: 10 seconds).</param>
/// <param name="ct">The cancellation token to cancel the <see cref="ResourceReaper" /> initialization.</param>
/// <returns>Task that completes when the <see cref="ResourceReaper" /> has been started.</returns>
/// <remarks>If <paramref name="endpoint" /> is null, the resource reaper will fallback to the default Docker API endpoint.</remarks>
[PublicAPI]
public static async Task<ResourceReaper> GetAndStartNewAsync(Guid sessionId, string ryukImage = RyukImage, TimeSpan initTimeout = default, CancellationToken ct = default)
public static async Task<ResourceReaper> GetAndStartNewAsync(Guid sessionId, Uri endpoint = null, string ryukImage = RyukImage, TimeSpan initTimeout = default, CancellationToken ct = default)
{
var ryukInitializedTaskSource = new TaskCompletionSource<bool>();

var resourceReaper = new ResourceReaper(sessionId, ryukImage);
var resourceReaper = new ResourceReaper(sessionId, endpoint, ryukImage);

initTimeout = TimeSpan.Equals(default, initTimeout) ? TimeSpan.FromSeconds(10) : initTimeout;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ await resourceReaper.DisposeAsync()
[Fact]
public async Task ResourceReaperShouldTimeoutIfInitializationFails()
{
var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, "alpine");
var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "alpine");
_ = await Assert.ThrowsAsync<ResourceReaperException>(() => resourceReaperTask);
Assert.Equal(new[] { ResourceReaperState.Created, ResourceReaperState.InitializingConnection }, this.stateChanges);
}
Expand All @@ -51,7 +51,7 @@ public async Task GetAndStartNewAsyncShouldBeCancellableDuringContainerStart()
{
ResourceReaper.StateChanged += this.CancelOnCreated;

var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, "alpine", TimeSpan.FromSeconds(60), this.cts.Token);
var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "alpine", TimeSpan.FromSeconds(60), this.cts.Token);
_ = await Assert.ThrowsAnyAsync<OperationCanceledException>(() => resourceReaperTask);
Assert.Equal(new[] { ResourceReaperState.Created }, this.stateChanges);
}
Expand All @@ -61,7 +61,7 @@ public async Task GetAndStartNewAsyncShouldBeCancellableDuringInitializingConnec
{
ResourceReaper.StateChanged += this.CancelOnInitializingConnection;

var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, "alpine", TimeSpan.FromSeconds(60), this.cts.Token);
var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "alpine", TimeSpan.FromSeconds(60), this.cts.Token);
_ = await Assert.ThrowsAsync<ResourceReaperException>(() => resourceReaperTask);
Assert.Equal(new[] { ResourceReaperState.Created, ResourceReaperState.InitializingConnection }, this.stateChanges);
}
Expand Down

0 comments on commit c0b0997

Please sign in to comment.