confex v3.5.0 Confex

Confex simplifies reading configuration at run-time with adapter-based system for resolvers.

Configuration tuples

Whenever there is a configuration that should be resolved at run-time you need to replace its value in config.exs by Confex configuration type. Common structure:

  @type fetch_statement :: {adapter :: atom() | module(), value_type :: value_type, key :: any(), default :: any()}
                         | {value_type :: value_type, key :: any()}
                         | {key :: any(), default :: any()}
                         | {key :: any()}

If value_type is set, Confex will automatically cast its value. Otherwise, default type of :string is used.

Confex TypeElixir TypeDescription
:stringString.tDefault.
:integerInteger.tParse Integer value in string.
:floatFloat.tParse Float value in string.
:booleantrue or falseCast 'true', '1', 'yes' to true; 'false', '0', 'no' to false.
:atomatom()Cast string to atom.
:modulemodule()Cast string to module name.
:listList.tCast comma-separated string (1,2,3) to list ([1, 2, 3]).
:charlistcharlist()Cast string to charlist.

Custom type casting

You can use your own casting function by replacing type with {module, function, arguments} tuple, Confex will call that function with apply(module, function, [value] ++ arguments).

This function returns either {:ok, value} or {:error, reason :: String.t} tuple.

Adapters

  • :system - read configuration from system environment;
  • :system_file - read file path from system environment and read configuration from this file.

You can create adapter by implementing Confex.Adapter behaviour with your own logic.

Examples

  • var - any bare values will be left as-is;
  • {:system, "ENV_NAME", default} - read string from "ENV_NAME" environment variable or return default if it's not set or has empty value;
  • {:system, "ENV_NAME"} - same as above, with default value nil;
  • {:system, :integer, "ENV_NAME", default} - read string from "ENV_NAME" environment variable and cast it to integer or return default if it's not set or has empty value;
  • {:system, :integer, "ENV_NAME"} - same as {:system, :integer, "ENV_NAME", nil};
  • {{:via, MyAdapter}, :string, "ENV_NAME", default} - read value by key "ENV_NAME" via adapter MyAdapter or return default if it's not set or has empty value;
  • {{:via, MyAdapter}, :string, "ENV_NAME"} - same as above, with default value nil;
  • {:system, {MyApp.MyType, :cast, [:foo]}, "ENV_NAME"} - MyApp.MyType.cast(value, :foo) call would be made to resolve environment variable value.

Link to this section Summary

Functions

Returns the value for key in app’s environment in a tuple. This function mimics Application.fetch_env/2 function

Returns the value for key in app’s environment. This function mimics Application.fetch_env!/2 function

Returns the value for key in app’s environment. This function mimics Application.get_env/2 function

Recursively merges configuration with default values

Reads all key-value pairs from an application environment and replaces them with resolved values

Link to this section Types

Link to this type

configuration_tuple()
configuration_tuple() ::
  {value_type :: Confex.Type.t(), key :: any(), default :: any()}
  | {value_type :: Confex.Type.t(), key :: any()}
  | {key :: any(), default :: any()}
  | {key :: any()}

Link to this section Functions

Link to this function

fetch_env(app, key)
fetch_env(app :: app(), key :: key()) :: {:ok, value()} | :error

Returns the value for key in app’s environment in a tuple. This function mimics Application.fetch_env/2 function.

If the configuration parameter does not exist or can not be parsed, the function returns :error.

Example

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, "MY_TEST_ENV"})
...> {:ok, "foo"} = Elixir.Confex.fetch_env(:myapp, :test_var)
{:ok, "foo"}

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV", "bar"})
...> {:ok, "bar"} = Elixir.Confex.fetch_env(:myapp, :test_var)
{:ok, "bar"}

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> :error = Elixir.Confex.fetch_env(:myapp, :test_var)
:error

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> :error = Elixir.Confex.fetch_env(:myapp, :test_var)
:error

iex> Application.put_env(:myapp, :test_var, 1)
...> {:ok, 1} = Elixir.Confex.fetch_env(:myapp, :test_var)
{:ok, 1}
Link to this function

fetch_env!(app, key)
fetch_env!(app :: app(), key :: key()) :: value() | no_return()

Returns the value for key in app’s environment. This function mimics Application.fetch_env!/2 function.

If the configuration parameter does not exist or can not be parsed, raises ArgumentError.

Example

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, "MY_TEST_ENV"})
...> "foo" = Elixir.Confex.fetch_env!(:myapp, :test_var)
"foo"

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV", "bar"})
...> "bar" = Elixir.Confex.fetch_env!(:myapp, :test_var)
"bar"

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> Elixir.Confex.fetch_env!(:myapp, :test_var)
** (ArgumentError) can't fetch value for key `:test_var` of application `:myapp`, can not resolve key MY_TEST_ENV value via adapter Elixir.Confex.Adapters.SystemEnvironment

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> Elixir.Confex.fetch_env!(:myapp, :test_var)
** (ArgumentError) can't fetch value for key `:test_var` of application `:myapp`, can not cast "foo" to Integer

iex> Application.put_env(:myapp, :test_var, 1)
...> 1 = Elixir.Confex.fetch_env!(:myapp, :test_var)
1
Link to this function

get_env(app, key, default \\ nil)
get_env(app :: app(), key :: key(), default :: value()) :: value()

Returns the value for key in app’s environment. This function mimics Application.get_env/2 function.

If the configuration parameter does not exist or can not be parsed, returns default value or nil.

Example

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, "MY_TEST_ENV"})
...> "foo" = Elixir.Confex.get_env(:myapp, :test_var)
"foo"

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV", "bar"})
...> "bar" = Elixir.Confex.get_env(:myapp, :test_var)
"bar"

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> nil = Elixir.Confex.get_env(:myapp, :test_var)
nil

iex> :ok = System.delete_env("MY_TEST_ENV")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> "baz" = Elixir.Confex.get_env(:myapp, :test_var, "baz")
"baz"

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> nil = Elixir.Confex.get_env(:myapp, :test_var)
nil

iex> nil = Elixir.Confex.get_env(:myapp, :does_not_exist)
nil

iex> Application.put_env(:myapp, :test_var, 1)
...> 1 = Elixir.Confex.get_env(:myapp, :test_var)
1
Link to this function

merge_configs!(config, defaults)
merge_configs!(config :: Keyword.t() | map(), defaults :: Keyword.t() | map()) ::
  Keyword.t() | map()

Recursively merges configuration with default values.

Both values must be either in Keyword or Map structures, otherwise ArgumentError is raised.

Example

iex> [b: 3, a: 1] = Elixir.Confex.merge_configs!([a: 1], [a: 2, b: 3])
[b: 3, a: 1]

iex> %{a: 1, b: 3} = Elixir.Confex.merge_configs!(%{a: 1}, %{a: 2, b: 3})
%{a: 1, b: 3}

iex> Elixir.Confex.merge_configs!(%{a: 1}, [b: 2])
** (ArgumentError) can not merge default values [b: 2] with configuration %{a: 1} because their types mismatch, expected both to be either Map or Keyword structures
Link to this function

resolve_env!(app, opts \\ [])
resolve_env!(app :: app(), opts :: Keyword.t()) ::
  [{key(), value()}] | no_return()

Reads all key-value pairs from an application environment and replaces them with resolved values.

Example

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, "MY_TEST_ENV"})
...> Confex.resolve_env!(:myapp)
...> "foo" = Application.get_env(:myapp, :test_var)
"foo"

iex> :ok = System.put_env("MY_TEST_ENV", "foo")
...> Application.put_env(:myapp, :test_var, {:system, :integer, "MY_TEST_ENV"})
...> Confex.resolve_env!(:myapp)
** (ArgumentError) can't fetch value for key `:test_var` of application `:myapp`, can not cast "foo" to Integer

The optional opts argument is passed through to the internal call to Application.put_env/4 and may be used to set the timeout and/or persistent parameters.

Warning! Do not use this function if you want to change your environment while VM is running. All {:system, _} tuples would be replaced with actual values.