unified-cfg
allows unified management of different configuration
files. It is possible to decline the configuration in different
variants (DEV, OPER, ...), and to locally overload a default
configuration.
The API allows accessing each configuration key individually, or using the configuration to complete jinja-like templates.
Each configuration file is an .ini
file, this venerable format being
by its simplicity well suited to the administrators of an instance.
The different variants are indicated in square brackets at the end of the key name.
[group]
key1[DEV] = value for dev env
key1[OPER] = value for oper env
The keys are searched in the different folders defined by the
CONFIG_PATH
variable. The value returned is that of the first folder
to resolve the key according to the CONFIG_NAME
variant.
Suppose 2 folders /default
and /local
containing a file
my_app.ini
.
# /default/my_app.ini
[group]
key1 = default value 1
key1[OPER] = default oper key1 value
key2 = default value 2
key2[OPER] = default oper key2 value
# /local/my_app.ini
[group]
key2[OPER_NODE1] = local node1 value
Assuming:
CONFIG_PATH=/local:/default
CONFIG_NAME=OPER_NODE1
We have:
$ cfg get my_app.group.key1
default oper key1 value
$ cfg get my_app.group.key2
local node1 value
cfg get [key]
: Return the value of a keycfg render [template]
: Formats the template with configuration values using jinja2 syntax.cfg doc [key]
: Shows the documentation of the key as well as its various value overloads.
Consider a web server with plugins providing optional services. In the configuration of nginx, we need to declare backends for each plugin and map URLs to those backends.
-
Main application, installed in
/path/to/application
:# /path/to/application/config/application.ini [nginx] port = 8080 # ...
-
First plugin, installed in
/path/to/first/plugin
:# /path/to/first/plugin/config/plugins/first_plugin.ini [main] enabled = true name = my_first_plugin [nginx] socket = /var/first_plugin.sock urls = ^/
-
Maybe other plugins are installed in their own directory.
-
The manager of a local instance overrides the configuration in a separate directory:
# /path/to/local/config/plugins/first_plugin.ini [main] # To deactivate this plugin on this instance enabled = false
-
And the nginx configuration
http { listen {{settings.application.nginx.port}}; {% for plugin in settings.plugins %} {% if plugin.main.enabled %} upstream {{plugin.main.name}} { server unix:{{plugin.nginx.socket}}; } {% endif %} {% endfor %} server { {% for plugin in settings.plugins %} {% if plugin.main.enabled %} {% for url in plugin.nginx.urls.split() %} location ~ {{url}} { proxy_pass http://{{plugin.main.name}}; } {% endfor %} {% endif %} {% endfor %} } }
We can render the nginx configuration with:
cfg -p /path/to/local/config -p /path/to/first/plugin/config \
-p /path/to/application/config render nginx.conf
Or:
export CONFIG_PATH=/path/to/local/config:/path/to/first/plugin/config:/path/to/application/config
cfg render nginx.conf
It is possible to call system commands an insert stdout in templates:
{{shell("commande")}}
It is allowed to write
# first.ini
[main]
key1 = value
# second.ini
[main]
key1 = {{settings.first.main.key1}}
key2 = {{settings.second.main.key1}}
unified-cfg is under LGPL-3.0-or-later.
unified-cfg embded various third-parties softwares:
- Jinja2CPP: Mozilla Public License Version 2.0
- fmt: MIT License
- CLI11: BSD-3-Clause
- subprocess: MIT License
- expected-lite: BSL-1.0
- optional-lite: BSL-1.0
- string-view-lite: BSL-1.0
- variant-lite: BSL-1.0
- rapidjson: MIT License