Golang Configuration Made Easy With Flæg And Stært
There are many ways to provide a configuration to a program. Some use Command Line Interfaces, others use configuration files. Any setting changes can require a refactor on many lines of code. The configuration loading process have to be very robust. If not, programs could not work as we expected. Unfortunately golang programs are no exception. For instance, adding a new argument in a CLI requires to create a flag, to parse data, to deal with the help section, to manage default values and to affect the collected value into the configuration structure.
Close your eyes and imagine a library able to automatically manage all this configuration process for you. You can open them because we did it :)
Flæg
Flæg is a Go package for building dynamically a powerful modern Command Line Interface and loading a program configuration structure from arguments. Go developers don’t need to worry about keeping flags and commands updated anymore : it works by itself !
Flæg package was born from the need of Træfik, the famous reverse proxy created by Emile Vauge. It was more and more difficult to maintain the list of `flags`: parameters passed in argument which drive the program.
Thanks to Flæg, the maintenance became a thing of the past. The `flags` are auto generated from the field names of the configuration structure. To do that, developers just have to add a StructTag following the field to create a flag on it. The helper (i.e. what is displayed with -help argument) is generated from the key `description` in the StructTag
Here an example of a complex configuration with StructTag that Flæg can process:
Flæg is able to load the argument values given in the configuration structure through reflection. The package supports most of field types, but no collections. Hopefully users can add a custom parser on specific types as collections or even whole structures.
Let’s see how simple it is to use Flæg.
First we will create a trivial command which do nothing but print the configuration:
Then, we only have to create a Flæg object and call the function Run :
Let’s try this program. We will first call the helper :
As you can see, the generated flags match the fields of the configuration structure with substructures `DatabaseInfo` and `OwnerInfo`. Default values can be defined directly in the fields of the configuration structure. These fields will be unchanged if their `flags` are not used in argument.
Then, we can try the program:
Flæg also handles sub-command, like the “version” command in the example :
To learn much more about Flæg, please visit the github project page https://github.com/containous/flaeg.
Thanks to Flæg, we have a nice solution to load the configuration from the flags. The maintenance is now way simpler than it used to be, which is appreciated on open source projects. But how can we manage merging this CLI configuration with other sources like configuration files ?
Stært
The CLI is not the only way to provide configuration to a program. There are other sources of configuration. For instance, Træfik can take a configuration from flags, from a config file and from a distributed Key-Value Store.
We created Stært to merge those configuration sources. So far, only flags (using Flæg), TOML config file and Key-Value Stored configuration are implemented, but we did the package in such way that it is easy to add other sources.
Stært uses the same Command type as Flæg.
We just have to create some sources :
Then, we can create a Stært object and use it :
Stært will load the configuration in the row and overwrite it following precedence order :
- Key-Value Store source
- Flæg source
- TOML config file source
Here an example of TOML file :
And there is the way to store the Key-Value :
This was a simple example of what we can do with Stært.
To conclude, those two packages made us save a lot of time on the Træfik project. We can now load and merge several configurations from different sources. Any changes on the configuration structure are automagically handled.
More features are described on the Github project pages, please visit: