Skip to content

Commit

Permalink
feat: Improve tar stream logging (copy files to container) (#1050)
Browse files Browse the repository at this point in the history
  • Loading branch information
HofmeisterAn authored Nov 13, 2023
1 parent 8368ceb commit 2229e96
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 96 deletions.
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.

0 comments on commit 2229e96

Please sign in to comment.