diff --git a/lib/container/redis_container.ex b/lib/container/redis_container.ex index ff22a61..2450991 100644 --- a/lib/container/redis_container.ex +++ b/lib/container/redis_container.ex @@ -25,7 +25,8 @@ defmodule Testcontainers.RedisContainer do :port, :wait_timeout, check_image: @default_image, - reuse: false + reuse: false, + password: nil ] @doc """ @@ -35,7 +36,8 @@ defmodule Testcontainers.RedisContainer do do: %__MODULE__{ image: @default_image_with_tag, wait_timeout: @default_wait_timeout, - port: @default_port + port: @default_port, + password: nil } @doc """ @@ -68,6 +70,20 @@ defmodule Testcontainers.RedisContainer do %{config | port: port} end + @doc """ + Sets the password for the Redis container. + + ## Examples + + iex> config = RedisContainer.new() + iex> new_config = RedisContainer.with_password(config, "secret") + iex> new_config.password + "secret" + """ + def with_password(%__MODULE__{} = config, password) when is_binary(password) do + %{config | password: password} + end + @doc """ Overrides the default wait timeout used for the Redis container. @@ -122,8 +138,11 @@ defmodule Testcontainers.RedisContainer do iex> RedisContainer.connection_url(container) "http://localhost:32768" # This value will be different depending on the mapped port. """ - def connection_url(%Container{} = container), - do: "redis://#{Testcontainers.get_host()}:#{port(container)}/" + def connection_url(%Container{} = container) do + password = container.environment[:REDIS_PASSWORD] + auth_part = if password, do: ":#{password}@", else: "" + "redis://#{auth_part}#{Testcontainers.get_host()}:#{port(container)}/" + end defimpl ContainerBuilder do import Container @@ -149,14 +168,31 @@ defmodule Testcontainers.RedisContainer do @spec build(%RedisContainer{}) :: %Container{} @impl true def build(%RedisContainer{} = config) do - new(config.image) - |> with_exposed_port(config.port) - |> with_waiting_strategy( - CommandWaitStrategy.new(["redis-cli", "PING"], config.wait_timeout) - ) - |> with_check_image(config.check_image) - |> with_reuse(config.reuse) - |> valid_image!() + container = + new(config.image) + |> with_exposed_port(config.port) + |> with_check_image(config.check_image) + |> with_reuse(config.reuse) + + container = + if config.password do + container + |> with_cmd(["redis-server", "--requirepass", config.password]) + |> with_waiting_strategy( + CommandWaitStrategy.new( + ["redis-cli", "-a", config.password, "PING"], + config.wait_timeout + ) + ) + |> with_environment("REDIS_PASSWORD", config.password) + else + container + |> with_waiting_strategy( + CommandWaitStrategy.new(["redis-cli", "PING"], config.wait_timeout) + ) + end + + valid_image!(container) end @impl true diff --git a/test/container/redis_container_test.exs b/test/container/redis_container_test.exs index 786aa64..cd84cac 100644 --- a/test/container/redis_container_test.exs +++ b/test/container/redis_container_test.exs @@ -18,4 +18,14 @@ defmodule Testcontainers.Container.RedisContainerTest do assert Redix.command!(conn, ["PING"]) == "PONG" end end + + describe "with password configuration" do + container(:redis, RedisContainer.new() |> RedisContainer.with_password("secret")) + + test "provides a ready-to-use redis container with password", %{redis: redis} do + {:ok, conn} = Redix.start_link(RedisContainer.connection_url(redis)) + + assert Redix.command!(conn, ["PING"]) == "PONG" + end + end end