skogsra v1.0.1 Skogsra View Source
The Skogsrå was a mythical creature of the forest that appears in the form of a small, beautiful woman with a seemingly friendly temperament. However, those who are enticed into following her into the forest are never seen again.
This library attempts to improve the use of OS environment variables for application configuration:
- Automatic type casting of values.
- Configuration options documentation.
- Variables defaults.
Small Example
You would create a settings module e.g:
defmodule MyApp.Settings do
use Skogsra
app_env :my_hostname, :myapp, :hostname,
default: "localhost"
end
Calling MyApp.Settings.my_hostname()
will retrieve the value for the
hostname in the following order:
- From the OS environment variable
$MYAPP_HOSTNAME
. - From the configuration file e.g:
config :myapp,
hostname: "my.custom.host"
- From the default value if it exists (In this case, it would return
"localhost"
).
Handling different environments
If it’s necessary to keep several environments, it’s possible to use a
namespace
e.g:
Calling MyApp.Settings.my_hostname(Test)
will retrieve the value for the
hostname in the following order:
- From the OS environment variable
$TEST_MYAPP_HOSTNAME
. - From the configuration file e.g:
config :myapp, Test,
hostname: "my.custom.test.host"
- From the default value if it exists.
Required variables
It is possible to set a environment variable as required with the required
option e.g:
defmodule MyApp.Settings do
use Skogsra
app_env :my_hostname, :myapp, :port,
required: true
end
If the variable $MYAPP_PORT
is undefined and the configuration is missing,
calling to MyApp.Settings.my_hostname()
will return an error tuple. Calling
$MyApp.Settings.my_hostname!()
(with the bang) will raise a runtime
exception.
Automatic casting
If the default value is set, the OS environment variable value will be casted
as the same type of the default value. Otherwise, it is possible to set the
type for the variable with the option type
. The available types are
:binary
(default), :integer
, :float
, :boolean
and :atom
.
Additionally, you can create a function to cast the value and specify it as
{module_name, function_name}
e.g:
defmodule MyApp.Settings do
use Skogsra
app_env :my_channels, :myapp, :channels,
type: {__MODULE__, channels},
required: true
def channels(value), do: String.split(value, ", ")
end
If $MYAPP_CHANNELS
’s value is "ch0, ch1, ch2"
then the casted value
will be ["ch0", "ch1", "ch2"]
.
Configuration definitions
Calling MyApp.Settings.my_hostname(nil, :system)
will print the expected OS
environment variable name and MyApp.Settings.my_hostname(nil, :config)
will
print the expected Mix
configuration. If the namespace
is necessary, pass
it as first parameter.
Reloading
For debugging purposes is possible to reload variables at runtime with
MyApp.Settings.my_hostname(nil, :reload)
.
Recommended Usage
The recommended way of using this project is to define a .env
file in the
root of your project with the variables that you want to define e.g:
export MYSERVICE_PORT=1234
and then when source
ing the file right before you execute your application.
In bash
(or zsh
) would be like this:
$ source .env
The previous step can be automated by adding the following code to your
~/.bashrc
(or ~/.zshrc
):
#################
# BEGIN: Auto env
export LAST_ENV=
function auto_env_on_chpwd() {
env_type="$1"
env_file="$PWD/.env"
if [ -n "$env_type" ]
then
env_file="$PWD/.env.$env_type"
if [ ! -r "$env_file" ]
then
echo -e "[33mFile $env_file does not exist.[0m"
env_file="$PWD/.env"
fi
fi
if [ -n "$LAST_ENV" ] && [ -r "$LAST_ENV" ]
then
UNSET=$(
cat $LAST_ENV |
sed -e 's/^export ([0-9a-zA-Z_]*)=.*$/unset 1/'
)
source <(echo "$UNSET")
echo -e "[33mUnloaded ENV VARS defined in "$LAST_ENV"[0m"
export LAST_ENV=
fi
if [ -r "$env_file" ]
then
export LAST_ENV="$env_file"
source $LAST_ENV
echo -e "[32mLoaded "$LAST_ENV"[0m"
fi
}
chpwd_functions=(${chpwd_functions[@]} "auto_env_on_chpwd")
if [ -n "$TMUX" ]
then
auto_env_on_chpwd
fi
alias change_to='function _change_to() {auto_env_on_chpwd $1}; _change_to'
# END: Auto env
###############
The previous code will attempt to source
any .env
file every time you
change directory e.g:
/home/alex $ cd my_app
Loaded "/home/alex/my_app/.env"
/home/alex/my_app $ echo "$MYSERVICE_PORT"
1234
Additionally, the command change_to <ENV>
is included. To keep your prod
,
dev
and test
environment variables separated, just create a
.env.${MIX_ENV}
in the root directory of your project. And when you want to
use the variables set in one of those files, just run the following:
$ change_to dev # Will use `.env.dev` instead of `.env`
Link to this section Summary
Functions
For now is just equivalent to use import Skogsra
Creates a function to retrieve specific environment/application variables values
Link to this section Types
Skogsra environment variable.
Link to this section Functions
For now is just equivalent to use import Skogsra
.
Creates a function to retrieve specific environment/application variables values.
The function created is named function_name
and will get the value
associated with an application called app_name
and one or several
parameters
keys. Optionally, receives a list of options
.
Options:
default
- Default value for the variable in case is not present.type
- Type of the variable. Used for casting the value. By default, casts the value to the same type of the default value. If the default value is not present, defaults to:binary
. The available values are::binary
,:integer
,:float
, :boolean,:atom
. Additionally, you can provide{module, function}
for custom types. The function must receive the binary and return the custom type.os_env
- Alias for the variable in the OS. If the alias isnil
will use the default name. This option is ignoredif the optionskip_system
istrue
(default isfalse
).namespace
- Namespace of the variable.skip_system
- Iftrue
, doesn’t look for the variable value in the system. Defaults tofalse
.skip_config
- Iftrue
, doesn’t look for the variable value in the configuration. Defaults tofalse
.required
- Errors when the value isnil
. Defaults tofalse
.cached
- Caches the value on the first read. Defaults totrue
.
e.g:
For the following declaration:
app_env :db_password, :myapp, [:mydb, :password],
default: "password",
It will generate the functions db_password/0
and db_password/1
. The
optional parameter is useful to specify namespaces.
A call to db_password/0
will try to:
- Look for the value of
$MYAPP_MYDB_PASSWORD
OS environment variable. If it’snil
, then it will try 2. - Look for the value in the configuration e.g:
config :myapp,
mydb: [password: "some password"]
If it’s nil
, then it will try 3.
- Return the value of the default value or
nil
.
A call to db_password/1
with namespace Test
will try to:
- Look for the value of
$TEST_MYAPP_MYDB_PASSWORD
OS environment variable. If it’snil
, then it will try 2. - Look for the value in the configuration e.g:
config :myapp, Test,
mydb: [password: "some password"]
If it’s nil
, then it will try 3.
- Return the value of the default value or
nil
.