Current section
Files
Jump to
Current section
Files
src/testcontainer@network.erl
-module(testcontainer@network).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/testcontainer/network.gleam").
-export([create/1, remove/1, with_network/2, name/1, id/1]).
-export_type([network/0, guard_event/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-opaque network() :: {network, binary(), binary()}.
-type guard_event() :: guard_stop | parent_down.
-file("src/testcontainer/network.gleam", 14).
?DOC(" Creates a new bridge network with the given name.\n").
-spec create(binary()) -> {ok, network()} | {error, testcontainer@error:error()}.
create(Name) ->
gleam@result:'try'(
testcontainer@internal@docker:create_network(Name),
fun(Id) -> {ok, {network, Id, Name}} end
).
-file("src/testcontainer/network.gleam", 20).
?DOC(" Removes a network created via `create/1`.\n").
-spec remove(network()) -> {ok, nil} | {error, testcontainer@error:error()}.
remove(Network) ->
testcontainer@internal@docker:remove_network(erlang:element(2, Network)).
-file("src/testcontainer/network.gleam", 91).
-spec guard_loop(binary(), gleam@erlang@process:subject(guard_event())) -> nil.
guard_loop(Id, Subject) ->
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
_pipe@1 = gleam@erlang@process:select(_pipe, Subject),
gleam@erlang@process:select_trapped_exits(
_pipe@1,
fun(_) -> parent_down end
)
end,
case gleam_erlang_ffi:select(Selector) of
guard_stop ->
nil;
parent_down ->
proc_lib:spawn_link(
fun() ->
_ = testcontainer@internal@docker:remove_network(Id),
nil
end
),
nil
end.
-file("src/testcontainer/network.gleam", 68).
-spec create_guarded(binary()) -> {ok,
{network(), gleam@erlang@process:subject(guard_event())}} |
{error, testcontainer@error:error()}.
create_guarded(Name) ->
Startup_subject = gleam@erlang@process:new_subject(),
proc_lib:spawn_link(
fun() ->
gleam_erlang_ffi:trap_exits(true),
Guard = gleam@erlang@process:new_subject(),
case create(Name) of
{ok, Net} ->
gleam@erlang@process:send(
Startup_subject,
{ok, {Net, Guard}}
),
guard_loop(erlang:element(2, Net), Guard);
{error, E} ->
gleam@erlang@process:send(Startup_subject, {error, E})
end
end
),
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:select(_pipe, Startup_subject)
end,
gleam_erlang_ffi:select(Selector).
-file("src/testcontainer/network.gleam", 30).
?DOC(
" Creates a network, runs `body/1`, then removes it. Cleanup runs even if\n"
" `body/1` returns an error or the caller process crashes (a linked guard\n"
" process performs the removal asynchronously on caller down).\n"
"\n"
" use net <- network.with_network(\"test-net\")\n"
).
-spec with_network(
binary(),
fun((network()) -> {ok, GVK} | {error, testcontainer@error:error()})
) -> {ok, GVK} | {error, testcontainer@error:error()}.
with_network(Name, Body) ->
gleam@result:'try'(
create_guarded(Name),
fun(_use0) ->
{Net, Guard} = _use0,
Body_result = Body(Net),
gleam@erlang@process:send(Guard, guard_stop),
Remove_result = remove(Net),
case {Body_result, Remove_result} of
{{ok, _}, {error, Rm_e}} ->
{error, Rm_e};
{_, _} ->
Body_result
end
end
).
-file("src/testcontainer/network.gleam", 45).
?DOC(" The network's name (as passed to `create/1`).\n").
-spec name(network()) -> binary().
name(Network) ->
erlang:element(3, Network).
-file("src/testcontainer/network.gleam", 50).
?DOC(" The Docker-assigned network id.\n").
-spec id(network()) -> binary().
id(Network) ->
erlang:element(2, Network).