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: Improve tar stream logging (copy files to container) #1050

Merged
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 @@ -184,7 +184,7 @@ public TBuilderEntity WithPortBinding(string hostPort, string containerPort)
/// <inheritdoc />
public TBuilderEntity WithResourceMapping(IResourceMapping resourceMapping)
{
var resourceMappings = new Dictionary<string, IResourceMapping> { { resourceMapping.Target, resourceMapping } };
var resourceMappings = new[] { resourceMapping };
return Clone(new ContainerConfiguration(resourceMappings: resourceMappings));
}

Expand Down
4 changes: 2 additions & 2 deletions src/Testcontainers/Clients/DockerContainerOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ public Task RemoveAsync(string id, CancellationToken ct = default)
return Docker.Containers.RemoveContainerAsync(id, new ContainerRemoveParameters { Force = true, RemoveVolumes = true }, ct);
}

public Task ExtractArchiveToContainerAsync(string id, string path, Stream tarStream, CancellationToken ct = default)
public Task ExtractArchiveToContainerAsync(string id, string path, TarOutputMemoryStream tarStream, CancellationToken ct = default)
{
_logger.CopyArchiveToDockerContainer(id, path);
_logger.CopyArchiveToDockerContainer(id, tarStream.ContentLength);
return Docker.Containers.ExtractArchiveToContainerAsync(id, new ContainerPathStatParameters { Path = path, AllowOverwriteDirWithFile = false }, tarStream, ct);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Clients/IDockerContainerOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal interface IDockerContainerOperations : IHasListOperations<ContainerList

Task RemoveAsync(string id, CancellationToken ct = default);

Task ExtractArchiveToContainerAsync(string id, string path, Stream tarStream, CancellationToken ct = default);
Task ExtractArchiveToContainerAsync(string id, string path, TarOutputMemoryStream tarStream, CancellationToken ct = default);

Task<Stream> GetArchiveFromContainerAsync(string id, string path, CancellationToken ct = default);

Expand Down
8 changes: 4 additions & 4 deletions src/Testcontainers/Clients/TestcontainersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public async Task CopyAsync(string id, IResourceMapping resourceMapping, Cancell
return;
}

using (var tarOutputMemStream = new TarOutputMemoryStream())
using (var tarOutputMemStream = new TarOutputMemoryStream(_logger))
{
await tarOutputMemStream.AddAsync(resourceMapping, ct)
.ConfigureAwait(false);
Expand All @@ -209,7 +209,7 @@ await Container.ExtractArchiveToContainerAsync(id, "/", tarOutputMemStream, ct)
/// <inheritdoc />
public async Task CopyAsync(string id, DirectoryInfo source, string target, UnixFileModes fileMode, CancellationToken ct = default)
{
using (var tarOutputMemStream = new TarOutputMemoryStream(target))
using (var tarOutputMemStream = new TarOutputMemoryStream(target, _logger))
{
await tarOutputMemStream.AddAsync(source, true, fileMode, ct)
.ConfigureAwait(false);
Expand All @@ -225,7 +225,7 @@ await Container.ExtractArchiveToContainerAsync(id, "/", tarOutputMemStream, ct)
/// <inheritdoc />
public async Task CopyAsync(string id, FileInfo source, string target, UnixFileModes fileMode, CancellationToken ct = default)
{
using (var tarOutputMemStream = new TarOutputMemoryStream(target))
using (var tarOutputMemStream = new TarOutputMemoryStream(target, _logger))
{
await tarOutputMemStream.AddAsync(source, fileMode, ct)
.ConfigureAwait(false);
Expand Down Expand Up @@ -313,7 +313,7 @@ await Network.ConnectAsync("bridge", id, ct)

if (configuration.ResourceMappings.Any())
{
await Task.WhenAll(configuration.ResourceMappings.Values.Select(resourceMapping => CopyAsync(id, resourceMapping, ct)))
await Task.WhenAll(configuration.ResourceMappings.Select(resourceMapping => CopyAsync(id, resourceMapping, ct)))
.ConfigureAwait(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class ContainerConfiguration : ResourceConfiguration<CreateContainerParam
/// <param name="environments">A dictionary of environment variables.</param>
/// <param name="exposedPorts">A dictionary of exposed ports.</param>
/// <param name="portBindings">A dictionary of port bindings.</param>
/// <param name="resourceMappings">A dictionary of resource mappings.</param>
/// <param name="resourceMappings">A list of resource mappings.</param>
/// <param name="containers">A list of containers.</param>
/// <param name="mounts">A list of mounts.</param>
/// <param name="networks">A list of networks.</param>
Expand All @@ -52,7 +52,7 @@ public ContainerConfiguration(
IReadOnlyDictionary<string, string> environments = null,
IReadOnlyDictionary<string, string> exposedPorts = null,
IReadOnlyDictionary<string, string> portBindings = null,
IReadOnlyDictionary<string, IResourceMapping> resourceMappings = null,
IEnumerable<IResourceMapping> resourceMappings = null,
IEnumerable<IContainer> containers = null,
IEnumerable<IMount> mounts = null,
IEnumerable<INetwork> networks = null,
Expand Down Expand Up @@ -178,7 +178,7 @@ public ContainerConfiguration(IContainerConfiguration oldValue, IContainerConfig
public IReadOnlyDictionary<string, string> PortBindings { get; }

/// <inheritdoc />
public IReadOnlyDictionary<string, IResourceMapping> ResourceMappings { get; }
public IEnumerable<IResourceMapping> ResourceMappings { get; }

/// <inheritdoc />
public IEnumerable<IContainer> Containers { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ public interface IContainerConfiguration : IResourceConfiguration<CreateContaine
IReadOnlyDictionary<string, string> PortBindings { get; }

/// <summary>
/// Gets a dictionary of resource mappings.
/// Gets a list of resource mappings.
/// </summary>
IReadOnlyDictionary<string, IResourceMapping> ResourceMappings { get; }
IEnumerable<IResourceMapping> ResourceMappings { get; }

/// <summary>
/// Gets a list of dependent containers.
Expand Down
31 changes: 28 additions & 3 deletions src/Testcontainers/Containers/TarOutputMemoryStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace DotNet.Testcontainers.Containers
using System.Threading.Tasks;
using DotNet.Testcontainers.Configurations;
using ICSharpCode.SharpZipLib.Tar;
using Microsoft.Extensions.Logging;

/// <summary>
/// Represent a tar archive file.
Expand All @@ -15,25 +16,41 @@ public sealed class TarOutputMemoryStream : TarOutputStream
{
private readonly string _targetDirectoryPath;

private readonly ILogger _logger;

private long _contentLength;

/// <summary>
/// Initializes a new instance of the <see cref="TarOutputMemoryStream" /> class.
/// </summary>
/// <param name="targetDirectoryPath">The target directory path to extract the files to.</param>
public TarOutputMemoryStream(string targetDirectoryPath)
: this()
/// <param name="logger">The logger.</param>
public TarOutputMemoryStream(string targetDirectoryPath, ILogger logger)
: this(logger)
{
_targetDirectoryPath = targetDirectoryPath;
}

/// <summary>
/// Initializes a new instance of the <see cref="TarOutputMemoryStream" /> class.
/// </summary>
public TarOutputMemoryStream()
/// <param name="logger">The logger.</param>
public TarOutputMemoryStream(ILogger logger)
: base(new MemoryStream(), Encoding.Default)
{
_logger = logger;
IsStreamOwner = false;
}

/// <summary>
/// Gets the content length.
/// </summary>
/// <remarks>
/// The initial tar output stream length is 10240 bytes (SharpZipLib). The stream
/// length does not correspond to the actual content's length.
/// </remarks>
public long ContentLength => _contentLength;

/// <summary>
/// Adds the content of an implementation of <see cref="IResourceMapping" /> to the archive.
/// </summary>
Expand All @@ -52,6 +69,8 @@ public async Task AddAsync(IResourceMapping resourceMapping, CancellationToken c
tarEntry.TarHeader.ModTime = DateTime.UtcNow;
tarEntry.Size = fileContent.Length;

_logger.LogInformation("Add file to tar archive: Content length: {Length} byte(s), Target file: \"{Target}\"", tarEntry.Size, targetFilePath);

await PutNextEntryAsync(tarEntry, ct)
.ConfigureAwait(false);

Expand All @@ -65,6 +84,8 @@ await WriteAsync(fileContent, 0, fileContent.Length, ct)

await CloseEntryAsync(ct)
.ConfigureAwait(false);

_ = Interlocked.Add(ref _contentLength, tarEntry.Size);
}

/// <summary>
Expand Down Expand Up @@ -116,6 +137,8 @@ public async Task AddAsync(DirectoryInfo directory, FileInfo file, UnixFileModes
tarEntry.TarHeader.ModTime = file.LastWriteTimeUtc;
tarEntry.Size = stream.Length;

_logger.LogInformation("Add file to tar archive: Source file: \"{Source}\", Target file: \"{Target}\"", tarEntry.TarHeader.Name, targetFilePath);

await PutNextEntryAsync(tarEntry, ct)
.ConfigureAwait(false);

Expand All @@ -124,6 +147,8 @@ await stream.CopyToAsync(this, 81920, ct)

await CloseEntryAsync(ct)
.ConfigureAwait(false);

_ = Interlocked.Add(ref _contentLength, tarEntry.Size);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/Testcontainers/Logging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ private static readonly Action<ILogger, string, Exception> _StartReadinessCheck
private static readonly Action<ILogger, string, Exception> _CompleteReadinessCheck
= LoggerMessage.Define<string>(LogLevel.Information, default, "Docker container {Id} ready");

private static readonly Action<ILogger, string, string, Exception> _CopyArchiveToDockerContainer
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Copy tar archive to \"{Path}\" to Docker container {Id}");
private static readonly Action<ILogger, long, string, Exception> _CopyArchiveToDockerContainer
= LoggerMessage.Define<long, string>(LogLevel.Information, default, "Copy tar archive to container: Content length: {Length} byte(s), Docker container: {Id}");

private static readonly Action<ILogger, string, string, Exception> _ReadArchiveFromDockerContainer
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Read \"{Path}\" from Docker container {Id}");
Expand Down Expand Up @@ -125,9 +125,9 @@ public static void CompleteReadinessCheck(this ILogger logger, string id)
_CompleteReadinessCheck(logger, TruncId(id), null);
}

public static void CopyArchiveToDockerContainer(this ILogger logger, string id, string path)
public static void CopyArchiveToDockerContainer(this ILogger logger, string id, long length)
{
_CopyArchiveToDockerContainer(logger, path, TruncId(id), null);
_CopyArchiveToDockerContainer(logger, length, TruncId(id), null);
}

public static void ReadArchiveFromDockerContainer(this ILogger logger, string id, string path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public abstract class TarOutputMemoryStreamTest
{
private const string TargetDirectoryPath = "/tmp";

private readonly TarOutputMemoryStream _tarOutputMemoryStream = new TarOutputMemoryStream(TargetDirectoryPath);
private readonly TarOutputMemoryStream _tarOutputMemoryStream = new TarOutputMemoryStream(TargetDirectoryPath, NullLogger.Instance);

private readonly FileInfo _testFile = new FileInfo(Path.Combine(TestSession.TempDirectoryPath, Path.GetRandomFileName()));

Expand Down
1 change: 1 addition & 0 deletions tests/Testcontainers.Platform.Linux.Tests/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
global using DotNet.Testcontainers.Containers;
global using ICSharpCode.SharpZipLib.Tar;
global using JetBrains.Annotations;
global using Microsoft.Extensions.Logging.Abstractions;
global using Xunit;

This file was deleted.