Using Aumbry¶
Dependencies¶
Many developers are very conscious of the number of dependencies that they include in their projects. To that end, Aumbry doesn’t install the dependencies for parsing yaml or loading from consul by default. However, Aumbry attempts to make this relatively easy on users by enabling users to easily install the extra dependencies using the following convention:
# For Consul dependencies
pip install aumbry['consul']
# For Etcd2 dependencies
pip install aumbry['etcd2']
# For Yaml dependencies
pip install aumbry['yaml']
# For Parameter Store dependencies
pip install aumbry['param_store']
# For Fernet File dependencies
pip install aumbry['fernet']
# Installing multiple dependencies
pip install aumbry['etcd2','yaml']
Loading from a File¶
One of the simplest and most common way of loading configuration is from a file. For this example, we’ll use a JSON configuration file.
Lets say we have the following JSON configuration that we want to load
{
"something": "it works!"
}
The next steps are to define a configuration class that matches what we’re trying to do and load the config up.
import aumbry
class SampleConfig(aumbry.JsonConfig):
__mapping__ = {
'something': aumbry.Attr('something', str),
}
# You can either specify the options here or via environment variables
options = {
'CONFIG_FILE_PATH': './my_config.json',
}
# Time to load it up!
config = aumbry.load(aumbry.FILE, SampleConfig, options)
print(config.something) # it works!
File Options¶
Like all options, these can be manually specified when calling load()
or via environment variables.
Key | Default | Notes |
---|---|---|
CONFIG_FILE_PATH | Required |
Encryption¶
Encryption and decryption support is provided by using pyca/cryptography’s Fernet module. Installing the required dependencies can be done with:
pip install aumbry['fernet']
The usage is nearly identical to a standard file; however, the source type
and options change slightly. The source type becomes aumbry.FERNET
and
you need to provide the CONFIG_FILE_FERNET_KEY
option.
Loading from Consul¶
As mentioned under the Dependencies section, the dependencies to load from consul are not included by default. As a result, we need to first install our extra dependencies.
pip install aumbry['consul']
Much like our loading from a file example, we need a configuration class and set our options for the Consul source.
import aumbry
class SampleConfig(aumbry.JsonConfig):
__mapping__ = {
'something': aumbry.Attr('something', str),
}
# You can either specify the options here or via environment variables
options = {
'CONSUL_URI': 'http://myhost:8500',
'CONSUL_KEY': 'test',
}
# Time to load it up!
config = aumbry.load(aumbry.CONSUL, SampleConfig, options)
print(config.something) # it works!
It is important to note that the Consul source will block until it either cannot load, reaches max retries, or successfully loads.
Consul Options¶
Like all options, these can be manually specified when calling load()
or via environment variables.
Key | Default | Notes |
---|---|---|
CONSUL_URI | Required | |
CONSUL_KEY | Required | |
CONSUL_TIMEOUT | 10 | Timeout per-request |
CONSUL_RETRY_MAX | 1 | Number of retries to attempt |
CONSUL_RETRY_INTERVAL | 10 | Wait period between retries |
Loading from Etcd2¶
As mentioned under the Dependencies section, the dependencies to load from etcd2 are not included by default. As a result, we need to first install our extra dependencies.
pip install aumbry['etcd2']
Much like our loading from a file example, we need a configuration class and set our options for the Etcd2 source.
import aumbry
class SampleConfig(aumbry.JsonConfig):
__mapping__ = {
'something': aumbry.Attr('something', str),
}
# You can either specify the options here or via environment variables
options = {
'ETCD2_URI': 'http://myhost:8500',
'ETCD2_KEY': 'test',
}
# Time to load it up!
config = aumbry.load(aumbry.ETCD2, SampleConfig, options)
print(config.something) # it works!
It is important to note that the Etcd2 source will block until it either cannot load, reaches max retries, or successfully loads.
Etcd2 Options¶
Like all options, these can be manually specified when calling load()
or via environment variables.
Key | Default | Notes |
---|---|---|
ETCD2_URI | Required | |
ETCD2_KEY | Required | |
ETCD2_TIMEOUT | 10 | Timeout per-request |
ETCD2_RETRY_MAX | 1 | Number of retries to attempt |
ETCD2_RETRY_INTERVAL | 10 | Wait period between retries |
Loading from AWS Parameter Store¶
As mentioned under the Dependencies section, the dependencies to load from the parameter store are not included by default. As a result, we need to first install our extra dependencies.
pip install aumbry['param_store']
To use the parameter store functionality, we need to use the generic
configuration class or force the usage of the generic handler on load()
and save()
.
import aumbry
class SampleConfig(aumbry.GenericConfig):
__mapping__ = {
'something': aumbry.Attr('something', str),
}
# You can either specify the options here or via environment variables
options = {
'PARAMETER_STORE_AWS_REGION': 'us-west-2',
'PARAMETER_STORE_PREFIX': '/prod/my_app',
}
# Time to load it up!
config = aumbry.load(aumbry.PARAM_STORE, SampleConfig, options)
print(config.something) # it works!
Note
If you need to mix configuration types, such as using a YamlConfig
,
you’ll need to tell Aumbry to attempt to coerce the configuration using
the aumbry.formats.generic.GenericHandler
when calling
aumbry.load()
and aumbry.save()
.
Parameter Store Options¶
Like all options, these can be manually specified when calling load()
or via environment variables.
Key | Default | Notes |
---|---|---|
PARAMETER_STORE_AWS_REGION | Required | |
PARAMETER_STORE_PREFIX | Required | |
PARAMETER_STORE_AWS_ACCESS_ID | If empty, the default machine credentials are used | |
PARAMETER_STORE_AWS_ACCESS_SECRET | If empty, the default machine credentials are used | |
PARAMETER_STORE_AWS_SESSION_TOKEN | If empty, the default machine credentials are used | |
PARAMETER_STORE_AWS_KMS_KEY_ID | Account Default |
Building Configuration Models¶
Because Aumbry uses Alchemize for model de/serialization, it’s just a matter of defining out the models in the Alchemize method.
Example Yaml Configuration
---
base-uri: http://localhost
database:
servers:
- localhost:5432
username: postgres
password: something
name: app
Example Code Load and Parse that config
import aumbry
from aumbry import Attr
class DatabaseConfig(aumbry.YamlConfig):
__mapping__ = {
'servers': Attr('servers', list),
'username': Attr('username', str),
'password': Attr('password', str),
'database': Attr('database', str),
}
class AppConfig(aumbry.YamlConfig):
__mapping__ = {
'base-uri': Attr('base_uri', str),
'database': Attr('database', DatabaseConfig),
}
cfg = aumbry.load(
aumbry.FILE,
AppConfig,
{
'CONFIG_FILE_PATH': '/etc/app/config.yml'
}
)
print(cfg.database.username) # postgres
One of the things you might have noticed is that the explicit mapping allows
for us to take an attribute name such as base-uri
which isn’t compatible
with Python, and map it over to base_uri
.
More details can be found on building your mappings in the Alchemize documentation.