defmodule Compox do @moduledoc """ Module to work with a Docker environment for testing. Compox starts Docker containers when the application starts (see [configuration](#configuration) for more info). ## Containers availability Compox makes two checks to ensure the containers are available: * the container has `running` status. * the exposed ports to the host, if any, accept connections. ## Configuration * `auto_start`: Whether the docker compose services should start with this application. Defaults to `true`. * `auto_stop`: Whether the docker compose services should stop after the tests. Defaults to `true`. * `exclude`: The list of Docker services to exclude. These services won't be started by Compox. """ use GenServer, restart: :transient require Logger alias Compox.Docker.Compose alias Compox.Docker.Services @doc false def start_link(opts) when is_list(opts) do Mix.shell().info("[compox] Starting containers...") GenServer.start_link(__MODULE__, opts, name: __MODULE__) end @doc """ Stops all the started containers. Any container started using the `docker-compose.yml` will be stopped. """ @spec stop() :: :ok def stop() do if Application.get_env(:compox, :auto_stop, true) do Mix.shell().info("[compox] Stopping containers...") GenServer.call(__MODULE__, :stop) end end @doc false @impl GenServer def init(opts) do if Keyword.get(opts, :auto_start, true) do services = Compose.up(opts) Mix.shell().info("[compox] All containers up!") {:ok, %{services: services}} else {:ok, %{services: []}} end end @doc false @impl GenServer def handle_call(:stop, _from, %{services: services}) do Services.stop(services) Mix.shell().info("[compox] All containers gone!") {:reply, :ok, nil} end @doc false @impl GenServer def handle_info(_message, state) do {:noreply, state} end end