Packages

A Common Test hook for starting and stopping docker-compose services

Current section

Files

Jump to
docker_compose_cth src docker_compose_cth.erl
Raw

src/docker_compose_cth.erl

-module(docker_compose_cth).
-export([init/2,
pre_init_per_suite/3,
terminate/1]).
-define(DEFAULTS, #{docker_compose_path => undefined,
executable_search_path => undefined,
check_if_running => false,
skip_or_fail => fail}).
-type state() :: #{docker_compose_path := filename:filename_all() | undefined,
executable_search_path := [filename:filename_all()],
check_if_running := string() | {string(), [string()]} | false,
skip_or_fail := skip | fail}.
%% Always called before any other callback function. Use this to initiate
%% any common state.
init(_Id, Opts) when is_map(Opts) ->
State = maps:merge(?DEFAULTS, ct:get_config(docker_compose_cth, #{})),
{ok, maps:merge(State, Opts)};
init(_Id, _Opts) ->
State = maps:merge(?DEFAULTS, ct:get_config(docker_compose_cth, #{})),
{ok, State}.
%% Called before init_per_suite is called.
pre_init_per_suite(_Suite, Config, State=#{executable_search_path := Path}) ->
case find_executable("docker-compose", Path) of
false ->
{{fail, "docker-compose not found in PATH"}, State};
DockerCompose ->
State1 = State#{docker_compose_path => DockerCompose},
case up_if_not_running(State1) of
ok ->
{Config, State1};
{fail, _}=Fail ->
{Fail, State1}
end
end.
%% TODO support shutting down post suite
%% TODO support not running down here if shutdown in post suite or no_shutdown is true
terminate(#{docker_compose_path := undefined}) ->
ok;
terminate(#{docker_compose_path := DockerCompose}) ->
down(DockerCompose).
%%
-spec up_if_not_running(state()) -> ok | {fail, term()}.
up_if_not_running(#{docker_compose_path := DockerCompose,
check_if_running := CheckIfRunning}) ->
case check_if_running(DockerCompose, CheckIfRunning) of
true ->
ok;
false ->
up(DockerCompose)
end.
find_executable(Executable, undefined) ->
os:find_executable(Executable);
find_executable(Executable, Path) ->
os:find_executable(Executable, Path).
check_if_running(_DockerCompose, false) ->
false;
check_if_running(DockerCompose, {Service, Command}) ->
0 =:= do(DockerCompose, ["exec", "-T", Service | Command]);
check_if_running(DockerCompose, Service) ->
check_if_running(DockerCompose, {Service, ["ls"]}).
up(DockerCompose) ->
case do(DockerCompose, ["up", "-d"]) of
127 ->
{fail, "docker-compose executable not found to run"};
0 ->
ok;
E ->
{fail, io_lib:format("docker-compose failed to run, exit_status=~p", [E])}
end.
down(DockerCompose) ->
case do(DockerCompose, ["down"]) of
0 ->
ok;
E ->
ct:pal("Failed to run 'docker-compose down' exit_status=~p", [E]),
ok
end.
do(Executable, Args) ->
Port = open_port({spawn_executable, Executable}, [exit_status,
{args, Args}]),
receive
{Port, {exit_status, E}} ->
E
end.