9.4 KiB
Config
config is a simple golang library and designed to read configurations from JSON, Yaml files, environment variables and command line. config depends on go-yaml to analyze Yaml file and uses built-in golang library to handle JSON file.
Installation
- Install Yaml library first:
go get gopkg.in/yaml.v3
- Install config library:
git@git.mousesoft.ru:ms/config.git
Usage
I. Define configuration name in structure tags
Like JSON, Yaml, config uses tags to define configurations:
Tag | Example | Function |
---|---|---|
json | Host string json:"host" |
Maps Host to a JSON field: host |
yaml | Host string yaml:"host" |
Maps Host to a Yaml field: host |
env | Host string env:"HOST" |
Maps Host to a Environment variable: HOST |
cli | Host string cli:"host database host" |
Maps Host to a command line argument: -host or --host |
default | Port int default:"8080" |
Defines the port with default value: 8080 |
separator | Path string json:"path" separator:";" |
Separator is used to split string to a slice |
usage | Usage string usage:"host address" |
Usage description |
1. Data types
config supports the following golang data types:
- bool
- string
- int8, int16, int, int32, int64
- uint8, uint16, uint, uint32, uint64
- float32, float64
- time.Duration
- slice type. e.g: []string, []int ...
2. Defines default values
Using default keyword in structure tags to define default value:
type Log struct {
Path string `default:"/var/logs"`
Level string `default:"debug"`
}
3. Defines configuration name for JSON
Like parsing JSON object, using json keyword to define configuration name:
type Database struct {
Host string `json:"host"`
Port int `json:"port"`
Username string `default:"admin" json:"username"`
Password string `default:"admin" json:"password"`
Log Log `json:"log"`
}
Corresponding JSON file:
{
"host": "test.db.hostname",
"port": 8080,
"username": "admin",
"password": "admin",
"log": {
"path": "/var/logs/db",
"level": "debug"
}
}
4. Defines configuration name for Yaml
Like parsing Yaml object, using yaml keyword to define configuration name
type Database struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Username string `default:"admin" yaml:"username"`
Password string `default:"admin" yaml:"password"`
Log Log `yaml:"log"`
}
Corresponding Yaml file:
host: test.db.hostname
port: 8080
username: admin
password: admin
log:
path: /var/logs/db
level: debug
5. Defines configuration name for Environment variable
Using env keyword to define configuration name
type Database struct {
Host string `env:"DB_HOST"`
Port int `env:"DB_PORT"`
Username string `default:"admin" env:"DB_USER"`
Password string `default:"admin" env:"DB_PASSWORD"`
Log Log `env:"DB_LOG_"`
}
Corresponding Environment variables:
export DB_HOST=test.db.hostname
export DB_PORT=8080
export DB_USER=admin
export DB_PASSWORD=admin
export DB_LOG_PATH=/var/logs/db
export DB_LOG_LEVEL=debug
Since the Log
is a structure and nested in Database
structure, the tag of Log
and tags of its structure members will be combined to be an unique environment variable,
for example: Path
will be mapped to environment var: DB_LOG_PATH
.
But if the Log
has no tag definition, only tags of its structure members will
be used, that means the Path
will be mapped to PATH
.
6. Defines configuration name for Command line
Using cli keyword to define configuration name:
type Database struct {
Host string `cli:"host" usage:"database host name"`
Port int `cli:"port" usage:"database port"`
Username string `cli:"username" default:"admin" usage:"database username"`
Password string `cli:"password" default:"admin" usage:"database password"`
Log Log `cli:"log" usage:"database log configurations"`
}
For cli definition, the string is command line argument, and the usage tag are the command line usage and will be outputted when printing usage.
Corresponding command line:
./main --host test.db.hostname --port 8080 --username admin --password admin --log-path /var/logs/db --log-level debug
or
./main --host=test.db.hostname --port=8080 --username=admin --password=admin --log-path=/var/logs/db --log-level=debug
7. Defines configuration name as a slice type
Using separator to split string as a slice:
type Log struct {
Levels []string `env:"LEVELS" cli:"levels" separator:";" usage:"log levels"`
}
If the separator is not given, its default is :, The separator only works on env and cli tags.
logConfig := Log{}
// export LEVELS=debug;error;info
config.ParseEnv(&logConfig)
// logConfig[0] == debug
// logConfig[1] == error
// logConfig[2] == info
II. Parses configurations
1. Parses default values
When default values are defined in tags, calls config.ParseDefault(interface{})
to assign them to given structure instance BEFORE parsing any other configuration
types:
logConfig := Log{}
config.ParseDefault(&logConfig)
Note: Other parsing functions don't set structure instance with default values whatever if the configuration value is provided or not
2. Parses from Environment variables
dbConfig := Database{}
config.ParseEnv(&dbConfig)
3. Parses from Command line
dbConfig := Database{}
config.ParseCli(&dbConfig)
4. Parses from default configuration files
Calls ParseConfigFile(interface{}, string) to parse given configuration file:
dbConfig := Database{}
config.ParseConfigFile(&dbConfig, "config.json")
If the configuration file is not given, the default configuration files: config.json and config.yaml will be located under the same folder with fixed searching order.
The config.json will always be located first, if it doesn't exist, then checks
config.yaml. If all of them are not found, parsing will fail.
dbConfig := Database{}
config.ParseConfigFile(&dbConfig, "")
4. Parses from configuration file specified by command line
Calls ParseConfig(interface{}, string) to parse the configuration file given by command line. The second parameter is a command line argument which is used to specify config file:
dbConfig := Database{}
config.ParseConfig(&dbConfig, "c")
Run application like:
./main -c config.json
ParseConfig() will analyze command line arguments and get configure file: config.json from argument -c
III. Multi-Configurations
You can define all supported configuration tags in a structure and call corresponding functions in your desired order to parse.
Examples:
type Log struct {
Path string `cli:"path" default:"/var/logs" env:"PATH" json:"path" usage:"log path" yaml:"path"`
Levels string `cli:"levels" default:"debug;error" env:"LEVELS" json:"levels" usage:"log levels" yaml:"levels"`
}
type Database struct {
Host string `cli:"host" env:"DB_HOST" json:"host" usage:"database host name" yaml:"host"`
Port int `cli:"port" env:"DB_PORT" json:"port" usage:"database port" yaml:"port"`
Username string `cli:"username" default:"admin" env:"DB_USER" json:"user" usage:"database username" yaml" user"`
Password string `cli:"password" default:"admin" env:"DB_PASSWD" json:"passwd" usage:"database password" yaml:"passwd"`
Log Log `cli:"log" env:"DB_LOG_" json:"log" usage:"database log configurations" yaml:"log"`
}
Then, you can parse as below:
dbConfig := Database{}
// parse default values
if err := config.ParseDefault(&dbConfig); err != nil {
// error handling
}
cmd := config.NewCLI("")
if err := cmd.Init(&dbConfig); err != nil {
// error handling
}
// capture cli flags
args := cmd.Capture(os.Args)
// parse cli flags of application, urfave for example
flagSet.Parse(args)
// parse captured cli flags of config
if err := cmd.Parse(cmd.Args); err != nil {
// error handling
}
// parse configuration file from command line
err := config.ParseConfig(&dbConfig, "c")
// parse default configurations
if err != nil {
err = config.ParseConfigFile(&dbConfig), "")
}
// parse environment variables
if err != nil {
err = config.ParseEnv(&dbConfig)
}
// parse command line
if err != nil {
err = config.ParseCli(&dbConfig)
}
// check if all required configurations are set
...
You don't need to call all of them. Just invokes parsing function that your need.
License
This project is licensed under the Apache License Version 2.0.