# SPDX-License-Identifier: MIT defmodule TestcontainerEx.RedisContainer do @moduledoc """ Provides functionality for creating and managing Redis container configurations. """ alias TestcontainerEx.CommandWaitStrategy alias TestcontainerEx.Container.Builder alias TestcontainerEx.Container.Config alias TestcontainerEx.RedisContainer use TestcontainerEx.ContainerConfig @default_image "redis" @default_tag "7.2-alpine" @default_image_with_tag "#{@default_image}:#{@default_tag}" @default_port 6379 @default_wait_timeout 60_000 @type t :: %__MODULE__{} @enforce_keys [:image, :port, :wait_timeout] defstruct [ :image, :port, :wait_timeout, :name, check_image: @default_image, reuse: false, password: nil ] def new, do: %__MODULE__{ image: @default_image_with_tag, wait_timeout: @default_wait_timeout, port: @default_port, password: nil } def with_image(%__MODULE__{} = config, image) when is_binary(image) do %{config | image: image} end def with_port(%__MODULE__{} = config, port) when is_integer(port) do %{config | port: port} end def with_password(%__MODULE__{} = config, password) when is_binary(password) do %{config | password: password} end def with_wait_timeout(%__MODULE__{} = config, wait_timeout) when is_integer(wait_timeout) do %{config | wait_timeout: wait_timeout} end @doc """ Sets the container name. """ @spec with_name(t(), String.t()) :: t() def with_name(%__MODULE__{} = config, name) when is_binary(name) do %__MODULE__{config | name: name} end def default_image, do: @default_image def port(%Config{} = container), do: TestcontainerEx.get_port(container, @default_port) def connection_url(%Config{} = container) do password = container.environment[:REDIS_PASSWORD] auth_part = if password, do: ":#{password}@", else: "" "redis://#{auth_part}#{TestcontainerEx.get_host(container)}:#{port(container)}/" end defimpl Builder do @spec build(RedisContainer.t()) :: Config.t() @impl true def build(%RedisContainer{} = config) do container = Config.new(config.image) |> Config.with_exposed_port(config.port) |> Config.with_check_image(config.check_image) |> Config.with_reuse(config.reuse) |> then(fn cfg -> if config.name, do: Config.with_name(cfg, config.name), else: cfg end) container = if config.password do container |> Config.with_cmd(["redis-server", "--requirepass", config.password]) |> Config.with_waiting_strategy( CommandWaitStrategy.new( ["redis-cli", "-a", config.password, "PING"], config.wait_timeout ) ) |> Config.with_environment("REDIS_PASSWORD", config.password) else container |> Config.with_waiting_strategy( CommandWaitStrategy.new(["redis-cli", "PING"], config.wait_timeout) ) end Config.valid_image!(container) end @impl true def after_start(_config, _container, _conn), do: :ok end end