diff --git a/src/Testcontainers/Builders/ContainerBuilder`3.cs b/src/Testcontainers/Builders/ContainerBuilder`3.cs
index f8b3b0859..0ca8b2933 100644
--- a/src/Testcontainers/Builders/ContainerBuilder`3.cs
+++ b/src/Testcontainers/Builders/ContainerBuilder`3.cs
@@ -255,12 +255,6 @@ public TBuilderEntity WithTmpfsMount(string destination, AccessMode accessMode)
return WithMount(new TmpfsMount(destination, accessMode));
}
- ///
- public TBuilderEntity WithNetwork(string id, string name)
- {
- return WithNetwork(name);
- }
-
///
public TBuilderEntity WithNetwork(string name)
{
diff --git a/src/Testcontainers/Clients/DockerContainerOperations.cs b/src/Testcontainers/Clients/DockerContainerOperations.cs
index a9e783844..72121bee0 100644
--- a/src/Testcontainers/Clients/DockerContainerOperations.cs
+++ b/src/Testcontainers/Clients/DockerContainerOperations.cs
@@ -102,13 +102,13 @@ public Task RemoveAsync(string id, CancellationToken ct = default)
public Task ExtractArchiveToContainerAsync(string id, string path, Stream tarStream, CancellationToken ct = default)
{
- _logger.ExtractArchiveToDockerContainer(id, path);
+ _logger.CopyArchiveToDockerContainer(id, path);
return Docker.Containers.ExtractArchiveToContainerAsync(id, new ContainerPathStatParameters { Path = path, AllowOverwriteDirWithFile = false }, tarStream, ct);
}
public async Task GetArchiveFromContainerAsync(string id, string path, CancellationToken ct = default)
{
- _logger.GetArchiveFromDockerContainer(id, path);
+ _logger.ReadArchiveFromDockerContainer(id, path);
var tarResponse = await Docker.Containers.GetArchiveFromContainerAsync(id, new GetArchiveFromContainerParameters { Path = path }, false, ct)
.ConfigureAwait(false);
diff --git a/src/Testcontainers/Clients/TraceProgress.cs b/src/Testcontainers/Clients/TraceProgress.cs
index 95264ae18..f03aa11c7 100644
--- a/src/Testcontainers/Clients/TraceProgress.cs
+++ b/src/Testcontainers/Clients/TraceProgress.cs
@@ -19,17 +19,17 @@ public void Report(JSONMessage value)
if (!string.IsNullOrWhiteSpace(value.Status))
{
- _logger.LogTrace(value.Status);
+ _logger.LogDebug(value.Status);
}
if (!string.IsNullOrWhiteSpace(value.Stream))
{
- _logger.LogTrace(value.Stream);
+ _logger.LogDebug(value.Stream);
}
if (!string.IsNullOrWhiteSpace(value.ProgressMessage))
{
- _logger.LogTrace(value.ProgressMessage);
+ _logger.LogDebug(value.ProgressMessage);
}
if (!string.IsNullOrWhiteSpace(value.ErrorMessage))
diff --git a/src/Testcontainers/Configurations/TestcontainersSettings.cs b/src/Testcontainers/Configurations/TestcontainersSettings.cs
index 595807dfe..4cae25bc1 100644
--- a/src/Testcontainers/Configurations/TestcontainersSettings.cs
+++ b/src/Testcontainers/Configurations/TestcontainersSettings.cs
@@ -1,6 +1,7 @@
namespace DotNet.Testcontainers.Configurations
{
using System;
+ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
@@ -167,7 +168,7 @@ static TestcontainersSettings()
///
[NotNull]
public static ILogger Logger { get; set; }
- = new Logger();
+ = ConsoleLogger.Instance;
///
/// Gets or sets the host operating system.
@@ -184,12 +185,16 @@ public static WaitHandle SettingsInitialized
=> ManualResetEvent.WaitHandle;
///
- public static async Task ExposeHostPortsAsync(params ushort[] ports)
+ public static Task ExposeHostPortsAsync(ushort port, CancellationToken ct = default)
+ => ExposeHostPortsAsync(new[] { port }, ct);
+
+ ///
+ public static async Task ExposeHostPortsAsync(IEnumerable ports, CancellationToken ct = default)
{
- await PortForwardingContainer.Instance.StartAsync()
+ await PortForwardingContainer.Instance.StartAsync(ct)
.ConfigureAwait(false);
- await PortForwardingContainer.Instance.ExposeHostPortsAsync(ports)
+ await PortForwardingContainer.Instance.ExposeHostPortsAsync(ports, ct)
.ConfigureAwait(false);
}
}
diff --git a/src/Testcontainers/Containers/DockerContainer.cs b/src/Testcontainers/Containers/DockerContainer.cs
index 01e037529..69dbd2526 100644
--- a/src/Testcontainers/Containers/DockerContainer.cs
+++ b/src/Testcontainers/Containers/DockerContainer.cs
@@ -440,12 +440,16 @@ await WaitStrategy.WaitUntilAsync(CheckPortBindingsAsync, TimeSpan.FromSeconds(1
await _configuration.StartupCallback(this, ct)
.ConfigureAwait(false);
+ Logger.StartReadinessCheck(_container.ID);
+
foreach (var waitStrategy in _configuration.WaitStrategies)
{
await WaitStrategy.WaitUntilAsync(() => CheckWaitStrategyAsync(waitStrategy), TimeSpan.FromSeconds(1), Timeout.InfiniteTimeSpan, ct)
.ConfigureAwait(false);
}
+ Logger.CompleteReadinessCheck(_container.ID);
+
Started?.Invoke(this, EventArgs.Empty);
}
diff --git a/src/Testcontainers/Containers/PortForwarding.cs b/src/Testcontainers/Containers/PortForwarding.cs
index 07450e0b8..2ebec57f2 100644
--- a/src/Testcontainers/Containers/PortForwarding.cs
+++ b/src/Testcontainers/Containers/PortForwarding.cs
@@ -1,7 +1,9 @@
namespace DotNet.Testcontainers.Containers
{
+ using System.Collections.Generic;
using System.Linq;
using System.Net;
+ using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Builders;
@@ -41,8 +43,9 @@ private PortForwardingContainer(PortForwardingConfiguration configuration, ILogg
/// Exposes the host ports using SSH port forwarding.
///
/// The host ports to forward.
+ /// Cancellation token.
/// A task that completes when the host ports are forwarded.
- public Task ExposeHostPortsAsync(params ushort[] ports)
+ public Task ExposeHostPortsAsync(IEnumerable ports, CancellationToken ct = default)
{
var sshClient = new SshClient(Hostname, GetMappedPublicPort(PortForwardingBuilder.SshdPort), _configuration.Username, _configuration.Password);
sshClient.Connect();
diff --git a/src/Testcontainers/Logger.cs b/src/Testcontainers/Logger.cs
index 0fea6e8b8..757a61e9a 100644
--- a/src/Testcontainers/Logger.cs
+++ b/src/Testcontainers/Logger.cs
@@ -2,9 +2,8 @@ namespace DotNet.Testcontainers
{
using System;
using System.Diagnostics;
- using System.Globalization;
- using System.IO;
using System.Runtime.InteropServices;
+ using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
///
@@ -55,11 +54,14 @@ namespace DotNet.Testcontainers
/// }
///
///
- internal sealed class Logger : ILogger, IDisposable
+ [PublicAPI]
+ public sealed class ConsoleLogger : ILogger, IDisposable
{
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
- public Logger()
+ private LogLevel _minLogLevel = LogLevel.Information;
+
+ private ConsoleLogger()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Console.IsOutputRedirected && !Console.IsErrorRedirected)
{
@@ -67,42 +69,50 @@ public Logger()
}
}
+ ///
+ /// Gets the instance.
+ ///
+ public static ConsoleLogger Instance { get; }
+ = new ConsoleLogger();
+
+ ///
+ /// Gets a value indicating whether the debug log level is enabled or not.
+ ///
+ public bool DebugLogLevelEnabled
+ {
+ get
+ {
+ return LogLevel.Debug.Equals(_minLogLevel);
+ }
+
+ set
+ {
+ _minLogLevel = value ? LogLevel.Debug : LogLevel.Information;
+ }
+ }
+
+ ///
public void Dispose()
{
- // The default logger does not support scopes. We return itself as IDisposable implementation.
+ // The default console logger does not support scopes. We return itself as IDisposable implementation.
}
+ ///
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
{
- TextWriter console;
-
- switch (logLevel)
+ if (IsEnabled(logLevel))
{
- case LogLevel.Information:
- console = Console.Out;
- break;
- case LogLevel.Warning:
- console = Console.Out;
- break;
- case LogLevel.Error:
- console = Console.Error;
- break;
- case LogLevel.Critical:
- console = Console.Error;
- break;
- default:
- return;
+ Console.Out.WriteLine("[testcontainers.org {0:hh\\:mm\\:ss\\.ff}] {1}", _stopwatch.Elapsed, formatter.Invoke(state, exception));
}
-
- var message = string.Format(CultureInfo.CurrentCulture, "[testcontainers.org {0:hh\\:mm\\:ss\\.ff}] {1}", _stopwatch.Elapsed, formatter.Invoke(state, exception));
- console.WriteLine(message);
}
+ ///
public bool IsEnabled(LogLevel logLevel)
{
- return true;
+ return logLevel >= _minLogLevel;
}
+ ///
public IDisposable BeginScope(TState state)
{
return this;
diff --git a/src/Testcontainers/Logging.cs b/src/Testcontainers/Logging.cs
index 9e675d861..12318b354 100644
--- a/src/Testcontainers/Logging.cs
+++ b/src/Testcontainers/Logging.cs
@@ -25,10 +25,16 @@ private static readonly Action _StopDockerContainer
private static readonly Action _DeleteDockerContainer
= LoggerMessage.Define(LogLevel.Information, default, "Delete Docker container {Id}");
- private static readonly Action _ExtractArchiveToDockerContainer
- = LoggerMessage.Define(LogLevel.Information, default, "Copy tar archive to \"{Path}\" at Docker container {Id}");
+ private static readonly Action _StartReadinessCheck
+ = LoggerMessage.Define(LogLevel.Information, default, "Wait for Docker container {Id} to complete readiness checks");
- private static readonly Action _GetArchiveFromDockerContainer
+ private static readonly Action _CompleteReadinessCheck
+ = LoggerMessage.Define(LogLevel.Information, default, "Docker container {Id} ready");
+
+ private static readonly Action _CopyArchiveToDockerContainer
+ = LoggerMessage.Define(LogLevel.Information, default, "Copy tar archive to \"{Path}\" to Docker container {Id}");
+
+ private static readonly Action _ReadArchiveFromDockerContainer
= LoggerMessage.Define(LogLevel.Information, default, "Read \"{Path}\" from Docker container {Id}");
private static readonly Action _AttachToDockerContainer
@@ -91,47 +97,57 @@ public static void IgnorePatternAdded(this ILogger logger, Regex ignorePattern)
public static void DockerContainerCreated(this ILogger logger, string id)
{
- _DockerContainerCreated(logger, id, null);
+ _DockerContainerCreated(logger, TruncId(id), null);
}
public static void StartDockerContainer(this ILogger logger, string id)
{
- _StartDockerContainer(logger, id, null);
+ _StartDockerContainer(logger, TruncId(id), null);
}
public static void StopDockerContainer(this ILogger logger, string id)
{
- _StopDockerContainer(logger, id, null);
+ _StopDockerContainer(logger, TruncId(id), null);
}
public static void DeleteDockerContainer(this ILogger logger, string id)
{
- _DeleteDockerContainer(logger, id, null);
+ _DeleteDockerContainer(logger, TruncId(id), null);
+ }
+
+ public static void StartReadinessCheck(this ILogger logger, string id)
+ {
+ _StartReadinessCheck(logger, TruncId(id), null);
}
- public static void ExtractArchiveToDockerContainer(this ILogger logger, string id, string path)
+ public static void CompleteReadinessCheck(this ILogger logger, string id)
{
- _ExtractArchiveToDockerContainer(logger, path, id, null);
+ _CompleteReadinessCheck(logger, TruncId(id), null);
}
- public static void GetArchiveFromDockerContainer(this ILogger logger, string id, string path)
+ public static void CopyArchiveToDockerContainer(this ILogger logger, string id, string path)
{
- _GetArchiveFromDockerContainer(logger, path, id, null);
+ _CopyArchiveToDockerContainer(logger, path, TruncId(id), null);
+ }
+
+ public static void ReadArchiveFromDockerContainer(this ILogger logger, string id, string path)
+ {
+ _ReadArchiveFromDockerContainer(logger, path, TruncId(id), null);
}
public static void AttachToDockerContainer(this ILogger logger, string id, Type type)
{
- _AttachToDockerContainer(logger, type, id, null);
+ _AttachToDockerContainer(logger, type, TruncId(id), null);
}
public static void ConnectToDockerNetwork(this ILogger logger, string networkId, string containerId)
{
- _ConnectToDockerNetwork(logger, containerId, networkId, null);
+ _ConnectToDockerNetwork(logger, TruncId(containerId), TruncId(networkId), null);
}
public static void ExecuteCommandInDockerContainer(this ILogger logger, string id, IEnumerable command)
{
- _ExecuteCommandInDockerContainer(logger, string.Join(" ", command), id, null);
+ _ExecuteCommandInDockerContainer(logger, string.Join(" ", command), TruncId(id), null);
}
public static void DockerImageCreated(this ILogger logger, IImage image)
@@ -151,12 +167,12 @@ public static void DeleteDockerImage(this ILogger logger, IImage image)
public static void DockerNetworkCreated(this ILogger logger, string id)
{
- _DockerNetworkCreated(logger, id, null);
+ _DockerNetworkCreated(logger, TruncId(id), null);
}
public static void DeleteDockerNetwork(this ILogger logger, string id)
{
- _DeleteDockerNetwork(logger, id, null);
+ _DeleteDockerNetwork(logger, TruncId(id), null);
}
public static void DockerVolumeCreated(this ILogger logger, string name)
@@ -205,5 +221,10 @@ public static void DockerRegistryCredentialFound(this ILogger logger, string doc
{
_DockerRegistryCredentialFound(logger, dockerRegistry, null);
}
+
+ private static string TruncId(string id)
+ {
+ return id.Substring(0, Math.Min(12, id.Length));
+ }
}
}