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

feat: Use Docker's inspect API to get resource information #1018

Merged
merged 4 commits into from
Oct 10, 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
2 changes: 1 addition & 1 deletion src/Testcontainers/Builders/ContainerBuilder`3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public TBuilderEntity WithImage(IImage image)
}

/// <inheritdoc />
public TBuilderEntity WithImagePullPolicy(Func<ImagesListResponse, bool> imagePullPolicy)
public TBuilderEntity WithImagePullPolicy(Func<ImageInspectResponse, bool> imagePullPolicy)
{
return Clone(new ContainerConfiguration(imagePullPolicy: imagePullPolicy));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Builders/IContainerBuilder`2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public interface IContainerBuilder<out TBuilderEntity, out TContainerEntity> : I
/// <param name="imagePullPolicy">The image pull policy.</param>
/// <returns>A configured instance of <typeparamref name="TBuilderEntity" />.</returns>
[PublicAPI]
TBuilderEntity WithImagePullPolicy(Func<ImagesListResponse, bool> imagePullPolicy);
TBuilderEntity WithImagePullPolicy(Func<ImageInspectResponse, bool> imagePullPolicy);

/// <summary>
/// Sets the name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public interface IImageFromDockerfileBuilder<out TBuilderEntity>
/// <param name="imageBuildPolicy">The image build policy.</param>
/// <returns>A configured instance of <typeparamref name="TBuilderEntity" />.</returns>
[PublicAPI]
TBuilderEntity WithImageBuildPolicy(Func<ImagesListResponse, bool> imageBuildPolicy);
TBuilderEntity WithImageBuildPolicy(Func<ImageInspectResponse, bool> imageBuildPolicy);

/// <summary>
/// Removes an existing image before building it again.
Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Builders/ImageFromDockerfileBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public ImageFromDockerfileBuilder WithDockerfileDirectory(CommonDirectoryPath co
}

/// <inheritdoc />
public ImageFromDockerfileBuilder WithImageBuildPolicy(Func<ImagesListResponse, bool> imageBuildPolicy)
public ImageFromDockerfileBuilder WithImageBuildPolicy(Func<ImageInspectResponse, bool> imageBuildPolicy)
{
return Merge(DockerResourceConfiguration, new ImageFromDockerfileConfiguration(imageBuildPolicy: imageBuildPolicy));
}
Expand Down
47 changes: 29 additions & 18 deletions src/Testcontainers/Clients/DockerContainerOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace DotNet.Testcontainers.Clients
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Containers;
Expand All @@ -24,37 +24,53 @@ public DockerContainerOperations(Guid sessionId, IDockerEndpointAuthenticationCo

public async Task<IEnumerable<ContainerListResponse>> GetAllAsync(CancellationToken ct = default)
{
return (await Docker.Containers.ListContainersAsync(new ContainersListParameters { All = true }, ct)
.ConfigureAwait(false)).ToArray();
return await Docker.Containers.ListContainersAsync(new ContainersListParameters { All = true }, ct)
.ConfigureAwait(false);
}

public async Task<IEnumerable<ContainerListResponse>> GetAllAsync(FilterByProperty filters, CancellationToken ct = default)
{
return await Docker.Containers.ListContainersAsync(new ContainersListParameters { All = true, Filters = filters }, ct)
.ConfigureAwait(false);
}

public Task<ContainerListResponse> ByIdAsync(string id, CancellationToken ct = default)
public Task<ContainerInspectResponse> ByIdAsync(string id, CancellationToken ct = default)
{
return ByPropertyAsync("id", id, ct);
}

public Task<ContainerListResponse> ByNameAsync(string name, CancellationToken ct = default)
public Task<ContainerInspectResponse> ByNameAsync(string name, CancellationToken ct = default)
{
return ByPropertyAsync("name", name, ct);
}

public async Task<ContainerListResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
public async Task<ContainerInspectResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
{
var filters = new FilterByProperty { { property, value } };
return (await Docker.Containers.ListContainersAsync(new ContainersListParameters { All = true, Filters = filters }, ct)
.ConfigureAwait(false)).FirstOrDefault();
try
{
return await Docker.Containers.InspectContainerAsync(value, ct)
.ConfigureAwait(false);
}
catch (DockerApiException)
{
return null;
}
}

public async Task<bool> ExistsWithIdAsync(string id, CancellationToken ct = default)
{
return await ByIdAsync(id, ct)
.ConfigureAwait(false) != null;
var response = await ByIdAsync(id, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<bool> ExistsWithNameAsync(string name, CancellationToken ct = default)
{
return await ByNameAsync(name, ct)
.ConfigureAwait(false) != null;
var response = await ByNameAsync(name, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<long> GetExitCodeAsync(string id, CancellationToken ct = default)
Expand Down Expand Up @@ -214,10 +230,5 @@ public async Task<string> RunAsync(IContainerConfiguration configuration, Cancel
_logger.DockerContainerCreated(createContainerResponse.ID);
return createContainerResponse.ID;
}

public Task<ContainerInspectResponse> InspectAsync(string id, CancellationToken ct = default)
{
return Docker.Containers.InspectContainerAsync(id, ct);
}
}
}
44 changes: 30 additions & 14 deletions src/Testcontainers/Clients/DockerImageOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace DotNet.Testcontainers.Clients
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Images;
Expand All @@ -26,38 +27,53 @@ public DockerImageOperations(Guid sessionId, IDockerEndpointAuthenticationConfig

public async Task<IEnumerable<ImagesListResponse>> GetAllAsync(CancellationToken ct = default)
{
return (await Docker.Images.ListImagesAsync(new ImagesListParameters { All = true }, ct)
.ConfigureAwait(false)).ToArray();
return await Docker.Images.ListImagesAsync(new ImagesListParameters { All = true }, ct)
.ConfigureAwait(false);
}

public async Task<IEnumerable<ImagesListResponse>> GetAllAsync(FilterByProperty filters, CancellationToken ct = default)
{
return await Docker.Images.ListImagesAsync(new ImagesListParameters { All = true, Filters = filters }, ct)
.ConfigureAwait(false);
}

public async Task<ImagesListResponse> ByIdAsync(string id, CancellationToken ct = default)
public Task<ImageInspectResponse> ByIdAsync(string id, CancellationToken ct = default)
{
return (await GetAllAsync(ct)
.ConfigureAwait(false)).FirstOrDefault(image => image.ID.Equals(id, StringComparison.OrdinalIgnoreCase));
return ByPropertyAsync("id", id, ct);
}

public Task<ImagesListResponse> ByNameAsync(string name, CancellationToken ct = default)
public Task<ImageInspectResponse> ByNameAsync(string name, CancellationToken ct = default)
{
return ByPropertyAsync("reference", name, ct);
}

public async Task<ImagesListResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
public async Task<ImageInspectResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
{
var filters = new FilterByProperty { { property, value } };
return (await Docker.Images.ListImagesAsync(new ImagesListParameters { All = true, Filters = filters }, ct)
.ConfigureAwait(false)).FirstOrDefault();
try
{
return await Docker.Images.InspectImageAsync(value, ct)
.ConfigureAwait(false);
}
catch (DockerApiException)
{
return null;
}
}

public async Task<bool> ExistsWithIdAsync(string id, CancellationToken ct = default)
{
return await ByIdAsync(id, ct)
.ConfigureAwait(false) != null;
var response = await ByIdAsync(id, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<bool> ExistsWithNameAsync(string name, CancellationToken ct = default)
{
return await ByNameAsync(name, ct)
.ConfigureAwait(false) != null;
var response = await ByNameAsync(name, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task CreateAsync(IImage image, IDockerRegistryAuthenticationConfiguration dockerRegistryAuthConfig, CancellationToken ct = default)
Expand Down
40 changes: 28 additions & 12 deletions src/Testcontainers/Clients/DockerNetworkOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace DotNet.Testcontainers.Clients
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;
using Microsoft.Extensions.Logging;
Expand All @@ -21,14 +22,19 @@ public DockerNetworkOperations(Guid sessionId, IDockerEndpointAuthenticationConf

public async Task<IEnumerable<NetworkResponse>> GetAllAsync(CancellationToken ct = default)
{
return (await Docker.Networks.ListNetworksAsync(new NetworksListParameters(), ct)
.ConfigureAwait(false)).ToArray();
return await Docker.Networks.ListNetworksAsync(new NetworksListParameters(), ct)
.ConfigureAwait(false);
}

public async Task<NetworkResponse> ByIdAsync(string id, CancellationToken ct = default)
public async Task<IEnumerable<NetworkResponse>> GetAllAsync(FilterByProperty filters, CancellationToken ct = default)
{
return (await GetAllAsync(ct)
.ConfigureAwait(false)).FirstOrDefault(image => image.ID.Equals(id, StringComparison.OrdinalIgnoreCase));
return await Docker.Networks.ListNetworksAsync(new NetworksListParameters { Filters = filters }, ct)
.ConfigureAwait(false);
}

public Task<NetworkResponse> ByIdAsync(string id, CancellationToken ct = default)
{
return ByPropertyAsync("id", id, ct);
}

public Task<NetworkResponse> ByNameAsync(string name, CancellationToken ct = default)
Expand All @@ -38,21 +44,31 @@ public Task<NetworkResponse> ByNameAsync(string name, CancellationToken ct = def

public async Task<NetworkResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
{
var filters = new FilterByProperty { { property, value } };
return (await Docker.Networks.ListNetworksAsync(new NetworksListParameters { Filters = filters }, ct)
.ConfigureAwait(false)).FirstOrDefault();
try
{
return await Docker.Networks.InspectNetworkAsync(value, ct)
.ConfigureAwait(false);
}
catch (DockerApiException)
{
return null;
}
}

public async Task<bool> ExistsWithIdAsync(string id, CancellationToken ct = default)
{
return await ByIdAsync(id, ct)
.ConfigureAwait(false) != null;
var response = await ByIdAsync(id, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<bool> ExistsWithNameAsync(string name, CancellationToken ct = default)
{
return await ByNameAsync(name, ct)
.ConfigureAwait(false) != null;
var response = await ByNameAsync(name, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<string> CreateAsync(INetworkConfiguration configuration, CancellationToken ct = default)
Expand Down
41 changes: 31 additions & 10 deletions src/Testcontainers/Clients/DockerVolumeOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace DotNet.Testcontainers.Clients
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;
using Microsoft.Extensions.Logging;
Expand All @@ -21,13 +22,23 @@ public DockerVolumeOperations(Guid sessionId, IDockerEndpointAuthenticationConfi

public async Task<IEnumerable<VolumeResponse>> GetAllAsync(CancellationToken ct = default)
{
return (await Docker.Volumes.ListAsync(ct)
.ConfigureAwait(false)).Volumes.ToArray();
var response = await Docker.Volumes.ListAsync(ct)
.ConfigureAwait(false);

return response.Volumes;
}

public async Task<IEnumerable<VolumeResponse>> GetAllAsync(FilterByProperty filters, CancellationToken ct = default)
{
var response = await Docker.Volumes.ListAsync(new VolumesListParameters { Filters = filters }, ct)
.ConfigureAwait(false);

return response.Volumes;
}

public Task<VolumeResponse> ByIdAsync(string id, CancellationToken ct = default)
{
return Task.FromResult<VolumeResponse>(null);
return ByPropertyAsync("id", id, ct);
}

public Task<VolumeResponse> ByNameAsync(string name, CancellationToken ct = default)
Expand All @@ -37,21 +48,31 @@ public Task<VolumeResponse> ByNameAsync(string name, CancellationToken ct = defa

public async Task<VolumeResponse> ByPropertyAsync(string property, string value, CancellationToken ct = default)
{
var filters = new FilterByProperty { { property, value } };
return (await Docker.Volumes.ListAsync(new VolumesListParameters { Filters = filters }, ct)
.ConfigureAwait(false)).Volumes.FirstOrDefault();
try
{
return await Docker.Volumes.InspectAsync(value, ct)
.ConfigureAwait(false);
}
catch (DockerApiException)
{
return null;
}
}

public async Task<bool> ExistsWithIdAsync(string id, CancellationToken ct = default)
{
return await ByIdAsync(id, ct)
.ConfigureAwait(false) != null;
var response = await ByIdAsync(id, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<bool> ExistsWithNameAsync(string name, CancellationToken ct = default)
{
return await ByNameAsync(name, ct)
.ConfigureAwait(false) != null;
var response = await ByNameAsync(name, ct)
.ConfigureAwait(false);

return response != null;
}

public async Task<string> CreateAsync(IVolumeConfiguration configuration, CancellationToken ct = default)
Expand Down
4 changes: 1 addition & 3 deletions src/Testcontainers/Clients/IDockerContainerOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace DotNet.Testcontainers.Clients
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Containers;

internal interface IDockerContainerOperations : IHasListOperations<ContainerListResponse>
internal interface IDockerContainerOperations : IHasListOperations<ContainerListResponse, ContainerInspectResponse>
{
Task<long> GetExitCodeAsync(string id, CancellationToken ct = default);

Expand All @@ -30,7 +30,5 @@ internal interface IDockerContainerOperations : IHasListOperations<ContainerList
Task<ExecResult> ExecAsync(string id, IList<string> command, CancellationToken ct = default);

Task<string> RunAsync(IContainerConfiguration configuration, CancellationToken ct = default);

Task<ContainerInspectResponse> InspectAsync(string id, CancellationToken ct = default);
}
}
2 changes: 1 addition & 1 deletion src/Testcontainers/Clients/IDockerImageOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DotNet.Testcontainers.Clients
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Images;

internal interface IDockerImageOperations : IHasListOperations<ImagesListResponse>
internal interface IDockerImageOperations : IHasListOperations<ImagesListResponse, ImageInspectResponse>
{
Task CreateAsync(IImage image, IDockerRegistryAuthenticationConfiguration dockerRegistryAuthConfig, CancellationToken ct = default);

Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Clients/IDockerNetworkOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace DotNet.Testcontainers.Clients
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;

internal interface IDockerNetworkOperations : IHasListOperations<NetworkResponse>
internal interface IDockerNetworkOperations : IHasListOperations<NetworkResponse, NetworkResponse>
{
Task<string> CreateAsync(INetworkConfiguration configuration, CancellationToken ct = default);

Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Clients/IDockerVolumeOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace DotNet.Testcontainers.Clients
using Docker.DotNet.Models;
using DotNet.Testcontainers.Configurations;

internal interface IDockerVolumeOperations : IHasListOperations<VolumeResponse>
internal interface IDockerVolumeOperations : IHasListOperations<VolumeResponse, VolumeResponse>
{
Task<string> CreateAsync(IVolumeConfiguration configuration, CancellationToken ct = default);

Expand Down
Loading