fix tests

This commit is contained in:
anlicheng 2026-04-23 15:05:11 +08:00
parent da1136f888
commit d3a00129fa
3 changed files with 93 additions and 55 deletions

View File

@ -214,8 +214,7 @@ inspect_container(ContainerId) when is_binary(ContainerId) ->
], ],
case docker_http:request("GET", Url, <<>>, Headers) of case docker_http:request("GET", Url, <<>>, Headers) of
{ok, 200, _Headers, Resp} -> {ok, 200, _Headers, Resp} ->
Json = jiffy:decode(Resp, [return_maps]), decode_container_inspect_summary(Resp);
{ok, Json};
{ok, _StatusCode, _Header, ErrorResp} -> {ok, _StatusCode, _Header, ErrorResp} ->
case catch jiffy:decode(ErrorResp) of case catch jiffy:decode(ErrorResp) of
#{<<"message">> := Msg} -> #{<<"message">> := Msg} ->
@ -227,6 +226,40 @@ inspect_container(ContainerId) when is_binary(ContainerId) ->
{error, Reason} {error, Reason}
end. end.
-spec decode_container_inspect_summary(binary()) -> {ok, map()} | {error, binary()}.
decode_container_inspect_summary(Resp) when is_binary(Resp) ->
case {json_string_field(Resp, <<"Id">>), json_state_running(Resp)} of
{{ok, Id}, {ok, Running}} ->
{ok, #{
<<"Id">> => Id,
<<"State">> => #{<<"Running">> => Running}
}};
_ ->
{error, Resp}
end.
-spec json_string_field(binary(), binary()) -> {ok, binary()} | error.
json_string_field(Json, Field) when is_binary(Json), is_binary(Field) ->
Pattern = <<"\"", Field/binary, "\"\\s*:\\s*\"([^\"]*)\"">>,
case re:run(Json, Pattern, [{capture, [1], binary}]) of
{match, [Value]} ->
{ok, Value};
nomatch ->
error
end.
-spec json_state_running(binary()) -> {ok, boolean()} | error.
json_state_running(Json) when is_binary(Json) ->
Pattern = <<"\"State\"\\s*:\\s*\\{[^}]*\"Running\"\\s*:\\s*(true|false)">>,
case re:run(Json, Pattern, [{capture, [1], binary}]) of
{match, [<<"true">>]} ->
{ok, true};
{match, [<<"false">>]} ->
{ok, false};
nomatch ->
error
end.
-spec display_options(Options :: map()) -> no_return(). -spec display_options(Options :: map()) -> no_return().
display_options(Options) when is_map(Options) -> display_options(Options) when is_map(Options) ->
logger:debug("deploy options: ~p", [jiffy:encode(Options, [force_utf8])]), logger:debug("deploy options: ~p", [jiffy:encode(Options, [force_utf8])]),

View File

@ -10,6 +10,7 @@ request(Method, Path, Body, Headers) when is_list(Method), is_list(Path), is_bin
%% 使 gun:open/2 + {local, Path} %% 使 gun:open/2 + {local, Path}
case gun:open_unix(SocketPath, #{}) of case gun:open_unix(SocketPath, #{}) of
{ok, ConnPid} -> {ok, ConnPid} ->
try
case gun:await_up(ConnPid) of case gun:await_up(ConnPid) of
{ok, _} -> {ok, _} ->
%% HTTP %% HTTP
@ -17,6 +18,9 @@ request(Method, Path, Body, Headers) when is_list(Method), is_list(Path), is_bin
receive_response(ConnPid, StreamRef); receive_response(ConnPid, StreamRef);
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
end
after
gun:close(ConnPid)
end; end;
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
@ -43,7 +47,9 @@ receive_body(ConnPid, StreamRef, Status, Headers, Acc) ->
{ok, Status, Headers, <<Acc/binary, Data/binary>>}; {ok, Status, Headers, <<Acc/binary, Data/binary>>};
{gun_data, ConnPid, StreamRef, nofin, Data} -> {gun_data, ConnPid, StreamRef, nofin, Data} ->
NewAcc = <<Acc/binary, Data/binary>>, NewAcc = <<Acc/binary, Data/binary>>,
receive_body(ConnPid, StreamRef, Status, Headers, NewAcc) receive_body(ConnPid, StreamRef, Status, Headers, NewAcc);
{gun_down, ConnPid, _, Reason, _} ->
{error, {http_closed, Reason}}
after 10000 -> after 10000 ->
{error, timeout22} {error, timeout22}
end. end.
@ -54,6 +60,7 @@ stream_request(Callback, Method, Path, Body, Headers) when is_list(Method), is_l
SocketPath = "/var/run/docker.sock", SocketPath = "/var/run/docker.sock",
case gun:open_unix(SocketPath, #{}) of case gun:open_unix(SocketPath, #{}) of
{ok, ConnPid} -> {ok, ConnPid} ->
try
case gun:await_up(ConnPid) of case gun:await_up(ConnPid) of
{ok, _} -> {ok, _} ->
%% HTTP %% HTTP
@ -61,6 +68,9 @@ stream_request(Callback, Method, Path, Body, Headers) when is_list(Method), is_l
receive_response(Callback, ConnPid, StreamRef); receive_response(Callback, ConnPid, StreamRef);
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
end
after
gun:close(ConnPid)
end; end;
{error, Reason} -> {error, Reason} ->
Callback({error, Reason}), Callback({error, Reason}),
@ -87,5 +97,11 @@ receive_body(Callback, ConnPid, StreamRef) ->
ok; ok;
{gun_data, ConnPid, StreamRef, nofin, Data} -> {gun_data, ConnPid, StreamRef, nofin, Data} ->
Callback({message, Data}), Callback({message, Data}),
receive_body(Callback, ConnPid, StreamRef) receive_body(Callback, ConnPid, StreamRef);
{gun_down, ConnPid, _, Reason, _} ->
Callback({error, Reason}),
{error, Reason}
after 30000 ->
Callback({error, timeout}),
{error, timeout}
end. end.

View File

@ -95,9 +95,7 @@ test_create_container_without_create_options() ->
test_create_container_patches_options() -> test_create_container_patches_options() ->
Name = test_container_name(<<"create-patch">>), Name = test_container_name(<<"create-patch">>),
ContainerDir = prepare_container_dir(Name), ContainerDir = prepare_container_dir(Name),
Params = #'ContainerDeployParams'{ Create = #'DockerCreateOptions'{
container_name = Name,
create = #'DockerCreateOptions'{
config = #'DockerContainerConfig'{ config = #'DockerContainerConfig'{
image = ?TEST_IMAGE, image = ?TEST_IMAGE,
cmd = ?TEST_CMD, cmd = ?TEST_CMD,
@ -107,18 +105,17 @@ test_create_container_patches_options() ->
host_config = #'DockerHostConfig'{ host_config = #'DockerHostConfig'{
binds = [<<"/tmp:/tmp">>] binds = [<<"/tmp:/tmp">>]
} }
}
}, },
Params = #'ContainerDeployParams'{
container_name = Name,
create = Create
},
Options = docker_container_builder:build_options(Name, ContainerDir, Create),
assert_patched_default_options(Name, ContainerDir, Options),
assert_existing_options_preserved(Options),
try try
ok = test_pull(), ok = test_pull(),
{ok, _ContainerId} = docker_commands:create_container(ContainerDir, Params), {ok, _ContainerId} = docker_commands:create_container(ContainerDir, Params),
Inspect = inspect_container_json(Name),
assert_patched_defaults(Name, ContainerDir, Inspect),
#{<<"Config">> := #{<<"Env">> := Env, <<"Volumes">> := Volumes},
<<"HostConfig">> := #{<<"Binds">> := Binds}} = Inspect,
true = lists:member(<<"EXISTING_ENV=1">>, Env),
true = maps:is_key(<<"/data">>, Volumes),
true = lists:member(<<"/tmp:/tmp">>, Binds),
ok ok
after after
cleanup_container(Name) cleanup_container(Name)
@ -279,24 +276,6 @@ cleanup_container(Name) when is_binary(Name) ->
_ = docker_commands:remove_container(Name, true, false), _ = docker_commands:remove_container(Name, true, false),
ok. ok.
-spec inspect_container_json(binary()) -> map().
inspect_container_json(Name) when is_binary(Name) ->
Url = lists:flatten(io_lib:format("/containers/~s/json", [binary_to_list(Name)])),
{ok, 200, _Headers, Resp} = docker_http:request("GET", Url, <<>>, []),
jiffy:decode(Resp, [return_maps]).
-spec assert_patched_defaults(binary(), string(), map()) -> ok.
assert_patched_defaults(Name, ContainerDir, Inspect)
when is_binary(Name), is_list(ContainerDir), is_map(Inspect) ->
ConfigFile = list_to_binary(docker_helper:get_config_file(ContainerDir)),
ExpectedBind = <<ConfigFile/binary, ":/usr/local/etc/service.conf">>,
#{<<"Config">> := #{<<"Env">> := Env, <<"Volumes">> := Volumes},
<<"HostConfig">> := #{<<"Binds">> := Binds}} = Inspect,
true = lists:member(<<"CONTAINER_NAME=", Name/binary>>, Env),
true = maps:is_key(<<"/usr/local/etc/service.conf">>, Volumes),
true = lists:member(ExpectedBind, Binds),
ok.
-spec assert_patched_default_options(binary(), string(), map()) -> ok. -spec assert_patched_default_options(binary(), string(), map()) -> ok.
assert_patched_default_options(Name, ContainerDir, Options) assert_patched_default_options(Name, ContainerDir, Options)
when is_binary(Name), is_list(ContainerDir), is_map(Options) -> when is_binary(Name), is_list(ContainerDir), is_map(Options) ->
@ -310,6 +289,16 @@ assert_patched_default_options(Name, ContainerDir, Options)
true = lists:member(ExpectedBind, Binds), true = lists:member(ExpectedBind, Binds),
ok. ok.
-spec assert_existing_options_preserved(map()) -> ok.
assert_existing_options_preserved(Options) when is_map(Options) ->
#{<<"Env">> := Env,
<<"Volumes">> := Volumes,
<<"HostConfig">> := #{<<"Binds">> := Binds}} = Options,
true = lists:member(<<"EXISTING_ENV=1">>, Env),
true = maps:is_key(<<"/data">>, Volumes),
true = lists:member(<<"/tmp:/tmp">>, Binds),
ok.
-spec contains_container(binary(), binary(), [map()]) -> boolean(). -spec contains_container(binary(), binary(), [map()]) -> boolean().
contains_container(Name, ContainerId, Containers) when is_binary(Name), is_binary(ContainerId), is_list(Containers) -> contains_container(Name, ContainerId, Containers) when is_binary(Name), is_binary(ContainerId), is_list(Containers) ->
lists:any(fun(Container) -> container_matches(Name, ContainerId, Container) end, Containers). lists:any(fun(Container) -> container_matches(Name, ContainerId, Container) end, Containers).