Skip to content

Commit

Permalink
fix: Allow specifying the protocol (TCP, UDP, SCTP) to resolve the pu…
Browse files Browse the repository at this point in the history
…blic assigned host port (#1219)

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
  • Loading branch information
wolfman42 and HofmeisterAn authored Jul 25, 2024
1 parent a0f1f76 commit 21137c6
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public ContainerConfigurationConverter(IContainerConfiguration configuration)

public IDictionary<string, EndpointSettings> Networks { get; }

private static string GetQualifiedPort(string containerPort)
public static string GetQualifiedPort(string containerPort)
{
return Array.Exists(new[] { UdpPortSuffix, TcpPortSuffix, SctpPortSuffix }, portSuffix => containerPort.EndsWith(portSuffix, StringComparison.OrdinalIgnoreCase)) ? containerPort.ToLowerInvariant() : containerPort + TcpPortSuffix;
}
Expand Down
6 changes: 4 additions & 2 deletions src/Testcontainers/Containers/DockerContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,15 @@ public ushort GetMappedPublicPort(string containerPort)
{
ThrowIfResourceNotFound();

if (_container.NetworkSettings.Ports.TryGetValue($"{containerPort}/tcp", out var portBindings) && ushort.TryParse(portBindings[0].HostPort, out var publicPort))
var qualifiedContainerPort = ContainerConfigurationConverter.GetQualifiedPort(containerPort);

if (_container.NetworkSettings.Ports.TryGetValue(qualifiedContainerPort, out var portBindings) && ushort.TryParse(portBindings[0].HostPort, out var publicPort))
{
return publicPort;
}
else
{
throw new InvalidOperationException($"Exposed port {containerPort} is not mapped.");
throw new InvalidOperationException($"Exposed port {qualifiedContainerPort} is not mapped.");
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/Testcontainers/Containers/IContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public interface IContainer : IAsyncDisposable
/// <summary>
/// Resolves the public assigned host port.
/// </summary>
/// <remarks>
/// Resolves the public assigned host port for the TCP protocol. To resolve a specific protocol, use <see cref="GetMappedPublicPort(string)" />.
/// </remarks>
/// <param name="containerPort">The container port.</param>
/// <returns>Returns the public assigned host port.</returns>
/// <exception cref="InvalidOperationException">Container has not been created.</exception>
Expand All @@ -140,6 +143,9 @@ public interface IContainer : IAsyncDisposable
/// <summary>
/// Resolves the public assigned host port.
/// </summary>
/// <remarks>
/// Append /tcp|udp|sctp to <paramref name="containerPort" /> to resolve the public assigned host port for a specific protocol e.g. "53/udp".
/// </remarks>
/// <param name="containerPort">The container port.</param>
/// <returns>Returns the public assigned host port.</returns>
/// <exception cref="InvalidOperationException">Container has not been created.</exception>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,29 @@ await container.StartAsync()
}

[Fact]
public async Task RandomPortBinding()
public async Task RandomUdpPortBinding()
{
// Given
const ushort containerPort = 53;

const string qualifiedContainerPort = "53/udp";

await using var container = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.WithPortBinding(qualifiedContainerPort, true)
.Build();

// When
await container.StartAsync()
.ConfigureAwait(true);

// Then
Assert.NotEqual(containerPort, container.GetMappedPublicPort(qualifiedContainerPort));
}

[Fact]
public async Task RandomTcpPortBinding()
{
// Given
const ushort containerPort = 80;
Expand Down

0 comments on commit 21137c6

Please # to comment.