Skip to content

Commit e0031d2

Browse files
authored
Fixing bug in mapped_port (#227)
* Fixing bug in mapped_port * Fix the bug properly * refactor: standardize exposed_ports as tuples and simplify mapped_port/2 logic
1 parent 2bbb3ea commit e0031d2

3 files changed

Lines changed: 33 additions & 20 deletions

File tree

lib/container.ex

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,30 @@ defmodule Testcontainers.Container do
9090
Adds a _port_ to be exposed on the _container_.
9191
"""
9292
def with_exposed_port(%__MODULE__{} = config, port) when is_integer(port) do
93-
filtered_ports = config.exposed_ports |> Enum.reject(fn p -> p == port end)
93+
filtered_ports =
94+
config.exposed_ports
95+
|> Enum.reject(fn
96+
{p, _} -> p == port
97+
p -> p == port
98+
end)
9499

95-
%__MODULE__{config | exposed_ports: [port | filtered_ports]}
100+
%__MODULE__{config | exposed_ports: [{port, nil} | filtered_ports]}
96101
end
97102

98103
@doc """
99104
Adds multiple _ports_ to be exposed on the _container_.
100105
"""
101106
def with_exposed_ports(%__MODULE__{} = config, ports) when is_list(ports) do
102-
filtered_ports = config.exposed_ports |> Enum.reject(fn port -> port in ports end)
107+
filtered_ports =
108+
config.exposed_ports
109+
|> Enum.reject(fn
110+
{p, _} -> p in ports
111+
p -> p in ports
112+
end)
113+
114+
new_ports = Enum.map(ports, fn port -> {port, nil} end)
103115

104-
%__MODULE__{config | exposed_ports: ports ++ filtered_ports}
116+
%__MODULE__{config | exposed_ports: new_ports ++ filtered_ports}
105117
end
106118

107119
@doc """
@@ -242,13 +254,10 @@ defmodule Testcontainers.Container do
242254
"""
243255
def mapped_port(%__MODULE__{} = container, port) when is_number(port) do
244256
container.exposed_ports
245-
|> Enum.filter(fn
246-
{exposed_port, _} -> exposed_port == port
247-
port -> port == port
257+
|> Enum.find_value(nil, fn
258+
{^port, host_port} -> host_port
259+
_ -> nil
248260
end)
249-
|> List.first({})
250-
|> Tuple.to_list()
251-
|> List.last()
252261
end
253262

254263
@doc """

lib/docker/api.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ defmodule Testcontainers.Docker.Api do
224224
container_config.exposed_ports
225225
|> Enum.map(fn
226226
{container_port, _host_port} -> {container_port, %{}}
227-
port -> {port, %{}}
228227
end)
229228
|> Enum.into(%{})
230229
end
@@ -237,11 +236,11 @@ defmodule Testcontainers.Docker.Api do
237236
defp map_port_bindings(%Container{} = container_config) do
238237
container_config.exposed_ports
239238
|> Enum.map(fn
239+
{container_port, host_port} when is_nil(host_port) ->
240+
{container_port, [%{"HostIp" => "0.0.0.0", "HostPort" => ""}]}
241+
240242
{container_port, host_port} ->
241243
{container_port, [%{"HostIp" => "0.0.0.0", "HostPort" => to_string(host_port)}]}
242-
243-
port ->
244-
{port, [%{"HostIp" => "0.0.0.0", "HostPort" => ""}]}
245244
end)
246245
|> Enum.into(%{})
247246
end

test/container_test.exs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ defmodule Testcontainers.ContainerTest do
2121
container2 = ContainerBuilder.build(Testcontainers.PostgresContainer.new())
2222

2323
assert Testcontainers.Util.Hash.struct_to_hash(container1) ==
24-
"2ac8f31c61b760b17176a9b9e51bd9d969eb26adadc9bf3db4cdcac69cfb065f"
24+
"082851e217cae88e1684169a9759a6d702d012016054c14b23d192f7e2559c63"
2525

2626
assert Testcontainers.Util.Hash.struct_to_hash(container2) ==
27-
"2ac8f31c61b760b17176a9b9e51bd9d969eb26adadc9bf3db4cdcac69cfb065f"
27+
"082851e217cae88e1684169a9759a6d702d012016054c14b23d192f7e2559c63"
2828
end
2929
end
3030

@@ -34,7 +34,7 @@ defmodule Testcontainers.ContainerTest do
3434
Container.new("my-image")
3535
|> Container.with_exposed_port(80)
3636

37-
assert container.exposed_ports == [80]
37+
assert container.exposed_ports == [{80, nil}]
3838
end
3939

4040
test "removes duplicate exposed ports" do
@@ -43,7 +43,7 @@ defmodule Testcontainers.ContainerTest do
4343
|> Container.with_exposed_port(80)
4444
|> Container.with_exposed_port(80)
4545

46-
assert container.exposed_ports == [80]
46+
assert container.exposed_ports == [{80, nil}]
4747
end
4848
end
4949

@@ -53,7 +53,7 @@ defmodule Testcontainers.ContainerTest do
5353
Container.new("my-image")
5454
|> Container.with_exposed_ports([80, 443])
5555

56-
assert container.exposed_ports == [80, 443]
56+
assert container.exposed_ports == [{80, nil}, {443, nil}]
5757
end
5858

5959
test "removes duplicate exposed ports" do
@@ -62,7 +62,7 @@ defmodule Testcontainers.ContainerTest do
6262
|> Container.with_exposed_ports([80, 443])
6363
|> Container.with_exposed_ports([80])
6464

65-
assert container.exposed_ports == [80, 443]
65+
assert container.exposed_ports == [{80, nil}, {443, nil}]
6666
end
6767
end
6868

@@ -96,6 +96,11 @@ defmodule Testcontainers.ContainerTest do
9696
container = Container.new("my-image")
9797
assert Container.mapped_port(container, 80) == nil
9898
end
99+
100+
test "returns nil (and does not crash) if the exposed port is present but not mapped (integer)" do
101+
container = Container.new("my-image") |> Container.with_exposed_port(80)
102+
assert Container.mapped_port(container, 80) == nil
103+
end
99104
end
100105

101106
describe "with_network_mode/2" do

0 commit comments

Comments
 (0)