-module(testcontainer@container). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/testcontainer/container.gleam"). -export([bind_mount/2, readonly_bind_mount/2, tmpfs/1, volume_kind/1, new/1, with_env/3, with_envs/2, with_secret_env/3, expose_port/2, expose_ports/2, wait_for/2, with_command/2, with_entrypoint/2, with_volume/2, with_bind_mount/3, with_readonly_bind/3, with_tmpfs/2, on_network/2, with_name/2, with_label/3, with_privileged/1, image/1, env/1, ports/1, wait_strategy/1, command/1, entrypoint/1, volumes/1, network/1, name/1, labels/1, is_privileged/1, build/5, with_keep/2, stop_timeout_sec/1, id/1, host/1, keep/1, host_port/2, mapped_url/3]). -export_type([volume/0, container_spec/0, container/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 volume() :: {bind_mount, binary(), binary(), boolean()} | {tmpfs_mount, binary()}. -opaque container_spec() :: {container_spec, binary(), list({binary(), cowl:secret(binary())}), list(testcontainer@port:port_()), testcontainer@wait:wait_strategy(), gleam@option:option(list(binary())), gleam@option:option(list(binary())), list(volume()), gleam@option:option(binary()), gleam@option:option(binary()), list({binary(), binary()}), boolean()}. -opaque container() :: {container, binary(), binary(), gleam@dict:dict({integer(), binary()}, integer()), boolean(), integer()}. -file("src/testcontainer/container.gleam", 20). ?DOC(" Creates a read-write bind mount from `host_path` to `container_path`.\n"). -spec bind_mount(binary(), binary()) -> volume(). bind_mount(Host_path, Container_path) -> {bind_mount, Host_path, Container_path, false}. -file("src/testcontainer/container.gleam", 25). ?DOC(" Creates a read-only bind mount.\n"). -spec readonly_bind_mount(binary(), binary()) -> volume(). readonly_bind_mount(Host_path, Container_path) -> {bind_mount, Host_path, Container_path, true}. -file("src/testcontainer/container.gleam", 33). ?DOC(" Creates an in-memory tmpfs mount at `container_path`.\n"). -spec tmpfs(binary()) -> volume(). tmpfs(Container_path) -> {tmpfs_mount, Container_path}. -file("src/testcontainer/container.gleam", 42). ?DOC(false). -spec volume_kind(volume()) -> {ok, {binary(), binary(), boolean()}} | {error, binary()}. volume_kind(V) -> case V of {bind_mount, H, C, Ro} -> {ok, {H, C, Ro}}; {tmpfs_mount, C@1} -> {error, C@1} end. -file("src/testcontainer/container.gleam", 71). ?DOC( " Creates a new spec for the given image (e.g. `\"redis:7-alpine\"`).\n" " The default wait strategy is `wait.none/0` (no wait) - most images need\n" " a real `wait_for/2` (e.g. `wait.log(\"ready\")`) to be reliable.\n" ). -spec new(binary()) -> container_spec(). new(Image) -> {container_spec, Image, [], [], testcontainer@wait:none(), none, none, [], none, none, [], false}. -file("src/testcontainer/container.gleam", 89). ?DOC( " Adds an environment variable. The value is wrapped in a `cowl.Secret`\n" " internally; use `with_secret_env/3` if you already have a Secret.\n" ). -spec with_env(container_spec(), binary(), binary()) -> container_spec(). with_env(Spec, Key, Value) -> {container_spec, erlang:element(2, Spec), lists:append(erlang:element(3, Spec), [{Key, cowl:secret(Value)}]), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 101). ?DOC(" Adds multiple environment variables at once.\n"). -spec with_envs(container_spec(), list({binary(), binary()})) -> container_spec(). with_envs(Spec, Pairs) -> Wrapped = gleam@list:map( Pairs, fun(P) -> {erlang:element(1, P), cowl:secret(erlang:element(2, P))} end ), {container_spec, erlang:element(2, Spec), lists:append(erlang:element(3, Spec), Wrapped), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 110). ?DOC(" Adds an environment variable whose value is already a `cowl.Secret`.\n"). -spec with_secret_env(container_spec(), binary(), cowl:secret(binary())) -> container_spec(). with_secret_env(Spec, Key, Value) -> {container_spec, erlang:element(2, Spec), lists:append(erlang:element(3, Spec), [{Key, Value}]), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 119). ?DOC(" Exposes a single container port to the host (host port assigned dynamically).\n"). -spec expose_port(container_spec(), testcontainer@port:port_()) -> container_spec(). expose_port(Spec, P) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), lists:append(erlang:element(4, Spec), [P]), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 124). ?DOC(" Exposes multiple container ports to the host.\n"). -spec expose_ports(container_spec(), list(testcontainer@port:port_())) -> container_spec(). expose_ports(Spec, Ps) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), lists:append(erlang:element(4, Spec), Ps), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 129). ?DOC(" Sets the readiness wait strategy. The default is \"no wait\".\n"). -spec wait_for(container_spec(), testcontainer@wait:wait_strategy()) -> container_spec(). wait_for(Spec, Strategy) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), Strategy, erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 137). ?DOC(" Overrides the container's CMD.\n"). -spec with_command(container_spec(), list(binary())) -> container_spec(). with_command(Spec, Cmd) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), {some, Cmd}, erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 142). ?DOC(" Overrides the container's ENTRYPOINT.\n"). -spec with_entrypoint(container_spec(), list(binary())) -> container_spec(). with_entrypoint(Spec, Ep) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), {some, Ep}, erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 170). ?DOC(" Adds an arbitrary `Volume` (built with `bind_mount/2`, `tmpfs/1`, …).\n"). -spec with_volume(container_spec(), volume()) -> container_spec(). with_volume(Spec, V) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), lists:append(erlang:element(8, Spec), [V]), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 147). ?DOC(" Adds a read-write bind mount (host path → container path).\n"). -spec with_bind_mount(container_spec(), binary(), binary()) -> container_spec(). with_bind_mount(Spec, Host, Container_path) -> with_volume(Spec, bind_mount(Host, Container_path)). -file("src/testcontainer/container.gleam", 156). ?DOC(" Adds a read-only bind mount.\n"). -spec with_readonly_bind(container_spec(), binary(), binary()) -> container_spec(). with_readonly_bind(Spec, Host, Container_path) -> with_volume(Spec, readonly_bind_mount(Host, Container_path)). -file("src/testcontainer/container.gleam", 165). ?DOC(" Mounts an in-memory tmpfs at the given path inside the container.\n"). -spec with_tmpfs(container_spec(), binary()) -> container_spec(). with_tmpfs(Spec, Path) -> with_volume(Spec, tmpfs(Path)). -file("src/testcontainer/container.gleam", 175). ?DOC(" Attaches the container to the named Docker network.\n"). -spec on_network(container_spec(), binary()) -> container_spec(). on_network(Spec, Network) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), {some, Network}, erlang:element(10, Spec), erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 180). ?DOC(" Assigns a fixed name to the container (otherwise Docker auto-generates one).\n"). -spec with_name(container_spec(), binary()) -> container_spec(). with_name(Spec, N) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), {some, N}, erlang:element(11, Spec), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 185). ?DOC(" Adds a label to the container.\n"). -spec with_label(container_spec(), binary(), binary()) -> container_spec(). with_label(Spec, Key, Value) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), lists:append(erlang:element(11, Spec), [{Key, Value}]), erlang:element(12, Spec)}. -file("src/testcontainer/container.gleam", 194). ?DOC(" Marks the container as privileged.\n"). -spec with_privileged(container_spec()) -> container_spec(). with_privileged(Spec) -> {container_spec, erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(4, Spec), erlang:element(5, Spec), erlang:element(6, Spec), erlang:element(7, Spec), erlang:element(8, Spec), erlang:element(9, Spec), erlang:element(10, Spec), erlang:element(11, Spec), true}. -file("src/testcontainer/container.gleam", 200). -spec image(container_spec()) -> binary(). image(Spec) -> erlang:element(2, Spec). -file("src/testcontainer/container.gleam", 204). -spec env(container_spec()) -> list({binary(), cowl:secret(binary())}). env(Spec) -> erlang:element(3, Spec). -file("src/testcontainer/container.gleam", 208). -spec ports(container_spec()) -> list(testcontainer@port:port_()). ports(Spec) -> erlang:element(4, Spec). -file("src/testcontainer/container.gleam", 212). -spec wait_strategy(container_spec()) -> testcontainer@wait:wait_strategy(). wait_strategy(Spec) -> erlang:element(5, Spec). -file("src/testcontainer/container.gleam", 216). -spec command(container_spec()) -> gleam@option:option(list(binary())). command(Spec) -> erlang:element(6, Spec). -file("src/testcontainer/container.gleam", 220). -spec entrypoint(container_spec()) -> gleam@option:option(list(binary())). entrypoint(Spec) -> erlang:element(7, Spec). -file("src/testcontainer/container.gleam", 224). -spec volumes(container_spec()) -> list(volume()). volumes(Spec) -> erlang:element(8, Spec). -file("src/testcontainer/container.gleam", 228). -spec network(container_spec()) -> gleam@option:option(binary()). network(Spec) -> erlang:element(9, Spec). -file("src/testcontainer/container.gleam", 232). -spec name(container_spec()) -> gleam@option:option(binary()). name(Spec) -> erlang:element(10, Spec). -file("src/testcontainer/container.gleam", 236). -spec labels(container_spec()) -> list({binary(), binary()}). labels(Spec) -> erlang:element(11, Spec). -file("src/testcontainer/container.gleam", 240). -spec is_privileged(container_spec()) -> boolean(). is_privileged(Spec) -> erlang:element(12, Spec). -file("src/testcontainer/container.gleam", 267). ?DOC(false). -spec build( binary(), binary(), gleam@dict:dict({integer(), binary()}, integer()), boolean(), integer() ) -> container(). build(Id, Gateway_host, Port_mapping, Keep, Stop_timeout_sec) -> {container, Id, Gateway_host, Port_mapping, Keep, Stop_timeout_sec}. -file("src/testcontainer/container.gleam", 280). ?DOC(false). -spec with_keep(container(), boolean()) -> container(). with_keep(C, Keep) -> {container, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), Keep, erlang:element(6, C)}. -file("src/testcontainer/container.gleam", 287). ?DOC(false). -spec stop_timeout_sec(container()) -> integer(). stop_timeout_sec(C) -> erlang:element(6, C). -file("src/testcontainer/container.gleam", 292). ?DOC(" Returns the Docker container id.\n"). -spec id(container()) -> binary(). id(C) -> erlang:element(2, C). -file("src/testcontainer/container.gleam", 299). ?DOC( " Returns the host that the test runner should use to reach the\n" " container's mapped ports (typically the bridge gateway IP, or\n" " the value of `TESTCONTAINERS_HOST_OVERRIDE`).\n" ). -spec host(container()) -> binary(). host(C) -> erlang:element(3, C). -file("src/testcontainer/container.gleam", 305). ?DOC( " Whether this container should be kept alive after the test\n" " (`TESTCONTAINERS_KEEP=true` or `start_and_keep/1`).\n" ). -spec keep(container()) -> boolean(). keep(C) -> erlang:element(5, C). -file("src/testcontainer/container.gleam", 311). ?DOC( " Returns the host port that maps to the given container port,\n" " or `PortNotMapped` if the port is not exposed.\n" ). -spec host_port(container(), testcontainer@port:port_()) -> {ok, integer()} | {error, testcontainer@error:error()}. host_port(C, P) -> N = testcontainer@port:number(P), Proto = testcontainer@port:protocol(P), case gleam_stdlib:map_get(erlang:element(4, C), {N, Proto}) of {ok, Hp} -> {ok, Hp}; {error, nil} -> {error, {port_not_mapped, N}} end. -file("src/testcontainer/container.gleam", 322). ?DOC( " Builds a URL for the given container port using the configured scheme,\n" " host, and mapped host port (e.g. `\"http://127.0.0.1:32768\"`).\n" ). -spec mapped_url(container(), testcontainer@port:port_(), binary()) -> {ok, binary()} | {error, testcontainer@error:error()}. mapped_url(C, P, Scheme) -> case host_port(C, P) of {ok, Hp} -> {ok, <<<<<<<>/binary, (host(C))/binary>>/binary, ":"/utf8>>/binary, (erlang:integer_to_binary(Hp))/binary>>}; {error, E} -> {error, E} end.