-module(melon@container). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/1, set_user/2, set_entrypoint/2, set_command/2, set_working_directory/2, set_memory_limit/3, set_env_file/2, add_exposed_port/4, add_env/3, stop/1, mapped_port/3, start/1]). -export_type([container_failure/0, port_protocol/0, port_/0, memory_unit/0, container/0, environment_variable/0, memory_limit/0]). -type container_failure() :: container_is_not_running | {container_could_not_be_started, binary()} | {container_could_not_be_stopped, binary()} | mapped_port_could_not_be_found. -type port_protocol() :: tcp | udp | sctp. -type port_() :: {port, binary(), binary(), port_protocol()}. -type memory_unit() :: byte | kilobyte | megabyte | gigabyte. -opaque container() :: {container, gleam@option:option(binary()), binary(), gleam@option:option(binary()), gleam@option:option(binary()), gleam@option:option(list(binary())), gleam@option:option(binary()), gleam@option:option(memory_limit()), gleam@option:option(binary()), list(port_()), list(environment_variable())}. -type environment_variable() :: {environment_variable, binary(), binary()}. -type memory_limit() :: {memory_limit, binary(), memory_unit()}. -spec new(binary()) -> container(). new(Image) -> {container, none, Image, none, none, none, none, none, none, [], []}. -spec set_user(container(), binary()) -> container(). set_user(Container, User) -> erlang:setelement(4, Container, {some, User}). -spec set_entrypoint(container(), binary()) -> container(). set_entrypoint(Container, Entrypoint) -> erlang:setelement(5, Container, {some, Entrypoint}). -spec set_command(container(), list(binary())) -> container(). set_command(Container, Command) -> erlang:setelement(6, Container, {some, Command}). -spec set_working_directory(container(), binary()) -> container(). set_working_directory(Container, Working_directory) -> erlang:setelement(7, Container, {some, Working_directory}). -spec set_memory_limit(container(), binary(), memory_unit()) -> container(). set_memory_limit(Container, Limit, Unit) -> erlang:setelement(8, Container, {some, {memory_limit, Limit, Unit}}). -spec set_env_file(container(), binary()) -> container(). set_env_file(Container, Env_file) -> erlang:setelement(9, Container, {some, Env_file}). -spec add_exposed_port(container(), binary(), binary(), port_protocol()) -> container(). add_exposed_port(Container, Host, Port, Protocol) -> erlang:setelement( 10, Container, [{port, Host, Port, Protocol} | erlang:element(10, Container)] ). -spec add_env(container(), binary(), binary()) -> container(). add_env(Container, Identifier, Value) -> erlang:setelement( 11, Container, [{environment_variable, Identifier, Value} | erlang:element(11, Container)] ). -spec docker_cmd(list(binary())) -> {ok, gleamyshell:command_output()} | {error, binary()}. docker_cmd(Args) -> gleamyshell_ffi:execute(<<"docker"/utf8>>, <<"."/utf8>>, Args). -spec stop(container()) -> {ok, container()} | {error, container_failure()}. stop(Container) -> case erlang:element(2, Container) of none -> {error, container_is_not_running}; {some, Container_id} -> case docker_cmd([<<"stop"/utf8>>, Container_id]) of {ok, {command_output, 0, _}} -> _pipe = erlang:setelement(2, Container, none), {ok, _pipe}; {ok, {command_output, _, Output}} -> _pipe@1 = gleam@string:trim(Output), _pipe@2 = {container_could_not_be_stopped, _pipe@1}, {error, _pipe@2}; {error, Reason} -> _pipe@3 = gleam@string:trim(Reason), _pipe@4 = {container_could_not_be_stopped, _pipe@3}, {error, _pipe@4} end end. -spec mapped_port(container(), binary(), port_protocol()) -> {ok, port_()} | {error, container_failure()}. mapped_port(Container, Port, Protocol) -> case erlang:element(2, Container) of none -> {error, container_is_not_running}; {some, Container_id} -> case docker_cmd( [<<"port"/utf8>>, Container_id, <<<>/binary, (begin _pipe = gleam@string:inspect(Protocol), gleam@string:lowercase(_pipe) end)/binary>>] ) of {ok, {command_output, 0, Output}} -> case begin _pipe@1 = gleam@string:trim(Output), gleam@string:split(_pipe@1, <<":"/utf8>>) end of [Host, Value | _] -> _pipe@2 = {port, Host, Value, Protocol}, {ok, _pipe@2}; _ -> {error, mapped_port_could_not_be_found} end; _ -> {error, mapped_port_could_not_be_found} end end. -spec user_to_arg(gleam@option:option(binary())) -> list(binary()). user_to_arg(User) -> case User of none -> []; {some, Value} -> [<<"-u"/utf8>>, Value] end. -spec entrypoint_to_arg(gleam@option:option(binary())) -> list(binary()). entrypoint_to_arg(Entrypoint) -> case Entrypoint of none -> []; {some, Value} -> [<<"--entrypoint"/utf8>>, Value] end. -spec working_directory_to_arg(gleam@option:option(binary())) -> list(binary()). working_directory_to_arg(Working_directory) -> case Working_directory of none -> []; {some, Value} -> [<<"-w"/utf8>>, Value] end. -spec env_file_to_arg(gleam@option:option(binary())) -> list(binary()). env_file_to_arg(Env_file) -> case Env_file of none -> []; {some, File} -> [<<"--env-file"/utf8>>, File] end. -spec port_to_arg(port_()) -> list(binary()). port_to_arg(Port) -> [<<"-p"/utf8>>, <<<<<<<<(erlang:element(2, Port))/binary, ":0:"/utf8>>/binary, (erlang:element(3, Port))/binary>>/binary, "/"/utf8>>/binary, (begin _pipe = gleam@string:inspect(erlang:element(4, Port)), gleam@string:lowercase(_pipe) end)/binary>>]. -spec env_to_arg(environment_variable()) -> list(binary()). env_to_arg(Env) -> [<<"-e"/utf8>>, <<<<(erlang:element(2, Env))/binary, "="/utf8>>/binary, (erlang:element(3, Env))/binary>>]. -spec memory_unit_to_string(memory_unit()) -> binary(). memory_unit_to_string(Memory_unit) -> _assert_subject = begin _pipe = gleam@string:inspect(Memory_unit), gleam@string:first(_pipe) end, {ok, Value} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"melon/container"/utf8>>, function => <<"memory_unit_to_string"/utf8>>, line => 272}) end, _pipe@1 = Value, gleam@string:lowercase(_pipe@1). -spec memory_limit_to_arg(gleam@option:option(memory_limit())) -> list(binary()). memory_limit_to_arg(Memory_limit) -> case Memory_limit of none -> []; {some, {memory_limit, Limit, Unit}} -> [<<"-m"/utf8>>, <>] end. -spec start(container()) -> {ok, container()} | {error, container_failure()}. start(Container) -> Arguments = begin _pipe = [<<"run"/utf8>>, <<"--rm"/utf8>>], _pipe@1 = lists:append(_pipe, user_to_arg(erlang:element(4, Container))), _pipe@2 = lists:append( _pipe@1, entrypoint_to_arg(erlang:element(5, Container)) ), _pipe@3 = lists:append( _pipe@2, working_directory_to_arg(erlang:element(7, Container)) ), _pipe@4 = lists:append( _pipe@3, memory_limit_to_arg(erlang:element(8, Container)) ), _pipe@5 = lists:append( _pipe@4, env_file_to_arg(erlang:element(9, Container)) ), _pipe@6 = lists:append( _pipe@5, gleam@list:flat_map( erlang:element(10, Container), fun port_to_arg/1 ) ), _pipe@7 = lists:append( _pipe@6, gleam@list:flat_map(erlang:element(11, Container), fun env_to_arg/1) ), _pipe@8 = lists:append( _pipe@7, [<<"-d"/utf8>>, erlang:element(3, Container)] ), lists:append( _pipe@8, gleam@option:unwrap(erlang:element(6, Container), []) ) end, case docker_cmd(Arguments) of {ok, {command_output, 0, Output}} -> case begin _pipe@9 = gleam@string:trim(Output), _pipe@10 = gleam@string:split(_pipe@9, <<"\n"/utf8>>), gleam@list:last(_pipe@10) end of {error, _} -> _pipe@11 = gleam@string:trim(Output), _pipe@12 = {container_could_not_be_started, _pipe@11}, {error, _pipe@12}; {ok, Container_id} -> _pipe@14 = erlang:setelement( 2, Container, begin _pipe@13 = gleam@string:trim(Container_id), {some, _pipe@13} end ), {ok, _pipe@14} end; {ok, {command_output, _, Output@1}} -> _pipe@15 = gleam@string:trim(Output@1), _pipe@16 = {container_could_not_be_started, _pipe@15}, {error, _pipe@16}; {error, Reason} -> _pipe@17 = gleam@string:trim(Reason), _pipe@18 = {container_could_not_be_started, _pipe@17}, {error, _pipe@18} end.