Packages
testcontainer_formulas
1.0.0
Ready-to-use, fully customizable Testcontainer formulas for Gleam (postgres, redis, …).
Current section
Files
Jump to
Current section
Files
src/testcontainer_formulas@mongo.erl
-module(testcontainer_formulas@mongo).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/testcontainer_formulas/mongo.gleam").
-export([new/0, with_image/2, with_version/2, with_database/2, with_username/2, with_password/2, with_secret_password/2, with_auth_database/2, with_extra_wait/2, on_network/2, on_network_name/2, with_name/2, formula/1]).
-export_type([mongo_container/0, mongo_config/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.
?MODULEDOC(
" Mongo formula. Defaults to `mongo:7` with root auth.\n"
"\n"
" use db <- testcontainer.with_formula(\n"
" mongo.new()\n"
" |> mongo.with_database(\"app_test\")\n"
" |> mongo.with_username(\"app\")\n"
" |> mongo.with_password(\"secret\")\n"
" |> mongo.formula(),\n"
" )\n"
"\n"
" // db.connection_url, db.host, db.port, db.database, db.username\n"
).
-type mongo_container() :: {mongo_container,
testcontainer@container:container(),
binary(),
binary(),
integer(),
binary(),
binary()}.
-opaque mongo_config() :: {mongo_config,
binary(),
binary(),
binary(),
cowl:secret(binary()),
binary(),
gleam@option:option(testcontainer@wait:wait_strategy()),
gleam@option:option(binary()),
gleam@option:option(binary())}.
-file("src/testcontainer_formulas/mongo.gleam", 52).
?DOC(" Sensible defaults: `mongo:7` / db `app` / user `root` / pass `root`.\n").
-spec new() -> mongo_config().
new() ->
{mongo_config,
<<"mongo:7"/utf8>>,
<<"app"/utf8>>,
<<"root"/utf8>>,
cowl:secret(<<"root"/utf8>>),
<<"admin"/utf8>>,
none,
none,
none}.
-file("src/testcontainer_formulas/mongo.gleam", 66).
?DOC(" Replaces the image entirely.\n").
-spec with_image(mongo_config(), binary()) -> mongo_config().
with_image(C, Image) ->
{mongo_config,
Image,
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 71).
?DOC(" Shorthand: keep `mongo:` prefix, override only the tag.\n").
-spec with_version(mongo_config(), binary()) -> mongo_config().
with_version(C, Version) ->
{mongo_config,
<<"mongo:"/utf8, Version/binary>>,
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 78).
?DOC(
" Sets `MONGO_INITDB_DATABASE`. The image creates this database during\n"
" bootstrap, but `mongosh` will still connect through `auth_database`\n"
" (default `\"admin\"`).\n"
).
-spec with_database(mongo_config(), binary()) -> mongo_config().
with_database(C, Db) ->
{mongo_config,
erlang:element(2, C),
Db,
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 84).
?DOC(
" Sets `MONGO_INITDB_ROOT_USERNAME`. This is the **root** user the image\n"
" creates at startup, used by the returned `connection_url`.\n"
).
-spec with_username(mongo_config(), binary()) -> mongo_config().
with_username(C, User) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
User,
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 89).
?DOC(" Sets `MONGO_INITDB_ROOT_PASSWORD` for the root user.\n").
-spec with_password(mongo_config(), binary()) -> mongo_config().
with_password(C, Pass) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
cowl:secret(Pass),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 94).
?DOC(" Same as `with_password/2` when the value is already a `cowl.Secret`.\n").
-spec with_secret_password(mongo_config(), cowl:secret(binary())) -> mongo_config().
with_secret_password(C, Pass) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
Pass,
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 102).
?DOC(" Authentication database used in the returned Mongo URI.\n").
-spec with_auth_database(mongo_config(), binary()) -> mongo_config().
with_auth_database(C, Db) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
Db,
erlang:element(7, C),
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 113).
?DOC(
" Adds an extra wait strategy on top of the default\n"
" `all_of([port(27017), log_times(\"Waiting for connections\", 2)])`.\n"
" The `log_times(_, 2)` matches the second emission of that line, which\n"
" is the post-bootstrap restart with `--auth` enabled — earlier, clients\n"
" using `MONGO_INITDB_ROOT_USERNAME` race the auth-bootstrap and fail\n"
" with \"Authentication failed\". Stays image-agnostic (no dependency on\n"
" `mongosh` being present in the image).\n"
).
-spec with_extra_wait(mongo_config(), testcontainer@wait:wait_strategy()) -> mongo_config().
with_extra_wait(C, S) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
{some, S},
erlang:element(8, C),
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 117).
-spec on_network(mongo_config(), testcontainer@network:network()) -> mongo_config().
on_network(C, Net) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
{some, testcontainer@network:name(Net)},
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 122).
?DOC(" Same as `on_network/2` when you already have the Docker network name.\n").
-spec on_network_name(mongo_config(), binary()) -> mongo_config().
on_network_name(C, Net) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
{some, Net},
erlang:element(9, C)}.
-file("src/testcontainer_formulas/mongo.gleam", 126).
-spec with_name(mongo_config(), binary()) -> mongo_config().
with_name(C, N) ->
{mongo_config,
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C),
erlang:element(5, C),
erlang:element(6, C),
erlang:element(7, C),
erlang:element(8, C),
{some, N}}.
-file("src/testcontainer_formulas/mongo.gleam", 132).
?DOC(
" Builds the `Formula(MongoContainer)` ready to pass to\n"
" `testcontainer.with_formula/2`.\n"
).
-spec formula(mongo_config()) -> testcontainer@formula:formula(mongo_container()).
formula(C) ->
Mongo_port = testcontainer@port:tcp(27017),
Base_wait = testcontainer@wait:all_of(
[testcontainer@wait:port(27017),
testcontainer@wait:log_times(<<"Waiting for connections"/utf8>>, 2)]
),
Wait_strategy = case erlang:element(7, C) of
none ->
Base_wait;
{some, Extra} ->
testcontainer@wait:all_of([Base_wait, Extra])
end,
With_auth = begin
_pipe = testcontainer@container:new(erlang:element(2, C)),
_pipe@1 = testcontainer@container:expose_port(_pipe, Mongo_port),
_pipe@2 = testcontainer@container:with_env(
_pipe@1,
<<"MONGO_INITDB_DATABASE"/utf8>>,
erlang:element(3, C)
),
_pipe@3 = testcontainer@container:with_env(
_pipe@2,
<<"MONGO_INITDB_ROOT_USERNAME"/utf8>>,
erlang:element(4, C)
),
_pipe@4 = testcontainer@container:with_secret_env(
_pipe@3,
<<"MONGO_INITDB_ROOT_PASSWORD"/utf8>>,
erlang:element(5, C)
),
testcontainer@container:wait_for(_pipe@4, Wait_strategy)
end,
With_net = case erlang:element(8, C) of
none ->
With_auth;
{some, N} ->
_pipe@5 = With_auth,
testcontainer@container:on_network(_pipe@5, N)
end,
Final_spec = case erlang:element(9, C) of
none ->
With_net;
{some, N@1} ->
_pipe@6 = With_net,
testcontainer@container:with_name(_pipe@6, N@1)
end,
testcontainer@formula:new(
Final_spec,
fun(Running) ->
gleam@result:'try'(
testcontainer@container:host_port(Running, Mongo_port),
fun(Mapped_port) ->
Host = testcontainer@container:host(Running),
Pass = cowl:reveal(erlang:element(5, C)),
{ok,
{mongo_container,
Running,
<<<<<<<<<<<<<<<<<<<<<<"mongodb://"/utf8,
(gleam_stdlib:percent_encode(
erlang:element(
4,
C
)
))/binary>>/binary,
":"/utf8>>/binary,
(gleam_stdlib:percent_encode(
Pass
))/binary>>/binary,
"@"/utf8>>/binary,
Host/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(
Mapped_port
))/binary>>/binary,
"/"/utf8>>/binary,
(gleam_stdlib:percent_encode(
erlang:element(3, C)
))/binary>>/binary,
"?authSource="/utf8>>/binary,
(gleam_stdlib:percent_encode(
erlang:element(6, C)
))/binary>>,
Host,
Mapped_port,
erlang:element(3, C),
erlang:element(4, C)}}
end
)
end
).