defmodule Testcontainers.MinioContainer do @moduledoc """ Provides functionality for creating and managing Minio container configurations. """ alias Testcontainers.Container alias Testcontainers.MinioContainer alias Testcontainers.ContainerBuilder alias Testcontainers.LogWaitStrategy @default_image "minio/minio" @default_tag "RELEASE.2023-11-11T08-14-41Z" @default_image_with_tag "#{@default_image}:#{@default_tag}" @default_username "minioadmin" @default_password "minioadmin" @default_s3_port 9000 @default_ui_port 9001 @default_wait_timeout 60_000 @enforce_keys [:image, :username, :password, :wait_timeout] defstruct [ :image, :username, :password, :wait_timeout, reuse: false ] def new, do: %__MODULE__{ image: @default_image_with_tag, username: @default_username, password: @default_password, wait_timeout: @default_wait_timeout } @doc """ Set the reuse flag to reuse the container if it is already running. """ def with_reuse(%__MODULE__{} = config, reuse) when is_boolean(reuse) do %__MODULE__{config | reuse: reuse} end def get_username, do: @default_username def get_password, do: @default_password def default_ui_port, do: @default_ui_port def default_s3_port, do: @default_s3_port @doc """ Retrieves the port mapped by the Docker host for the Minio container. """ def port(%Container{} = container), do: Testcontainers.get_port(container, @default_s3_port) @doc """ Generates the connection URL for accessing the Minio service running within the container. """ def connection_url(%Container{} = container) do "http://#{Testcontainers.get_host(container)}:#{port(container)}" end @doc """ Generates the connection options for accessing the Minio service running within the container. Compatible with what ex_aws expects in `ExAws.request(options)` """ def connection_opts(%Container{} = container) do [ port: MinioContainer.port(container), scheme: "http://", host: Testcontainers.get_host(container), access_key_id: container.environment[:MINIO_ROOT_USER], secret_access_key: container.environment[:MINIO_ROOT_PASSWORD] ] end defimpl ContainerBuilder do import Container @spec build(%MinioContainer{}) :: %Container{} @impl true def build(%MinioContainer{} = config) do new(config.image) |> with_exposed_ports([MinioContainer.default_s3_port(), MinioContainer.default_ui_port()]) |> with_environment(:MINIO_ROOT_USER, config.username) |> with_environment(:MINIO_ROOT_PASSWORD, config.password) |> with_reuse(config.reuse) |> with_cmd([ "server", "--console-address", ":#{MinioContainer.default_ui_port()}", "/data" ]) |> with_waiting_strategy( LogWaitStrategy.new(~r/.*Status: 1 Online, 0 Offline..*/, config.wait_timeout) ) end @impl true def after_start(_config, _container, _conn), do: :ok end end