Current section

15 Versions

Jump to

Compare versions

9 files changed
+491 additions
-181 deletions
  @@ -5,6 +5,12 @@
5 5 {<<"elixir">>,<<"~> 1.11">>}.
6 6 {<<"files">>,
7 7 [<<"lib">>,<<"lib/secret_config">>,<<"lib/secret_config/cache">>,
8 + <<"lib/secret_config/cache/util.ex">>,
9 + <<"lib/secret_config/cache/string_interpolator.ex">>,
10 + <<"lib/secret_config/cache/config">>,
11 + <<"lib/secret_config/cache/config/local.ex">>,
12 + <<"lib/secret_config/cache/config/ssm.ex">>,
13 + <<"lib/secret_config/cache/config/loader.ex">>,
8 14 <<"lib/secret_config/cache/server.ex">>,
9 15 <<"lib/secret_config/application.ex">>,<<"lib/secret_config.ex">>,
10 16 <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>]}.
  @@ -47,4 +53,4 @@
47 53 {<<"optional">>,false},
48 54 {<<"repository">>,<<"hexpm">>},
49 55 {<<"requirement">>,<<"~> 4.0">>}]]}.
50 - {<<"version">>,<<"0.14.0">>}.
56 + {<<"version">>,<<"1.0.0">>}.
  @@ -9,7 +9,7 @@ defmodule SecretConfig do
9 9 Sets the env explicitly as this configuration item may not be able to be set
10 10 inside a releases.exs or runtime.exs if you perform ensure_all_started(:secret_config)
11 11 """
12 - @spec set_env(env :: binary) :: none()
12 + @spec set_env(env :: binary) :: :ok
13 13 def set_env(env) do
14 14 GenServer.cast(SecretConfig.Cache.Server, {:set_env, env})
15 15 end
  @@ -17,7 +17,7 @@ defmodule SecretConfig do
17 17 @doc """
18 18 Gets parameter from GenServer (returns default value if present)
19 19 """
20 - @spec fetch(key :: binary, default :: binary | nil) :: ExAws.Operation.JSON.t()
20 + @spec fetch(key :: binary, default :: binary | nil) :: binary | nil
21 21 def fetch(key, default) do
22 22 GenServer.call(SecretConfig.Cache.Server, {:fetch, key, default})
23 23 end
  @@ -25,18 +25,21 @@ defmodule SecretConfig do
25 25 @doc """
26 26 Gets parameter from GenServer (raise error if the value is not present)
27 27 """
28 - @spec fetch!(key :: binary) :: ExAws.Operation.JSON.t()
28 + @spec fetch!(key :: String.t()) :: String.t()
29 29 def fetch!(key) do
30 - case GenServer.call(SecretConfig.Cache.Server, {:fetch, key, :not_exist}) do
31 - :not_exist -> raise "SecretConfig key does not exist: #{inspect(key)}"
32 - val -> val
30 + case GenServer.call(SecretConfig.Cache.Server, {:fetch!, key, :not_exist}) do
31 + {:not_exist, full_key} ->
32 + raise "SecretConfig key does not exist: #{inspect(full_key)}"
33 +
34 + value ->
35 + value
33 36 end
34 37 end
35 38
36 39 @doc """
37 40 Checks for parameter to be present
38 41 """
39 - @spec key?(key :: binary) :: ExAws.Operation.JSON.t()
42 + @spec key?(key :: binary) :: boolean()
40 43 def key?(key) do
41 44 GenServer.call(SecretConfig.Cache.Server, {:key?, key})
42 45 end
  @@ -44,7 +47,7 @@ defmodule SecretConfig do
44 47 @doc """
45 48 Deletes parameter from the AWS Parameter Store, then it triggers a refresh of the GenServer state
46 49 """
47 - @spec delete(key :: binary) :: ExAws.Operation.JSON.t()
50 + @spec delete(key :: binary) :: {:deleted, binary} | {:not_exist, binary}
48 51 def delete(key) do
49 52 GenServer.call(SecretConfig.Cache.Server, {:delete, key})
50 53 end
  @@ -53,7 +56,7 @@ defmodule SecretConfig do
53 56 Adds parameter to the AWS Parameter Store, then it triggers a refresh of the GenServer state
54 57 """
55 58
56 - @spec push(key :: binary, value :: binary) :: ExAws.Operation.JSON.t()
59 + @spec push(key :: binary, value :: binary) :: {:added, binary} | {:error, binary}
57 60 def push(key, value) do
58 61 GenServer.call(SecretConfig.Cache.Server, {:push, key, value})
59 62 end
  @@ -61,7 +64,7 @@ defmodule SecretConfig do
61 64 @doc """
62 65 Triggers a refresh of the GenServer state by pulling the latest from the AWS Parameter Store
63 66 """
64 - @spec refresh() :: none()
67 + @spec refresh() :: :ok
65 68 def refresh() do
66 69 GenServer.cast(SecretConfig.Cache.Server, {:refresh})
67 70 end
  @@ -0,0 +1,56 @@
1 + defmodule Config.Loader do
2 + @moduledoc """
3 + Handles loading of configuration based on the environment setting.
4 +
5 + It supports loading configuration from a YAML string, a YAML file, or an SSM parameter store,
6 + depending on the application's environment settings.
7 + """
8 +
9 + @doc """
10 + Initializes the configuration state based on the provided environment.
11 +
12 + ## Parameters
13 + - env: The environment name as a string or `nil`.
14 +
15 + ## Returns
16 + - The loaded configuration as a map, or `nil` if the environment is not set.
17 + """
18 + @spec init_state(String.t() | nil) :: {:local, String.t(), map()} | nil
19 + def init_state(env) do
20 + case env do
21 + nil -> nil
22 + _ -> load_config(env)
23 + end
24 + end
25 +
26 + @doc """
27 + Loads configuration based on the environment setting.
28 +
29 + Attempts to load configuration from a YAML string, then from a file, and finally
30 + falls back to loading from the SSM parameter store if the previous methods are not configured.
31 +
32 + ## Parameters
33 + - env: The environment name as a string.
34 +
35 + ## Returns
36 + - The loaded configuration as a map, wrapped in a tuple with `:local` and the environment,
37 + or directly from the SSM parameter store.
38 + """
39 + @spec load_config(String.t()) :: {:local, String.t(), map()} | any()
40 + def load_config(env) do
41 + cond do
42 + yaml_str = Application.get_env(:secret_config, :yaml_str) ->
43 + Config.Local.parse_yaml(yaml_str, env)
44 +
45 + file = Application.get_env(:secret_config, :file) ->
46 + yaml_str = File.read!(file)
47 + local_map = Util.yaml_str_to_map(yaml_str)
48 + |> Util.apply_local_imports
49 + |> StringInterpolator.interpolate_env()
50 + {:local, env, local_map}
51 +
52 + true ->
53 + Config.SSM.load_ssm_config(env)
54 + end
55 + end
56 + end
  @@ -0,0 +1,47 @@
1 + defmodule Config.Local do
2 + @moduledoc """
3 + Handles parsing of local YAML configurations, providing functionality to load configurations
4 + from YAML strings or files, applying environment-specific interpolations and imports.
5 + """
6 +
7 + @doc """
8 + Parses a YAML string into a configuration state, applying environment variable interpolation.
9 +
10 + ## Parameters
11 + - yaml_str: The YAML string to be parsed.
12 + - env: The environment context used for interpolation.
13 +
14 + ## Returns
15 + - A tuple containing `:local`, the environment, and the parsed state as a map.
16 + """
17 + @spec parse_yaml(String.t(), String.t()) :: {:local, String.t(), map()}
18 + def parse_yaml(yaml_str, env) do
19 + state = yaml_str
20 + |> Util.yaml_str_to_map()
21 + |> StringInterpolator.interpolate_env()
22 +
23 + {:local, env, state}
24 + end
25 +
26 + @doc """
27 + Reads and parses a YAML file into a configuration state, applying local imports
28 + and environment variable interpolation.
29 +
30 + ## Parameters
31 + - file: The path to the YAML file to be read and parsed.
32 + - env: The environment context used for interpolation and imports.
33 +
34 + ## Returns
35 + - A tuple containing `:local`, the environment, and the parsed state as a map.
36 + """
37 + @spec parse_file(String.t(), String.t()) :: {:local, String.t(), map()}
38 + def parse_file(file, env) do
39 + state = file
40 + |> File.read!()
41 + |> Util.yaml_str_to_map()
42 + |> Util.apply_local_imports()
43 + |> StringInterpolator.interpolate_env()
44 +
45 + {:local, env, state}
46 + end
47 + end
\ No newline at end of file
  @@ -0,0 +1,27 @@
1 + defmodule Config.SSM do
2 + @moduledoc """
3 + Provides functionality to load configuration settings from AWS SSM Parameter Store
4 + based on the provided environment.
5 + """
6 +
7 + @doc """
8 + Loads configuration from the AWS SSM Parameter Store for the specified environment.
9 +
10 + Utilizes utility functions to fetch parameters, apply imports, and interpolate
11 + environment variables within the parameters.
12 +
13 + ## Parameters
14 + - env: The environment name as a string which scopes the SSM parameter lookup.
15 +
16 + ## Returns
17 + - A tuple with `:ssm`, the environment name, and the configuration map.
18 + """
19 + @spec load_ssm_config(String.t()) :: {:ssm, String.t(), map()}
20 + def load_ssm_config(env) do
21 + ssm_map = Util.ssm_parameter_map(%{}, nil, true, env)
22 + |> Util.apply_imports(env)
23 + |> StringInterpolator.interpolate_env()
24 +
25 + {:ssm, env, ssm_map}
26 + end
27 + end
Loading more files…