Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Confex | 283 | 77 | 43 | 3 years ago | 24 | October 28, 2020 | 5 | mit | Elixir | |
Useful helper to read and use application configuration from environment variables. | ||||||||||
Hubot Lets Chat | 56 | 7 | 3 | 8 years ago | 6 | April 14, 2015 | 3 | CoffeeScript | ||
Hubot Adapter for Let's Chat | ||||||||||
Hubot Skype Web | 46 | 2 | 7 years ago | 30 | November 03, 2016 | 7 | mit | CoffeeScript | ||
A Skype adapter for Hubot that connects via Skype web. | ||||||||||
Exenv | 34 | 1 | 1 | 3 years ago | 7 | July 10, 2019 | mit | Elixir | ||
Exenv makes loading environment variables from external sources easy. | ||||||||||
Parse Server Gcs Adapter | 28 | 91 | 10 | 3 months ago | 4 | April 04, 2017 | 1 | JavaScript | ||
parse-server adapter for Google Cloud Storage | ||||||||||
Hubot Kandan | 21 | 8 years ago | 10 | mit | CoffeeScript | |||||
Kandan adapter for GitHub's Hubot | ||||||||||
Voltha Openolt Adapter | 12 | 18 days ago | 24 | October 07, 2019 | Go | |||||
OpenOLT Adapter for VOLTHA | ||||||||||
Caddy Yaml | 10 | 2 years ago | 1 | June 07, 2020 | 1 | apache-2.0 | Go | |||
Alternative Caddy YAML config adapter with extra features | ||||||||||
Voltha Openonu Adapter Go | 10 | a month ago | 73 | April 25, 2022 | Go | |||||
OpenONU Adapter written in GO for VOLTHA | ||||||||||
Param_store | 8 | 3 years ago | 1 | mit | Ruby | |||||
Easy switch in between ENV, AWS Parameter Store, AWS Secrets Manager and EJSON |
Confex simplifies reading configuration at run-time with adapter-based system for fetch values from any source.
It's inspired by Phoenix {:system, value}
definition for HTTP port and have no external dependencies.
It's available on hex.pm and can be installed as project dependency:
Add confex
to your list of dependencies in mix.exs
:
def deps do
[{:confex, "~> 3.5.0"}]
end
Ensure confex
is started before your application either by adding it to applications
list as shown below or by making sure you use extra_applications
option instead of applications
(this feature is available since Elixir 1.4 and enabled by default for new projects):
def application do
[applications: [:confex]]
end
Replace values with configuration tuples
Define configuration in your config.exs
:
config :my_app, MyApp.MyQueue,
queue: [
name: {:system, "OUT_QUEUE_NAME", "MyQueueOut"},
error_name: {:system, "OUT_ERROR_QUEUE_NAME", "MyQueueOut.Errors"},
routing_key: {:system, "OUT_ROUTING_KEY", ""},
durable: {:system, "OUT_DURABLE", false},
port: {:system, :integer, "OUT_PORT", 1234},
]
Configuration tuples examples:
var
- any bare values will be left as-is.{:system, "ENV_NAME", "default"}
- read string from system environment or fallback to "default"
if it is not set.{:system, "ENV_NAME"}
- same as above, but raise error if ENV_NAME
is not set.Additionally you can cast string values to common types:
{:system, :string, "ENV_NAME", "default"}
(string is a default type).{:system, :string, "ENV_NAME"}
.{:system, :integer, "ENV_NAME", 123}
.{:system, :integer, "ENV_NAME"}
.{:system, :float, "ENV_NAME", 123.5}
.{:system, :float, "ENV_NAME"}
.{:system, :boolean, "ENV_NAME", true}
.{:system, :boolean, "ENV_NAME"}
.{:system, :atom, "ENV_NAME"}
.{:system, :atom, "ENV_NAME", :default}
.{:system, :module, "ENV_NAME"}
.{:system, :module, "ENV_NAME", MyDefault}
.{:system, :list, "ENV_NAME"}
.{:system, :list, "ENV_NAME", ["a", "b", "c"]}
.{:system, :charlist, "ENV_NAME"}
.{:system, :charlist, "ENV_NAME", 'default'}
.:system
can be replaced with a {:via, adapter}
tuple, where adapter is a module that implements Confex.Adapter
behaviour.
Type can be replaced with {module, function, arguments}
tuple, in this case Confex will use external function to
resolve the type. Function must returns either {:ok, value}
or {:error, reason :: String.t}
tuple.
Read configuration by replacing Application.fetch_env/2
, Application.fetch_env!/2
and Application.get_env/3
calls with Confex
functions
Fetch string values:
iex> Confex.fetch_env(:myapp, MyKey)
{:ok, "abc"}
Fetch integer values:
iex> Confex.fetch_env(:myapp, MyIntKey)
{:ok, 123}
Fetch configuration from maps or keywords:
iex> Confex.fetch_env(:myapp, MyIntKey)
{:ok, [a: 123, b: "abc"]}
Ecto.Repo
has a init/2
callback, you can use it with Confex to read environment variables. We used to have all our repos to look like this:
defmodule MyApp do
use Ecto.Repo, otp_app: :my_app
@doc """
Dynamically loads the repository configuration from the environment variables.
"""
def init(_, config) do
url = System.get_env("DATABASE_URL")
config = if url, do: [url: url] ++ config, else: Confex.Resolver.resolve!(config)
unless config[:database] do
raise "Set DB_NAME environment variable!"
end
{:ok, config}
end
end
Same for Phoenix, use init/2
callback of Phoenix.Endpoint
:
defmodule MyApp.Web.Endpoint do
# Some code here
@doc """
Dynamically loads configuration from the system environment
on startup.
It receives the endpoint configuration from the config files
and must return the updated configuration.
"""
def init(_type, config) do
{:ok, config} = Confex.Resolver.resolve(config)
unless config[:secret_key_base] do
raise "Set SECRET_KEY environment variable!"
end
{:ok, config}
end
end
In case you want to keep using Application.get_env/2
and other methods to keep accessing configuration,
you can resolve it one-time when application is started:
defmodule MyApp do
use Application
def start(_type, _args) do
# Replace Application environment with resolved values
Confex.resolve_env!(:my_app)
# ...
end
end
However, don't drink too much Kool-Aid. Direct calls to the Confex are more explicit and should be default way to go, you don't want your colleagues to waste their time finding out how that resolved value got into the configuration, right?
Confex is supplied with helper macros that allow to attach configuration to specific modules of your application.
defmodule Connection do
use Confex, otp_app: :myapp
end
It will add config/0
function to Connection
module that reads configuration at run-time for :myapp
OTP application with key Connection
.
You can add defaults by extending macro options:
defmodule Connection do
use Confex,
otp_app: :myapp,
some_value: {:system, "ENV_NAME", "this_will_be_default value"}
end
If application environment contains values in Keyword
or Map
structs, default values will be recursively merged with application configuration.
We recommend to avoid using tuples without default values in this case, since config/0
calls will raise exceptions if they are not resolved.
You can validate configuration by overriding validate_config!/1
function, which will receive configuration and must return it back to caller function. It will be evaluated each time config/1
is called.
defmodule Connection do
use Confex, otp_app: :myapp
def validate_config!(config) do
unless config[:password] do
raise "Password is not set!"
end
config
end
end
Currently Confex supports two embedded adapters:
:system
- read configuration from system environment;:system_file
- read file path from system environment and read configuration from this file. Useful when you want to resolve Docker, Swarm or Kubernetes secrets that are stored in files.You can create adapter by implementing Confex.Adapter
behaviour with your own logic.