Current section
Files
Jump to
Current section
Files
src/testcontainer@internal@docker.erl
-module(testcontainer@internal@docker).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/testcontainer/internal/docker.gleam").
-export([parse_response/1, ping/0, image_exists/1, pull_image/2, create_container/1, start_container/1, stop_container/2, remove_container/1, inspect_container/1, container_logs/2, exec_container/2, create_network/1, remove_network/1, copy_file_to/3]).
-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(false).
-file("src/testcontainer/internal/docker.gleam", 50).
?DOC(false).
-spec parse_response(binary()) -> {ok, {integer(), binary()}} |
{error, binary()}.
parse_response(Data) ->
docker_transport:parse_response(Data).
-file("src/testcontainer/internal/docker.gleam", 63).
?DOC(false).
-spec encode_grapheme(binary()) -> binary().
encode_grapheme(G) ->
case G of
<<"%"/utf8>> ->
<<"%25"/utf8>>;
<<"\r"/utf8>> ->
<<"%0D"/utf8>>;
<<"\n"/utf8>> ->
<<"%0A"/utf8>>;
<<" "/utf8>> ->
<<"%20"/utf8>>;
<<"/"/utf8>> ->
<<"%2F"/utf8>>;
<<":"/utf8>> ->
<<"%3A"/utf8>>;
<<"="/utf8>> ->
<<"%3D"/utf8>>;
<<"?"/utf8>> ->
<<"%3F"/utf8>>;
<<"&"/utf8>> ->
<<"%26"/utf8>>;
<<"#"/utf8>> ->
<<"%23"/utf8>>;
<<"+"/utf8>> ->
<<"%2B"/utf8>>;
Other ->
Other
end.
-file("src/testcontainer/internal/docker.gleam", 54).
?DOC(false).
-spec url_encode(binary()) -> binary().
url_encode(Input) ->
_pipe = Input,
_pipe@1 = gleam@string:to_graphemes(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun encode_grapheme/1),
erlang:list_to_binary(_pipe@2).
-file("src/testcontainer/internal/docker.gleam", 80).
?DOC(false).
-spec contains_crlf(binary()) -> boolean().
contains_crlf(Input) ->
gleam_stdlib:contains_string(Input, <<"\r"/utf8>>) orelse gleam_stdlib:contains_string(
Input,
<<"\n"/utf8>>
).
-file("src/testcontainer/internal/docker.gleam", 97).
?DOC(false).
-spec request_with_headers(
binary(),
binary(),
list({binary(), binary()}),
binary()
) -> {ok, {integer(), binary()}} | {error, testcontainer@error:error()}.
request_with_headers(Method, Path, Headers, Body) ->
case docker_transport:request(Method, Path, Headers, Body) of
{ok, {Status, Response}} ->
{ok, {Status, Response}};
{error, Reason} ->
{error,
{docker_unavailable, docker_transport:socket_path(), Reason}}
end.
-file("src/testcontainer/internal/docker.gleam", 84).
?DOC(false).
-spec request(binary(), binary(), binary()) -> {ok, {integer(), binary()}} |
{error, testcontainer@error:error()}.
request(Method, Path, Body) ->
request_with_headers(
Method,
Path,
[{<<"Content-Type"/utf8>>, <<"application/json"/utf8>>}],
Body
).
-file("src/testcontainer/internal/docker.gleam", 110).
?DOC(false).
-spec check_ok(binary(), binary(), integer(), binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
check_ok(Method, Path, Status, Body) ->
case Status of
200 ->
{ok, nil};
201 ->
{ok, nil};
204 ->
{ok, nil};
_ ->
{error, {docker_api_error, Method, Path, Status, Body}}
end.
-file("src/testcontainer/internal/docker.gleam", 124).
?DOC(false).
-spec request_ok(binary(), binary(), binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
request_ok(Method, Path, Body) ->
case request(Method, Path, Body) of
{ok, {Status, Response}} ->
check_ok(Method, Path, Status, Response);
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 135).
?DOC(false).
-spec request_json(binary(), binary(), gleam@json:json()) -> {ok, binary()} |
{error, testcontainer@error:error()}.
request_json(Method, Path, Body) ->
Body_string = gleam@json:to_string(Body),
case request(Method, Path, Body_string) of
{ok, {200, Response}} ->
{ok, Response};
{ok, {201, Response@1}} ->
{ok, Response@1};
{ok, {Status, Response@2}} ->
{error, {docker_api_error, Method, Path, Status, Response@2}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 150).
?DOC(false).
-spec ping() -> {ok, nil} | {error, testcontainer@error:error()}.
ping() ->
request_ok(<<"GET"/utf8>>, <<"/_ping"/utf8>>, <<""/utf8>>).
-file("src/testcontainer/internal/docker.gleam", 155).
?DOC(false).
-spec image_exists(binary()) -> boolean().
image_exists(Image) ->
Encoded = url_encode(Image),
case request(
<<"GET"/utf8>>,
<<<<"/images/"/utf8, Encoded/binary>>/binary, "/json"/utf8>>,
<<""/utf8>>
) of
{ok, {200, _}} ->
true;
_ ->
false
end.
-file("src/testcontainer/internal/docker.gleam", 213).
?DOC(false).
-spec scan_pull_stream_for_error(binary()) -> gleam@option:option(binary()).
scan_pull_stream_for_error(Stream) ->
case gleam@string:split_once(Stream, <<"\"error\":\""/utf8>>) of
{ok, {_, Rest}} ->
case gleam@string:split_once(Rest, <<"\""/utf8>>) of
{ok, {Msg, _}} ->
{some, Msg};
{error, _} ->
{some, <<"image pull failed"/utf8>>}
end;
{error, _} ->
none
end.
-file("src/testcontainer/internal/docker.gleam", 202).
?DOC(false).
-spec encode_registry_auth(testcontainer@internal@config:registry_auth()) -> binary().
encode_registry_auth(A) ->
Payload = gleam@json:object(
[{<<"username"/utf8>>, gleam@json:string(erlang:element(2, A))},
{<<"password"/utf8>>,
gleam@json:string(cowl:reveal(erlang:element(3, A)))}]
),
gleam_stdlib:base64_encode(
<<(gleam@json:to_string(Payload))/binary>>,
false
).
-file("src/testcontainer/internal/docker.gleam", 163).
?DOC(false).
-spec pull_image(
binary(),
gleam@option:option(testcontainer@internal@config:registry_auth())
) -> {ok, nil} | {error, testcontainer@error:error()}.
pull_image(Image, Auth) ->
Ref = testcontainer@internal@image_ref:parse(Image),
Path = <<<<<<"/images/create?fromImage="/utf8,
(url_encode(erlang:element(2, Ref)))/binary>>/binary,
"&tag="/utf8>>/binary,
(url_encode(erlang:element(3, Ref)))/binary>>,
Headers = case Auth of
{some, A} ->
[{<<"Content-Type"/utf8>>, <<"application/json"/utf8>>},
{<<"X-Registry-Auth"/utf8>>, encode_registry_auth(A)}];
none ->
[{<<"Content-Type"/utf8>>, <<"application/json"/utf8>>}]
end,
case request_with_headers(<<"POST"/utf8>>, Path, Headers, <<""/utf8>>) of
{ok, {Status, Body}} when Status =:= 200 ->
case scan_pull_stream_for_error(Body) of
{some, Reason} ->
{error, {image_pull_failed, Image, Reason}};
none ->
{ok, nil}
end;
{ok, {Status@1, Body@1}} ->
{error,
{image_pull_failed,
Image,
<<<<<<"HTTP "/utf8,
(erlang:integer_to_binary(Status@1))/binary>>/binary,
": "/utf8>>/binary,
Body@1/binary>>}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 391).
?DOC(false).
-spec validate_volumes(testcontainer@container:container_spec()) -> {ok, nil} |
{error, testcontainer@error:error()}.
validate_volumes(Spec) ->
Bad = gleam@list:find(
testcontainer@container:volumes(Spec),
fun(V) -> case testcontainer@container:volume_kind(V) of
{ok, {Host, Cpath, _}} ->
(contains_crlf(Host) orelse contains_crlf(Cpath)) orelse gleam_stdlib:contains_string(
Host,
<<":"/utf8>>
);
{error, P} ->
contains_crlf(P)
end end
),
case Bad of
{ok, _} ->
{error,
{container_create_failed,
testcontainer@container:image(Spec),
<<"volume path invalid (CR/LF or ':' in host path)"/utf8>>}};
{error, nil} ->
{ok, nil}
end.
-file("src/testcontainer/internal/docker.gleam", 379).
?DOC(false).
-spec validate_ports(testcontainer@container:container_spec()) -> {ok, nil} |
{error, testcontainer@error:error()}.
validate_ports(Spec) ->
Bad = gleam@list:find(
testcontainer@container:ports(Spec),
fun(P) ->
N = testcontainer@port:number(P),
(N < 1) orelse (N > 65535)
end
),
case Bad of
{ok, P@1} ->
{error, {invalid_port, testcontainer@port:number(P@1)}};
{error, nil} ->
{ok, nil}
end.
-file("src/testcontainer/internal/docker.gleam", 357).
?DOC(false).
-spec validate_spec(testcontainer@container:container_spec()) -> {ok, nil} |
{error, testcontainer@error:error()}.
validate_spec(Spec) ->
Image = testcontainer@container:image(Spec),
gleam@result:'try'(case contains_crlf(Image) of
true ->
{error, {invalid_image_ref, Image}};
false ->
{ok, nil}
end, fun(_) ->
gleam@result:'try'(case testcontainer@container:name(Spec) of
{some, N} ->
case contains_crlf(N) of
true ->
{error,
{container_create_failed,
Image,
<<"container name contains CR/LF"/utf8>>}};
false ->
{ok, nil}
end;
none ->
{ok, nil}
end, fun(_) ->
gleam@result:'try'(
validate_ports(Spec),
fun(_) -> validate_volumes(Spec) end
)
end)
end).
-file("src/testcontainer/internal/docker.gleam", 224).
?DOC(false).
-spec create_container(testcontainer@container:container_spec()) -> {ok,
binary()} |
{error, testcontainer@error:error()}.
create_container(Spec) ->
gleam@result:'try'(
validate_spec(Spec),
fun(_) ->
Cmd = case testcontainer@container:command(Spec) of
{some, C} ->
gleam@json:array(C, fun gleam@json:string/1);
none ->
gleam@json:null()
end,
Entrypoint = case testcontainer@container:entrypoint(Spec) of
{some, E} ->
gleam@json:array(E, fun gleam@json:string/1);
none ->
gleam@json:null()
end,
Env_list = gleam@list:map(
testcontainer@container:env(Spec),
fun(Pair) ->
gleam@json:string(
<<<<(erlang:element(1, Pair))/binary, "="/utf8>>/binary,
(cowl:reveal(erlang:element(2, Pair)))/binary>>
)
end
),
Port_keys = gleam@list:map(
testcontainer@container:ports(Spec),
fun(P) ->
<<<<(erlang:integer_to_binary(testcontainer@port:number(P)))/binary,
"/"/utf8>>/binary,
(testcontainer@port:protocol(P))/binary>>
end
),
Exposed_ports = gleam@json:object(
gleam@list:map(
Port_keys,
fun(K) -> {K, gleam@json:object([])} end
)
),
Port_bindings = gleam@json:object(
gleam@list:map(
Port_keys,
fun(K@1) ->
{K@1,
gleam@json:array(
[gleam@json:object(
[{<<"HostIp"/utf8>>,
gleam@json:string(<<""/utf8>>)},
{<<"HostPort"/utf8>>,
gleam@json:string(<<""/utf8>>)}]
)],
fun(X) -> X end
)}
end
)
),
Binds = gleam@list:filter_map(
testcontainer@container:volumes(Spec),
fun(V) -> case testcontainer@container:volume_kind(V) of
{ok, {Host, Cpath, Ro}} ->
Mode = case Ro of
true ->
<<":ro"/utf8>>;
false ->
<<":rw"/utf8>>
end,
{ok,
gleam@json:string(
<<<<<<Host/binary, ":"/utf8>>/binary,
Cpath/binary>>/binary,
Mode/binary>>
)};
{error, _} ->
{error, nil}
end end
),
Tmpfs_entries = gleam@list:filter_map(
testcontainer@container:volumes(Spec),
fun(V@1) -> case testcontainer@container:volume_kind(V@1) of
{error, Cpath@1} ->
{ok, {Cpath@1, gleam@json:string(<<""/utf8>>)}};
{ok, _} ->
{error, nil}
end end
),
Labels_obj = gleam@json:object(
gleam@list:map(
testcontainer@container:labels(Spec),
fun(Pair@1) ->
{erlang:element(1, Pair@1),
gleam@json:string(erlang:element(2, Pair@1))}
end
)
),
Network_mode = case testcontainer@container:network(Spec) of
{some, N} ->
gleam@json:string(N);
none ->
gleam@json:string(<<"bridge"/utf8>>)
end,
Networking_config = case testcontainer@container:network(Spec) of
{some, N@1} ->
gleam@json:object(
[{<<"EndpointsConfig"/utf8>>,
gleam@json:object(
[{N@1, gleam@json:object([])}]
)}]
);
none ->
gleam@json:object([])
end,
Host_config = gleam@json:object(
[{<<"PortBindings"/utf8>>, Port_bindings},
{<<"Binds"/utf8>>,
gleam@json:array(Binds, fun(X@1) -> X@1 end)},
{<<"Tmpfs"/utf8>>, gleam@json:object(Tmpfs_entries)},
{<<"Privileged"/utf8>>,
gleam@json:bool(
testcontainer@container:is_privileged(Spec)
)},
{<<"NetworkMode"/utf8>>, Network_mode}]
),
Body = gleam@json:object(
[{<<"Image"/utf8>>,
gleam@json:string(testcontainer@container:image(Spec))},
{<<"Cmd"/utf8>>, Cmd},
{<<"Entrypoint"/utf8>>, Entrypoint},
{<<"Env"/utf8>>,
gleam@json:array(Env_list, fun(X@2) -> X@2 end)},
{<<"ExposedPorts"/utf8>>, Exposed_ports},
{<<"Labels"/utf8>>, Labels_obj},
{<<"HostConfig"/utf8>>, Host_config},
{<<"NetworkingConfig"/utf8>>, Networking_config}]
),
Path = case testcontainer@container:name(Spec) of
{some, N@2} ->
<<"/containers/create?name="/utf8,
(url_encode(N@2))/binary>>;
none ->
<<"/containers/create"/utf8>>
end,
case request_json(<<"POST"/utf8>>, Path, Body) of
{ok, Response} ->
case gleam@json:parse(
Response,
gleam@dynamic@decode:at(
[<<"Id"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
) of
{ok, Id} ->
{ok, Id};
{error, _} ->
{error,
{container_create_failed,
testcontainer@container:image(Spec),
<<"unable to parse create response"/utf8>>}}
end;
{error, {docker_api_error, _, _, Status, Body_str}} ->
{error,
{container_create_failed,
testcontainer@container:image(Spec),
<<<<<<"HTTP "/utf8,
(erlang:integer_to_binary(Status))/binary>>/binary,
": "/utf8>>/binary,
Body_str/binary>>}};
{error, E@1} ->
{error, E@1}
end
end
).
-file("src/testcontainer/internal/docker.gleam", 412).
?DOC(false).
-spec start_container(binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
start_container(Id) ->
case request(
<<"POST"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "/start"/utf8>>,
<<""/utf8>>
) of
{ok, {Status, _}} when (Status =:= 204) orelse (Status =:= 304) ->
{ok, nil};
{ok, {Status@1, Body}} ->
{error,
{container_start_failed,
Id,
<<<<<<"HTTP "/utf8,
(erlang:integer_to_binary(Status@1))/binary>>/binary,
": "/utf8>>/binary,
Body/binary>>}};
{error, {docker_unavailable, _, Reason}} ->
{error, {container_start_failed, Id, Reason}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 426).
?DOC(false).
-spec stop_container(binary(), integer()) -> {ok, nil} |
{error, testcontainer@error:error()}.
stop_container(Id, Timeout_sec) ->
Path = <<<<<<"/containers/"/utf8, Id/binary>>/binary, "/stop?t="/utf8>>/binary,
(erlang:integer_to_binary(Timeout_sec))/binary>>,
case request(<<"POST"/utf8>>, Path, <<""/utf8>>) of
{ok, {Status, _}} when (Status =:= 204) orelse (Status =:= 304) ->
{ok, nil};
{ok, {Status@1, Body}} ->
{error,
{container_stop_failed,
Id,
<<<<<<"HTTP "/utf8,
(erlang:integer_to_binary(Status@1))/binary>>/binary,
": "/utf8>>/binary,
Body/binary>>}};
{error, {docker_unavailable, _, Reason}} ->
{error, {container_stop_failed, Id, Reason}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 445).
?DOC(false).
-spec remove_container(binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
remove_container(Id) ->
request_ok(
<<"DELETE"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "?force=true"/utf8>>,
<<""/utf8>>
).
-file("src/testcontainer/internal/docker.gleam", 449).
?DOC(false).
-spec inspect_container(binary()) -> {ok, binary()} |
{error, testcontainer@error:error()}.
inspect_container(Id) ->
case request(
<<"GET"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "/json"/utf8>>,
<<""/utf8>>
) of
{ok, {200, Response}} ->
{ok, Response};
{ok, {Status, Response@1}} ->
{error,
{docker_api_error,
<<"GET"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "/json"/utf8>>,
Status,
Response@1}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 463).
?DOC(false).
-spec container_logs(binary(), gleam@option:option(integer())) -> {ok, binary()} |
{error, testcontainer@error:error()}.
container_logs(Id, Tail) ->
Tail_q = case Tail of
{some, N} ->
<<"&tail="/utf8, (erlang:integer_to_binary(N))/binary>>;
none ->
<<"&tail=all"/utf8>>
end,
case request(
<<"GET"/utf8>>,
<<<<<<"/containers/"/utf8, Id/binary>>/binary,
"/logs?stdout=1&stderr=1"/utf8>>/binary,
Tail_q/binary>>,
<<""/utf8>>
) of
{ok, {200, Response}} ->
{ok, docker_transport:strip_log_frames(Response)};
{ok, {Status, Response@1}} ->
{error,
{docker_api_error,
<<"GET"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "/logs"/utf8>>,
Status,
Response@1}};
{error, E} ->
{error, E}
end.
-file("src/testcontainer/internal/docker.gleam", 494).
?DOC(false).
-spec exec_container(binary(), list(binary())) -> {ok,
testcontainer@exec:exec_result()} |
{error, testcontainer@error:error()}.
exec_container(Id, Cmd) ->
Create_body = gleam@json:object(
[{<<"Cmd"/utf8>>, gleam@json:array(Cmd, fun gleam@json:string/1)},
{<<"AttachStdout"/utf8>>, gleam@json:bool(true)},
{<<"AttachStderr"/utf8>>, gleam@json:bool(true)}]
),
gleam@result:'try'(
begin
_pipe = request_json(
<<"POST"/utf8>>,
<<<<"/containers/"/utf8, Id/binary>>/binary, "/exec"/utf8>>,
Create_body
),
gleam@result:map_error(_pipe, fun(E) -> case E of
{docker_api_error, _, _, Status, Body} ->
{exec_failed,
Id,
Cmd,
-1,
<<<<<<"create exec HTTP "/utf8,
(erlang:integer_to_binary(Status))/binary>>/binary,
": "/utf8>>/binary,
Body/binary>>};
_ ->
E
end end)
end,
fun(Exec_resp) ->
gleam@result:'try'(
case gleam@json:parse(
Exec_resp,
gleam@dynamic@decode:at(
[<<"Id"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
) of
{ok, Eid} ->
{ok, Eid};
{error, _} ->
{error,
{exec_failed,
Id,
Cmd,
-1,
<<"unable to parse exec create response"/utf8>>}}
end,
fun(Exec_id) ->
Start_body = gleam@json:object(
[{<<"Detach"/utf8>>, gleam@json:bool(false)},
{<<"Tty"/utf8>>, gleam@json:bool(false)}]
),
gleam@result:'try'(
case request(
<<"POST"/utf8>>,
<<<<"/exec/"/utf8, Exec_id/binary>>/binary,
"/start"/utf8>>,
gleam@json:to_string(Start_body)
) of
{ok, {200, Body@1}} ->
{ok, Body@1};
{ok, {Status@1, Body@2}} ->
{error,
{exec_failed,
Id,
Cmd,
-1,
<<<<<<"start exec HTTP "/utf8,
(erlang:integer_to_binary(
Status@1
))/binary>>/binary,
": "/utf8>>/binary,
Body@2/binary>>}};
{error, E@1} ->
{error, E@1}
end,
fun(Raw) ->
{Stdout, Stderr} = docker_transport:split_log_streams(
Raw
),
gleam@result:'try'(
case request(
<<"GET"/utf8>>,
<<<<"/exec/"/utf8, Exec_id/binary>>/binary,
"/json"/utf8>>,
<<""/utf8>>
) of
{ok, {200, Body@3}} ->
case gleam@json:parse(
Body@3,
gleam@dynamic@decode:at(
[<<"ExitCode"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_int/1}
)
) of
{ok, Code} ->
{ok, Code};
{error, _} ->
{error,
{exec_failed,
Id,
Cmd,
-1,
<<"unable to parse exec inspect response"/utf8>>}}
end;
{ok, {Status@2, Body@4}} ->
{error,
{exec_failed,
Id,
Cmd,
-1,
<<<<<<"inspect exec HTTP "/utf8,
(erlang:integer_to_binary(
Status@2
))/binary>>/binary,
": "/utf8>>/binary,
Body@4/binary>>}};
{error, E@2} ->
{error, E@2}
end,
fun(Exit_code) ->
{ok,
{exec_result, Exit_code, Stdout, Stderr}}
end
)
end
)
end
)
end
).
-file("src/testcontainer/internal/docker.gleam", 591).
?DOC(false).
-spec create_network(binary()) -> {ok, binary()} |
{error, testcontainer@error:error()}.
create_network(Name) ->
case contains_crlf(Name) of
true ->
{error,
{docker_api_error,
<<"POST"/utf8>>,
<<"/networks/create"/utf8>>,
0,
<<"network name contains CR/LF"/utf8>>}};
false ->
Body = gleam@json:object(
[{<<"Name"/utf8>>, gleam@json:string(Name)},
{<<"Driver"/utf8>>, gleam@json:string(<<"bridge"/utf8>>)}]
),
case request_json(
<<"POST"/utf8>>,
<<"/networks/create"/utf8>>,
Body
) of
{ok, Response} ->
case gleam@json:parse(
Response,
gleam@dynamic@decode:at(
[<<"Id"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
) of
{ok, Nid} ->
{ok, Nid};
{error, _} ->
{error,
{docker_api_error,
<<"POST"/utf8>>,
<<"/networks/create"/utf8>>,
0,
<<"parse error"/utf8>>}}
end;
{error, E} ->
{error, E}
end
end.
-file("src/testcontainer/internal/docker.gleam", 624).
?DOC(false).
-spec remove_network(binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
remove_network(Id) ->
request_ok(<<"DELETE"/utf8>>, <<"/networks/"/utf8, Id/binary>>, <<""/utf8>>).
-file("src/testcontainer/internal/docker.gleam", 635).
?DOC(false).
-spec copy_file_to(binary(), binary(), binary()) -> {ok, nil} |
{error, testcontainer@error:error()}.
copy_file_to(Container_id, Host_path, Container_path) ->
case (contains_crlf(Container_id) orelse contains_crlf(Host_path)) orelse contains_crlf(
Container_path
) of
true ->
{error,
{file_copy_failed,
Container_path,
<<"path contains CR/LF"/utf8>>}};
false ->
case docker_transport:copy_file_to_container(
Container_id,
Host_path,
Container_path
) of
{ok, nil} ->
{ok, nil};
{error, Reason} ->
{error, {file_copy_failed, Container_path, Reason}}
end
end.