diff --git a/lib/redix/start_options.ex b/lib/redix/start_options.ex index b841223..57904db 100644 --- a/lib/redix/start_options.ex +++ b/lib/redix/start_options.ex @@ -209,7 +209,8 @@ defmodule Redix.StartOptions do """ ], password: [ - type: :string, + type: {:or, [:string, :mfa]}, + type_doc: "`String.t/0` or `{mod, fun, args}`", doc: """ if you don't want to specify a password for each sentinel you list, you can use this option to specify a password that will be used to authenticate diff --git a/test/redix/sentinel_test.exs b/test/redix/sentinel_test.exs index b2a085b..1cf6a91 100644 --- a/test/redix/sentinel_test.exs +++ b/test/redix/sentinel_test.exs @@ -77,6 +77,45 @@ defmodule Redix.SentinelTest do assert Redix.command!(pid, ["PING"]) == "PONG" end + test "sentinel supports password mfa in sentinels list", %{sentinel_config: sentinel_config} do + System.put_env("REDIX_SENTINEL_MFA_PASSWORD", "sentinel-password") + + password_mfa = {System, :get_env, ["REDIX_SENTINEL_MFA_PASSWORD"]} + + sentinel_config = + Keyword.merge(sentinel_config, + sentinels: [[host: "localhost", port: 26383, password: password_mfa]] + ) + + pid = + start_supervised!( + {Redix, sentinel: sentinel_config, password: "main-password", sync_connect: true} + ) + + assert Redix.command!(pid, ["PING"]) == "PONG" + after + System.delete_env("REDIX_SENTINEL_MFA_PASSWORD") + end + + test "sentinel supports global password mfa", %{sentinel_config: sentinel_config} do + System.put_env("REDIX_SENTINEL_MFA_PASSWORD", "sentinel-password") + + sentinel_config = + Keyword.merge(sentinel_config, + password: {System, :get_env, ["REDIX_SENTINEL_MFA_PASSWORD"]}, + sentinels: ["redis://localhost:26383"] + ) + + pid = + start_supervised!( + {Redix, sentinel: sentinel_config, password: "main-password", sync_connect: true} + ) + + assert Redix.command!(pid, ["PING"]) == "PONG" + after + System.delete_env("REDIX_SENTINEL_MFA_PASSWORD") + end + test "failed sentinel connection" do {test_name, _arity} = __ENV__.function diff --git a/test/redix/start_options_test.exs b/test/redix/start_options_test.exs index 84c8d31..4e6b016 100644 --- a/test/redix/start_options_test.exs +++ b/test/redix/start_options_test.exs @@ -102,6 +102,49 @@ defmodule Redix.StartOptionsTest do end end + test "sentinel password string" do + opts = + StartOptions.sanitize( + sentinel: [ + sentinels: [ + [host: "host1", port: 26379, password: "secret1"], + [host: "host2", port: 26379] + ], + group: "mygroup", + password: "secret2" + ] + ) + + sentinels = opts[:sentinel][:sentinels] + + assert Enum.count(sentinels) == 2 + assert Enum.find(sentinels, &(&1[:host] == 'host1'))[:password] == "secret1" + assert Enum.find(sentinels, &(&1[:host] == 'host2'))[:password] == "secret2" + end + + test "sentinel password mfa" do + mfa1 = {System, :fetch_env!, ["REDIS_PASS1"]} + mfa2 = {System, :fetch_env!, ["REDIS_PASS2"]} + + opts = + StartOptions.sanitize( + sentinel: [ + sentinels: [ + [host: "host1", port: 26379, password: mfa1], + [host: "host2", port: 26379] + ], + group: "mygroup", + password: mfa2 + ] + ) + + sentinels = opts[:sentinel][:sentinels] + + assert Enum.count(sentinels) == 2 + assert Enum.find(sentinels, &(&1[:host] == 'host1'))[:password] == mfa1 + assert Enum.find(sentinels, &(&1[:host] == 'host2'))[:password] == mfa2 + end + test "gen_statem options are allowed" do opts = StartOptions.sanitize(hibernate_after: 1000, debug: [], spawn_opt: [fullsweep_after: 0])