README
¶
Xconf
Package xconf
provides a configuration registry for an application.
Configurations can be extracted from a file / env / flag set / remote system.
Supported formats are json, yaml, ini, (java) properties, toml, plain.
Installation
$ go get -u github.com/actforgood/xconf
Configuration loaders
You can create your own configuration retriever implementing Loader
interface.
Package provides these Loaders for you:
EnvLoader
- loads environment variables.DotEnvFileLoader
- loads configuration from a .env file.JSONFileLoader
- loads json configuration from a file.JSONReaderLoader
- loads json configuration from aio.Reader
.YAMLFileLoader
- loads yaml configuration from a file.YAMLReaderLoader
- loads yaml configuration from aio.Reader
.IniFileLoader
- loads ini configuration from a file.PropertiesFileLoader
- loads java style properties configuration from a file.PropertiesBytesLoader
- loads java style properties configuration from a bytes slice.TOMLFileLoader
- loads toml configuration from a file.TOMLReaderLoader
- loads toml configuration from aio.Reader
.ConsulLoader
- loads json/yaml/plain configuration from a remote Consul KV Store.EtcdLoader
- loads json/yaml/plain configuration from a remote Etcd KV Store.PlainLoader
- explicit configuration provider.FileLoader
- factory for<JSON|YAML|Ini|DotEnv|Properties|TOML>FileLoader
s based on file extension.FlagSetLoader
- extracts configuration from aflag.FlagSet
.MultiLoader
- loads (and merges, if configured) configuration from multiple loaders.
Upon above loaders there are available decorators which can help you achieve more sophisticated outcome:
FilterKVLoader
- filters other loader's configurations (based on keys and or their values).
Example of applicability: I load configurations from environment, but I only want the ones prefixed with "MY_APP_" - I can apply this loader withFilterKVWhitelistFunc(FilterKeyWithPrefix("MY_APP_")
filter function.AlterValueLoader
- changes the value for a configuration key.
Example of applicability: I load configurations from environment and for a given key I want its value to be a slice (not a string as envs are read/stored by default) - I can apply this loader withToStringList
altering function.IgnoreErrorLoader
- ignores the error returned by another loader.
Example of applicability: I load configuration from environment and from file (using aMultiLoader
), but it's not mandatory for that file to exist (file it's just an auxiliary source for my configurations, that may exist) - I can use this loader to ignore "file does not exist" error.FileCacheLoader
- caches configuration from a[X]FileLoader
until file gets modified (to be used if loader is called multiple times).FlattenLoader
- creates easy to access nested configuration leaf keys symlinks.AliasLoader
- creates aliases for other keys.
Configuration contract
The main configuration contract this package provides looks like:
type Config interface {
Get(key string, def ...interface{}) interface{}
}
with a default implementation obtained with:
// NewDefaultConfig instantiates a new default config object.
// The first parameter is the loader used as a source of getting the key-value configuration map.
// The second parameter represents a list of optional functions to configure the object.
func NewDefaultConfig(loader Loader, opts ...DefaultConfigOption) (*DefaultConfig, error)
The DefaultConfig
has an option of reloading configurations (interval based), if you want to retrieve updated configuration
at runtime.
There are 2 (proposed) ways of working with it:
- injecting a
Config
reference and callingGet(key)
every time you need a configuration. - registering your class as an observer to get notified about config changes.
Example of usage (first case) (note: code does not compile):
// cart_service.go
const (
defaultMaxQtyCfgVal uint = 100
maxQtyCfgKey = "MAX_ALLOWED_QTY_TO_ORDER"
)
type CartService struct {
config xconf.Config
}
func NewCartService(config xconf.Config) *CartService {
return &CartService{
config: config,
}
}
func (cartSvc *CartService) AddProduct(sku string, qty uint) error {
// ...
if customerType != B2B {
totalQty := currentQty + qty
maxQty := cartSvc.config.Get(maxQtyCfgKey, defaultMaxQtyCfgVal).(uint)
if totalQty > maxQty {
return ErrMaxQtyExceeded
}
}
// ...
return nil
}
func main() {
// somewhere in the bootstrap of your application ...
var (
loader xconf.Loader // = ... your desired source(s)
config xconf.Config
cartSvc *CartService
)
config, err := xconf.NewDefaultConfig(
loader,
xconf.DefaultConfigWithReloadInterval(time.Minute), // reload every minute
)
if err != nil {
panic(err)
}
cartSvc = NewCartService(config)
// somewhere in the application business flow ...
_ = cartSvc.AddProduct("IPHONE", 1)
// somewhere in the shutdown of your application ...
if closableConfig, ok := config.(io.Closer); ok {
_ = closableConfig.Close()
}
}
Example of usage (second case) (note: code does not compile):
// redis_wrapper.go
const (
RedisHostCfgKey = "REDIS_HOST"
DefaultRedisHostCfgVal = "127.0.0.1:6379"
)
type RedisClient interface {
Ping() error
Get(key string) (string, error)
Set(key string, value interface{}, expiration time.Duration) (string, error)
Close() error
}
type RedisClientWrapper struct {
client *redis.Client // official client
mu sync.RWMutex
}
func NewRedisClientWrapper(host string) *RedisClientWrapper {
officialClient = ...
return &RedisClientWrapper {
client: officialClient,
}
}
func (wrapper *RedisClientWrapper) Get(key string) (string, error) {
wrapper.mu.RLock()
defer wrapper.mu.RUnlock()
return wrapper.client.Get(key).Result()
}
func (wrapper *RedisClientWrapper) OnConfigChange(config xconf.Config, changedKeys ...string) {
for _, changedKey := range changedKeys {
if changedKey == RedisHostCfgKey { // or use strings.EqualFold() if you enabled DefaultConfigWithIgnoreCaseSensitivity.
wrapper.mu.Lock()
_ = wrapper.client.Close() // close previous client
newClient := ... // reinitialize client based on config.Get(RedisHostCfgKey).(string)
wrapper.client = newClient
wrapper.mu.Unlock()
}
}
}
func main() {
// somewhere in the bootstrap of your application ...
var (
loader xconf.Loader // = ... your desired source(s)
config xconf.Config
redisClient RedisClient
)
config, err := xconf.NewDefaultConfig(
loader,
xconf.DefaultConfigWithReloadInterval(30 * time.Second), // reload every 30 seconds
)
if err != nil {
panic(err)
}
redisHost := config.Get(RedisHostCfgKey, DefaultRedisHostCfgVal).(string)
redisClient = NewRedisClient(redisHost)
config.RegisterObserver(redisClient.OnConfigChange) // register redis wrapper as an observer
// somewhere in the application business flow ...
_, _ = redisClient.Get("something")
// somewhere in the shutdown of your application ...
if closableConfig, ok := config.(io.Closer); ok {
_ = closableConfig.Close()
}
_ = redisClient.Close()
}
Unmarshal configuration map to structs
This is not the subject of this package, but as a mention, you can achieve that if needed, with a package like github.com/mitchellh/mapstructure.
Example:
package main
import (
"bytes"
"fmt"
"github.com/actforgood/xconf"
"github.com/mitchellh/mapstructure"
)
type DBConfig struct {
Host string
Port int
Auth Auth
}
type Auth struct {
Username string
Password string
}
func main() {
var (
jsonConfig = `{
"db": {
"host": "127.0.0.1",
"port": 3306,
"auth": {
"username": "JohnDoe",
"password": "verySecretPwd"
}
}
}`
dbConfig DBConfig // the struct to populate with configuration
dbConfigMap map[string]interface{} // the configuration map for "db" key
loader = xconf.JSONReaderLoader(bytes.NewReader([]byte(jsonConfig)))
)
// example using directly a Loader:
configMap, err := loader.Load()
if err != nil {
panic(err)
}
dbConfigMap = configMap["db"].(map[string]interface{})
if err := mapstructure.Decode(dbConfigMap, &dbConfig); err != nil {
panic(err)
}
fmt.Printf("%+v", dbConfig)
// example using the Config contract:
config, err := xconf.NewDefaultConfig(loader)
if err != nil {
panic(err)
}
dbConfigMap = config.Get("db").(map[string]interface{})
if err := mapstructure.Decode(dbConfigMap, &dbConfig); err != nil {
panic(err)
}
fmt.Printf("%+v", dbConfig)
// both Printf will produce: {Host:127.0.0.1 Port:3306 Auth:{Username:JohnDoe Password:verySecretPwd}}
}
TODOs
Things that can be added to package, extended:
- Support more formats (like HCL)
- Add also a writer/persister functionality (currently you can only read configurations) to different sources and formats (JSONFileWriter/YAMLFileWriter/EtcdWriter/ConsulWriter/...) implementing a common contract like:
type ConfigWriter interface {
Write(configMap map[string]interface{}) error
}
- Add a typed struct with methods like
GetString
,GetInt
...
Misc
Feel free to use this pkg if you like it and fits your needs.
Check also other packages like spf13/viper ...
License
This package is released under a MIT license. See LICENSE.
Other 3rd party packages directly used by this package are released under their own licenses.
- github.com/joho/godotenv - MIT License
- github.com/magiconair/properties - BSD (2 Clause) License
- gopkg.in/ini.v1 - Apache 2.0 License
- gopkg.in/yaml.v3 - MIT And Apache License
- github.com/pelletier/go-toml/v2 - MIT License
- go.etcd.io/etcd/client/v3 - Apache 2.0 License
- github.com/spf13/cast - MIT License
- github.com/actforgood/xerr - MIT License
- github.com/actforgood/xlog - MIT License
Documentation
¶
Overview ¶
Package xconf provides a configuration registry for an application. Configurations can be extracted from a file / env / flag set / remote system. Supported formats are json, yaml, ini, (java) properties, toml, plain.
Index ¶
- Constants
- Variables
- func DeepCopyConfigMap(src map[string]interface{}) map[string]interface{}
- func FilterEmptyValue(_ string, value interface{}) bool
- func FilterExactKeys(keys ...string) func(key string, _ interface{}) bool
- func FilterKeyWithPrefix(prefix string) func(key string, _ interface{}) bool
- func FilterKeyWithSuffix(suffix string) func(key string, _ interface{}) bool
- func LogErrorHandler(loggerGetter func() xlog.Logger) func(error)
- func LogLevelProvider(config Config, lvlKey string, defaultLvl string, ...) xlog.LevelProvider
- type AlterValueFunc
- type Config
- type ConfigObserver
- type ConsulLoader
- type ConsulLoaderOption
- func ConsulLoaderWithCache() ConsulLoaderOption
- func ConsulLoaderWithContext(ctx context.Context) ConsulLoaderOption
- func ConsulLoaderWithHTTPClient(client *http.Client) ConsulLoaderOption
- func ConsulLoaderWithHost(host string) ConsulLoaderOption
- func ConsulLoaderWithPrefix() ConsulLoaderOption
- func ConsulLoaderWithQueryDataCenter(dc string) ConsulLoaderOption
- func ConsulLoaderWithQueryNamespace(ns string) ConsulLoaderOption
- func ConsulLoaderWithRequestHeader(hName, hValue string) ConsulLoaderOption
- func ConsulLoaderWithValueFormat(valueFormat string) ConsulLoaderOption
- type DefaultConfig
- type DefaultConfigOption
- type EtcdLoader
- type EtcdLoaderOption
- func EtcdLoaderWithAuth(username, pwd string) EtcdLoaderOption
- func EtcdLoaderWithContext(ctx context.Context) EtcdLoaderOption
- func EtcdLoaderWithEndpoints(endpoints []string) EtcdLoaderOption
- func EtcdLoaderWithPrefix() EtcdLoaderOption
- func EtcdLoaderWithTLS(tlsCfg *tls.Config) EtcdLoaderOption
- func EtcdLoaderWithValueFormat(valueFormat string) EtcdLoaderOption
- func EtcdLoaderWithWatcher() EtcdLoaderOption
- type FileCacheLoader
- type FilterKV
- type FilterKVBlacklistFunc
- type FilterKVWhitelistFunc
- type FilterType
- type FlattenLoader
- type FlattenLoaderOption
- type IniFileLoader
- type IniFileLoaderOption
- type KeyConflictError
- type Loader
- func AliasLoader(loader Loader, aliasKeyKey ...string) Loader
- func AlterValueLoader(loader Loader, transformation AlterValueFunc, keys ...string) Loader
- func DotEnvFileLoader(filePath string) Loader
- func DotEnvReaderLoader(reader io.Reader) Loader
- func EnvLoader() Loader
- func FileLoader(filePath string) Loader
- func FilterKVLoader(loader Loader, filters ...FilterKV) Loader
- func FlagSetLoader(flgSet *flag.FlagSet, visitAll ...bool) Loader
- func IgnoreErrorLoader(loader Loader, errs ...error) Loader
- func JSONFileLoader(filePath string) Loader
- func JSONReaderLoader(reader io.Reader) Loader
- func PlainLoader(configMap map[string]interface{}) Loader
- func PropertiesBytesLoader(propertiesContent []byte) Loader
- func PropertiesFileLoader(filePath string) Loader
- func TOMLFileLoader(filePath string) Loader
- func TOMLReaderLoader(reader io.Reader) Loader
- func YAMLFileLoader(filePath string) Loader
- func YAMLReaderLoader(reader io.Reader) Loader
- type LoaderFunc
- type MockConfig
- type MultiLoader
- type NopConfig
Examples ¶
- AliasLoader
- AlterValueLoader
- ConsulLoader
- DefaultConfig
- DotEnvFileLoader
- EnvLoader
- EtcdLoader
- FileCacheLoader
- FileLoader
- FilterEmptyValue
- FilterExactKeys
- FilterKVLoader
- FilterKeyWithPrefix
- FilterKeyWithSuffix
- FlagSetLoader
- FlattenLoader
- IgnoreErrorLoader
- IniFileLoader
- JSONFileLoader
- LogErrorHandler
- LogLevelProvider
- MultiLoader
- PropertiesFileLoader
- TOMLFileLoader
- YAMLFileLoader
Constants ¶
const ( // RemoteValueJSON indicates that content under a key is in JSON format. RemoteValueJSON = "json" // RemoteValueYAML indicates that content under a key is in YAML format. RemoteValueYAML = "yaml" // RemoteValuePlain indicates that content under a key is plain text. RemoteValuePlain = "plain" )
const ( // ConsulHeaderAuthToken is the header name for setting a token. // See also [Consul API Ref]. // // [Consul API Ref]: https://www.consul.io/api-docs#authentication ConsulHeaderAuthToken = "X-Consul-Token" )
Variables ¶
var ErrAliasPairBroken = errors.New("alias - missing key")
ErrAliasPairBroken is an error returned by AliasLoader when the variadic list of aliases and their keys consists of odd no. of elements.
var ErrConsulKeyNotFound = errors.New("404 - Consul Key Not Found")
ErrConsulKeyNotFound is thrown when a Consul read key request responds with 404.
var ErrUnknownConfigFileExt = errors.New("unknown configuration file extension")
ErrUnknownConfigFileExt is an error returned by FileLoader if file extension does not match any supported format.
Functions ¶
func DeepCopyConfigMap ¶
DeepCopyConfigMap is a utility function to make a deep "copy"/clone of a config map.
func FilterEmptyValue ¶
FilterEmptyValue returns true if a value is nil or "". It can be used as a FilterKV like:
xconf.FilterKVBlacklistFunc(xconf.FilterEmptyValue)
func FilterExactKeys ¶
FilterExactKeys returns true if a key is present in the provided list. It can be used as a FilterKV like:
xconf.FilterKVWhitelistFunc(xconf.FilterExactKeys(key1, key2)) xconf.FilterKVBlacklistFunc(xconf.FilterExactKeys(key1, key2))
func FilterKeyWithPrefix ¶
FilterKeyWithPrefix returns true if a key has given prefix. It can be used as a FilterKV like:
xconf.FilterKVWhitelistFunc(xconf.FilterKeyWithPrefix(prefix)) xconf.FilterKVBlacklistFunc(xconf.FilterKeyWithPrefix(prefix))
func FilterKeyWithSuffix ¶
FilterKeyWithSuffix returns true if a key has given suffix. It can be used as a FilterKV like:
xconf.FilterKVWhitelistFunc(xconf.FilterKeyWithSuffix(suffix)) xconf.FilterKVBlacklistFunc(xconf.FilterKeyWithSuffix(suffix))
func LogErrorHandler ¶
LogErrorHandler is a handler which can be used in a xconf.DefaultConfig object as a reload error handler. It logs the error with a xlog.Logger. Passed parameter is a function that returns the logger (Logger and Config depend one of each other, this way we can instantiate them separately...)
func LogLevelProvider ¶
func LogLevelProvider( config Config, lvlKey string, defaultLvl string, levelLabels map[xlog.Level]string, ) xlog.LevelProvider
LogLevelProvider provides a level read from a Config object. It can be used to configure log level for a xlog.Logger. If the level configuration key is not found, the default provided level is returned. If the reload option is present on the config object, you may change during application run the underlying key without restarting the app, and new configured value will be used in place, if suitable.
Example ¶
Output: {"date":"2022-06-21T17:17:20Z","lvl":"INFO","msg":"log level is taken from xconf.Config","src":"/xlog_adapter_test.go:48"}
Types ¶
type AlterValueFunc ¶
type AlterValueFunc func(value interface{}) interface{}
AlterValueFunc is a function that manipulates a config's value.
func ToIntList ¶
func ToIntList(sep string) AlterValueFunc
ToIntList makes a slice of integers from a string value, who's items are separated by given separator parameter.
If the original value is not a string, the value remains unaltered.
Example: "10,100,1000" => [10, 100, 1000].
func ToStringList ¶
func ToStringList(sep string) AlterValueFunc
ToStringList makes a slice of strings from a string value, who's items are separated by given separator parameter.
If the original value is not a string, the value remains unaltered.
Example: "bread,eggs,milk" => ["bread", "eggs", "milk"].
type Config ¶
type Config interface { // Get returns a configuration value for a given key. // The first parameter is the key to return the value for. // The second parameter is optional, and represents a default // value in case key is not found. It also has a role in inferring // the type of key's value (if it exists) and thus key's value // will be casted to default's value type. Get(key string, def ...interface{}) interface{} }
Config provides prototype for returning configurations.
type ConfigObserver ¶
ConfigObserver gets called to notify about changed keys on Config reload.
type ConsulLoader ¶
type ConsulLoader struct {
// contains filtered or unexported fields
}
ConsulLoader loads configuration from Consul Key-Value Store.
func NewConsulLoader ¶
func NewConsulLoader(key string, opts ...ConsulLoaderOption) ConsulLoader
NewConsulLoader instantiates a new ConsulLoader object that loads configuration from Consul.
func (ConsulLoader) Load ¶
func (loader ConsulLoader) Load() (map[string]interface{}, error)
Load returns a configuration key-value map from Consul KV Store, or an error if something bad happens along the process.
type ConsulLoaderOption ¶
type ConsulLoaderOption func(*ConsulLoader)
ConsulLoaderOption defines optional function for configuring a Consul Loader.
func ConsulLoaderWithCache ¶
func ConsulLoaderWithCache() ConsulLoaderOption
ConsulLoaderWithCache enables cache.
func ConsulLoaderWithContext ¶
func ConsulLoaderWithContext(ctx context.Context) ConsulLoaderOption
ConsulLoaderWithContext sets request 's context. By default, a context.Background() is used.
func ConsulLoaderWithHTTPClient ¶
func ConsulLoaderWithHTTPClient(client *http.Client) ConsulLoaderOption
ConsulLoaderWithHTTPClient sets the http client used for calls. A default one is provided if you don't use this option.
func ConsulLoaderWithHost ¶
func ConsulLoaderWithHost(host string) ConsulLoaderOption
ConsulLoaderWithHost sets Consul's base url. By default, is set to "http://127.0.0.1:8500". Consul host can also be set through CONSUL_HTTP_ADDR and CONSUL_HTTP_SSL ENV as in official hashicorp's client.
Example:
xconf.ConsulLoaderWithHost("http://consul.example.com:8500")
func ConsulLoaderWithPrefix ¶
func ConsulLoaderWithPrefix() ConsulLoaderOption
ConsulLoaderWithPrefix specifies if the lookup should be recursive and the "key" treated as a prefix instead of a literal match.
func ConsulLoaderWithQueryDataCenter ¶
func ConsulLoaderWithQueryDataCenter(dc string) ConsulLoaderOption
ConsulLoaderWithQueryDataCenter specifies the datacenter to query. This will default to the datacenter of the agent being queried. See also official doc. Example:
xconf.ConsulLoaderWithQueryDataCenter("my-dc")
func ConsulLoaderWithQueryNamespace ¶
func ConsulLoaderWithQueryNamespace(ns string) ConsulLoaderOption
ConsulLoaderWithQueryNamespace specifies the namespace to query (enterprise). If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace. For recursive lookups, the namespace may be specified as '*' and then results will be returned for all namespaces. Added in Consul 1.7.0. See also official doc.
Example:
xconf.ConsulLoaderWithQueryNamespace("my-ns")
func ConsulLoaderWithRequestHeader ¶
func ConsulLoaderWithRequestHeader(hName, hValue string) ConsulLoaderOption
ConsulLoaderWithRequestHeader adds a request header. You can set the auth token for example:
xconf.ConsulLoaderWithRequestHeader(xconf.ConsulHeaderAuthToken, "someSecretToken")
or some basic auth header:
xconf.ConsulLoaderWithRequestHeader("Authorization", "Basic " + base64.StdEncoding.EncodeToString([]byte(usr + ":" + pwd))
func ConsulLoaderWithValueFormat ¶
func ConsulLoaderWithValueFormat(valueFormat string) ConsulLoaderOption
ConsulLoaderWithValueFormat sets the value format for a key.
If is set to RemoteValueJSON, the key's value will be treated as JSON and configuration will be loaded from it.
If is set to RemoteValueYAML, the key's value will be treated as YAML and configuration will be loaded from it.
If is set to RemoteValuePlain, the key's value will be treated as plain content and configuration will contain the key and its plain value.
By default, is set to RemoteValuePlain.
type DefaultConfig ¶
type DefaultConfig struct {
// contains filtered or unexported fields
}
DefaultConfig is the default implementation for the Config contract. It is based on a Loader to retrieve configuration from. Is implements io.Closer interface and thus Close should be called at your application shutdown in order to avoid memory leaks.
func NewDefaultConfig ¶
func NewDefaultConfig(loader Loader, opts ...DefaultConfigOption) (*DefaultConfig, error)
NewDefaultConfig instantiates a new default config object. The first parameter is the loader used as a source of getting the key-value configuration map. The second parameter represents a list of optional functions to configure the object.
func (*DefaultConfig) Close ¶
func (cfg *DefaultConfig) Close() error
Close stops the underlying ticker used to reload config, avoiding memory leaks. It should be called at your application shutdown. It implements io.Closer interface, and the returned error can be disregarded (is nil all the time).
func (DefaultConfig) Get ¶
func (cfg DefaultConfig) Get(key string, def ...interface{}) interface{}
Get returns a configuration value for a given key. The first parameter is the key to return the value for. The second parameter is optional, and represents a default value in case key is not found. It so has a role in inferring the type of key's value (if it exists) and thus key's value will be casted to default's value type. Only basic types (string, bool, int, uint, float, and their flavours), time.Duration, time.Time, []int, []string are covered. If a cast error occurs, the defaultValue is returned.
func (DefaultConfig) RegisterObserver ¶
func (cfg DefaultConfig) RegisterObserver(observer ConfigObserver)
RegisterObserver adds a new observer that will get notified of keys changes.
type DefaultConfigOption ¶
type DefaultConfigOption func(*DefaultConfig)
DefaultConfigOption defines optional function for configuring a DefaultConfig object.
func DefaultConfigWithIgnoreCaseSensitivity ¶
func DefaultConfigWithIgnoreCaseSensitivity() DefaultConfigOption
DefaultConfigWithIgnoreCaseSensitivity disables case sensitivity for keys.
For example, if the configuration map contains a key "Foo", calling Get() with "foo" / "FOO" / etc. will return Foo's value.
Usage example:
cfg, err := xconf.NewDefaultConfig(loader, xconf.DefaultConfigWithIgnoreCaseSensitivity()) if err != nil { panic(err) } value1 := cfg.Get("foo") value2 := cfg.Get("FOO") value3 := cfg.Get("foO") // all values are equal
func DefaultConfigWithReloadErrorHandler ¶
func DefaultConfigWithReloadErrorHandler(errHandler func(error)) DefaultConfigOption
DefaultConfigWithReloadErrorHandler sets the handler for errors that may occur during reloading configuration, if DefaultConfigWithReloadInterval was applied. If reload fails, "old"/previous configuration is active.
You can choose to log the error, for example.
By default, error is simply ignored.
func DefaultConfigWithReloadInterval ¶
func DefaultConfigWithReloadInterval(reloadInterval time.Duration) DefaultConfigOption
DefaultConfigWithReloadInterval sets interval to reload configuration. Passing a value <= 0 disables the config reload.
By default, configuration reload is disabled.
Usage example:
// enable config reload at an interval of 5 minutes: cfg, err := xconf.NewDefaultConfig(loader, xconf.DefaultConfigWithReloadInterval(5 * time.Minute))
type EtcdLoader ¶
type EtcdLoader struct {
// contains filtered or unexported fields
}
EtcdLoader loads configuration from etcd. Close it if watcher option is enabled, in order to properly release resources.
func NewEtcdLoader ¶
func NewEtcdLoader(key string, opts ...EtcdLoaderOption) EtcdLoader
NewEtcdLoader instantiates a new EtcdLoader object that loads configuration from etcd.
func (EtcdLoader) Close ¶
func (loader EtcdLoader) Close() error
Close needs to be called in case watch key changes were enabled. It releases associated resources.
func (EtcdLoader) Load ¶
func (loader EtcdLoader) Load() (map[string]interface{}, error)
Load returns a configuration key-value map from etcd, or an error if something bad happens along the process.
type EtcdLoaderOption ¶
type EtcdLoaderOption func(*EtcdLoader)
EtcdLoaderOption defines optional function for configuring an Etcd Loader.
func EtcdLoaderWithAuth ¶
func EtcdLoaderWithAuth(username, pwd string) EtcdLoaderOption
EtcdLoaderWithAuth sets the authentication username and password.
func EtcdLoaderWithContext ¶
func EtcdLoaderWithContext(ctx context.Context) EtcdLoaderOption
EtcdLoaderWithContext sets request's context. By default, a context.Background() is used.
func EtcdLoaderWithEndpoints ¶
func EtcdLoaderWithEndpoints(endpoints []string) EtcdLoaderOption
EtcdLoaderWithEndpoints sets the etcd host(s) for the client. By default, is set to "127.0.0.1:2379". Etcd hosts can also be set through ETCD_ENDPOINTS ENV (comma separated, if there is more than 1 ep).
func EtcdLoaderWithPrefix ¶
func EtcdLoaderWithPrefix() EtcdLoaderOption
EtcdLoaderWithPrefix sets the WithPrefix() option on etcd client. The loaded key will be treated as a prefix, and thus all the keys having that prefix will be returned.
func EtcdLoaderWithTLS ¶ added in v1.5.0
func EtcdLoaderWithTLS(tlsCfg *tls.Config) EtcdLoaderOption
EtcdLoaderWithTLS sets the TLS configuration for secure communication between client and server.
func EtcdLoaderWithValueFormat ¶
func EtcdLoaderWithValueFormat(valueFormat string) EtcdLoaderOption
EtcdLoaderWithValueFormat sets the value format for a key.
If is set to RemoteValueJSON, the key's value will be treated as JSON and configuration will be loaded from it.
If is set to RemoteValueYAML, the key's value will be treated as YAML and configuration will be loaded from it.
If is set to RemoteValuePlain, the key's value will be treated as plain content and configuration will contain the key and its plain value.
By default, is set to RemoteValuePlain.
func EtcdLoaderWithWatcher ¶
func EtcdLoaderWithWatcher() EtcdLoaderOption
EtcdLoaderWithWatcher enables watch for keys changes. Use this if you intend to load configuration intensively, multiple times. If you plan to load configuration only once, or rarely, don't use this feature. If you use this feature, call Close() method on the loader to gracefully release resources (at your application shutdown).
type FileCacheLoader ¶
type FileCacheLoader struct {
// contains filtered or unexported fields
}
FileCacheLoader decorates another "file" loader to load configuration only if the file was modified. If the file was not modified since the previous load, the file won't be read and parsed again. You can improve performance this way, if you plan to load configuration multiple times (like using it in DefaultConfig with reload enabled).
Example ¶
Output: json_foo: bar json_year: 2022 json_temperature: 37.5 json_shopping_list: [bread milk eggs]
func NewFileCacheLoader ¶
func NewFileCacheLoader(loader Loader, filePath string) FileCacheLoader
NewFileCacheLoader instantiates a new FileCacheLoader object that loads that caches the configuration from the original "file" loader. The second parameter should be the same file as the original loader's one.
func (FileCacheLoader) Load ¶
func (decorator FileCacheLoader) Load() (map[string]interface{}, error)
Load returns decorated loader's key-value configuration map. If the file was modified since last load, that file will be read and parsed again, if not, the previous, already processed, configuration map will be returned.
type FilterKV ¶
type FilterKV interface { // IsAllowed returns true if a key-value is eligible to be returned // in the configuration map. IsAllowed(key string, value interface{}) bool // Type returns filter's type (FilterTypeWhitelist / FilterTypeBlacklist). Type() FilterType }
FilterKV is the contract for a key-value filter.
type FilterKVBlacklistFunc ¶
The FilterKVBlacklistFunc type is an adapter to allow the use of ordinary functions as FilterKV of "blacklist" type. If fn is a function with the appropriate signature, FilterKVBlacklistFunc(fn) is a FilterKV that calls fn and has type FilterTypeBlacklist. fn should return true if the KV is blacklisted.
Example:
xconf.FilterKVBlacklistFunc(func(key string, _ interface{}) bool { return key == "DENY_ME_1" || key == "DENY_ME_2" })
func (FilterKVBlacklistFunc) IsAllowed ¶
func (filter FilterKVBlacklistFunc) IsAllowed(key string, value interface{}) bool
IsAllowed returns false if a key-value is blacklisted.
func (FilterKVBlacklistFunc) Type ¶
func (filter FilterKVBlacklistFunc) Type() FilterType
Type returns filter's type (FilterTypeBlacklist).
type FilterKVWhitelistFunc ¶
The FilterKVWhitelistFunc type is an adapter to allow the use of ordinary functions as FilterKV of "whitelist" type. If fn is a function with the appropriate signature, FilterKVWhitelistFunc(fn) is a FilterKV that calls fn of type FilterTypeWhitelist. fn should return true if the KV is whitelisted.
Example:
xconf.FilterKVWhitelistFunc(func(key string, _ interface{}) bool { return key == "KEEP_ME_1" || key == "KEEP_ME_2" })
func (FilterKVWhitelistFunc) IsAllowed ¶
func (filter FilterKVWhitelistFunc) IsAllowed(key string, value interface{}) bool
IsAllowed returns true if a key-value is whitelisted.
func (FilterKVWhitelistFunc) Type ¶
func (filter FilterKVWhitelistFunc) Type() FilterType
Type returns filter's type (FilterTypeWhitelist).
type FilterType ¶
type FilterType byte
FilterType is just an alias for byte.
const ( // FilterTypeWhitelist represents a whitelist filter. FilterTypeWhitelist FilterType = 1 // FilterTypeBlacklist represents a blacklist filter. FilterTypeBlacklist FilterType = 2 )
type FlattenLoader ¶
type FlattenLoader struct {
// contains filtered or unexported fields
}
FlattenLoader decorates another loader to add shortcuts to leaves' information in a nested configuration key.
Example, given the configuration:
{ "mysql": { "host": "127.0.0.1", "port": 3306 } }
2 additional flat keys will be added to above standard configuration: "mysql.host", "mysql.port" for easy access of leaf-keys. Note: original nested configuration is still kept by default, if you want to remove it, apply FlattenLoaderWithFlatKeysOnly option.
func NewFlattenLoader ¶
func NewFlattenLoader(loader Loader, opts ...FlattenLoaderOption) FlattenLoader
NewFlattenLoader instantiates a new FlattenLoader object that adds flat version for nested keys for easily access.
func (FlattenLoader) Load ¶
func (decorator FlattenLoader) Load() (map[string]interface{}, error)
Load returns a configuration key-value map from original loader, enriched with shortcuts to leaves' information in nested configuration key(s).
type FlattenLoaderOption ¶
type FlattenLoaderOption func(*FlattenLoader)
FlattenLoaderOption defines optional function for configuring a Flatten Loader.
func FlattenLoaderWithFlatKeysOnly ¶
func FlattenLoaderWithFlatKeysOnly() FlattenLoaderOption
FlattenLoaderWithFlatKeysOnly triggers nested keys to be removed, and only their flat version to be kept.
func FlattenLoaderWithSeparator ¶
func FlattenLoaderWithSeparator(keySeparator string) FlattenLoaderOption
FlattenLoaderWithSeparator sets the separator for the new, flat keys. By default, is set to "."(dot).
type IniFileLoader ¶
type IniFileLoader struct {
// contains filtered or unexported fields
}
IniFileLoader is a loader that returns configuration from an INI content based file.
func NewIniFileLoader ¶
func NewIniFileLoader(filePath string, opts ...IniFileLoaderOption) IniFileLoader
NewIniFileLoader instantiates a new IniFileLoader object that loads INI configuration from a file. The location of INI content based file is given as parameter.
func (IniFileLoader) Load ¶
func (loader IniFileLoader) Load() (map[string]interface{}, error)
Load returns a configuration key-value map from a INI file, or an error if something bad happens along the process.
type IniFileLoaderOption ¶
type IniFileLoaderOption func(*IniFileLoader)
IniFileLoaderOption defines optional function for configuring an INI File Loader.
func IniFileLoaderWithLoadOptions ¶
func IniFileLoaderWithLoadOptions(iniLoadOpts ini.LoadOptions) IniFileLoaderOption
IniFileLoaderWithLoadOptions sets given ini load options on the loader. By default, an empty object is used.
func IniFileLoaderWithSectionKeyFunc
deprecated
func IniFileLoaderWithSectionKeyFunc(keyFunc func(section, key string) string) IniFileLoaderOption
IniFileLoaderWithSectionKeyFunc sets given configuration key name provider based on a key and the section it belongs to.
Deprecated: do not use it anymore, it will be removed in a future release! You can use FlattenLoader wrapper to get flatten keys when they belong to a section different from 'default' section, if needed. Neither current usage of accessing keys should be avoided. Example: for a key "bar" in section "[foo]"" deprecated implementation gives access to a key "foo/bar". This kind of key generation will be removed. You should use new implementation output in the form of map ({"foo": {"bar": ...}}).
type KeyConflictError ¶
type KeyConflictError struct {
// contains filtered or unexported fields
}
KeyConflictError is an error returned by MultiLoader in case of a duplicate key. If key overwrite is allowed, this error will not be returned.
func NewKeyConflictError ¶
func NewKeyConflictError(key string) KeyConflictError
NewKeyConflictError instantiates a new KeyConflictError. The duplicate key must be provided.
func (KeyConflictError) Error ¶
func (e KeyConflictError) Error() string
Error returns string representation of the KeyConflictError. It implements standard go error interface.
type Loader ¶
type Loader interface { // Load returns a configuration key value map or an error. // // It's Loader's responsibility to return a map that is safe for // an eventual later mutation (decorator pattern can be used to // modify a loader's returned configuration key value map and // that's why this must/should be accomplished safely; safely // from concurrency point of view / data integrity point of view; // in other words, Loader should return a disposable config map - // see also DeepCopyConfigMap utility and current usages as example). Load() (map[string]interface{}, error) }
Loader is responsible for loading a configuration key value map.
func AliasLoader ¶
AliasLoader decorates another loader to set aliases for keys. The aliases will be added to decorated loader's configuration map. The second parameter represents a list of alias and keys they're for under the form "aliasForKey1, key1, aliasForKey2, key2".
func AlterValueLoader ¶
func AlterValueLoader(loader Loader, transformation AlterValueFunc, keys ...string) Loader
AlterValueLoader decorates another loader to manipulate a config's value. The transformation function is applied to all passed keys.
Example ¶
Output: foo: foo val bar: 100 shopping_list: [bread eggs milk] weekend_days: [friday saturday sunday]
func DotEnvFileLoader ¶
DotEnvFileLoader loads .env configuration from a file. The location of .env content based file is given as parameter.
Example ¶
Output: DOTENV_FOO: bar DOTENV_YEAR: 2022 DOTENV_TEMPERATURE: 37.5 DOTENV_SHOPPING_LIST: bread,milk,eggs
func DotEnvReaderLoader ¶
DotEnvReaderLoader loads .env configuration from an io.Reader.
func FileLoader ¶ added in v1.3.0
FileLoader is a factory for appropriate XFileLoader based on file's extension. This is useful when you don't want to tie an application to a certain config format. Supported extensions are: .json, .yml, .yaml, .ini, .properties, .env, .toml.
func FilterKVLoader ¶
FilterKVLoader decorates another loader to whitelist/blacklist key-values.
A blacklist filter has more weight than a whitelist filter, as if a blacklist denies a KV and a whitelist allows it, that KV will not be returned in the configuration map.
If there are only whitelist filters, a KV will be returned into the configuration map if at least one filter allows it.
If there are only blacklist filters, a KV will be returned into the configuration map if no filter denies it.
Example ¶
Output: APP_FOO_1: bar 1 APP_FOO_2: bar 2 REDIS_SERVICE_HOST: 10.0.0.11 REDIS_SERVICE_PORT: 6379 MYSQL_SERVICE_HOST: 10.0.0.12 MYSQL_SERVICE_PORT: 3306
func FlagSetLoader ¶ added in v1.5.0
FlagSetLoader reduces flags to a configuration map. The first parameter is the flag.FlagSet holding flags. The second, optional, parameter indicates if all flags (even those not explicitly set) should be taken into consideration; by default, is true.
Example ¶
Output: flag_foo: bar flag_year: 2022 flag_temperature: 37.5 flag_shopping_list: bread,milk,eggs
func IgnoreErrorLoader ¶
IgnoreErrorLoader decorates another loader to ignore the error returned by it, if error is present in the list of errors passed as second parameter. You can ignore, for example, os.ErrNotExist for a file based Loader if that file is not mandatory to exist, or Consul's ErrConsulKeyNotFound, etc.
func JSONFileLoader ¶
JSONFileLoader loads JSON configuration from a file. The location of JSON content based file is given as parameter.
Example ¶
Output: json_foo: bar json_year: 2022 json_temperature: 37.5 json_shopping_list: [bread milk eggs]
func JSONReaderLoader ¶
JSONReaderLoader loads JSON configuration from an io.Reader.
func PlainLoader ¶
PlainLoader is an explicit go configuration map retriever. It simply returns a copy of the given config map parameter.
It can be used for example:
- in a MultiLoader (with allowing keys overwrite) as the first loader in order to specify default configurations.
- to provide any application hardcoded configs.
func PropertiesBytesLoader ¶
PropertiesBytesLoader loads Properties configuration from bytes.
func PropertiesFileLoader ¶
PropertiesFileLoader loads Java Properties configuration from a file. The location of properties content based file is given as parameter.
Example ¶
Output: properties_foo: bar properties_baz: bar properties_year: 2022 properties_temperature: 37.5
func TOMLFileLoader ¶ added in v1.4.0
TOMLFileLoader loads TOML configuration from a file. The location of TOML content based file is given as parameter.
Example ¶
Output: toml_foo: bar toml_year: 2022 toml_temperature: 37.5 toml_shopping_list: [bread milk eggs]
func TOMLReaderLoader ¶ added in v1.4.0
TOMLReaderLoader loads TOML configuration from an io.Reader.
func YAMLFileLoader ¶
YAMLFileLoader loads YAML configuration from a file. The location of YAML content based file is given as parameter.
Example ¶
Output: yaml_foo: bar yaml_year: 2022 yaml_temperature: 37.5 yaml_shopping_list: [bread milk eggs]
func YAMLReaderLoader ¶
YAMLReaderLoader loads YAML configuration from an io.Reader.
type LoaderFunc ¶
The LoaderFunc type is an adapter to allow the use of ordinary functions as Loaders. If fn is a function with the appropriate signature, LoaderFunc(fn) is a Loader that calls fn.
func (LoaderFunc) Load ¶
func (fn LoaderFunc) Load() (map[string]interface{}, error)
Load calls fn().
type MockConfig ¶
type MockConfig struct {
// contains filtered or unexported fields
}
MockConfig is a mock for xconf.Config contract, to be used in UT.
func NewMockConfig ¶
func NewMockConfig(kv ...interface{}) *MockConfig
NewMockConfig instantiates new mocked Config with given key-values configuration. Make sure you pass an even number of elements and that the keys are strings.
Usage example:
mock := xconf.NewMockConfig( "foo", "bar", "year", 2022, )
func (*MockConfig) Get ¶
func (mock *MockConfig) Get(key string, def ...interface{}) interface{}
Get mock logic.
func (*MockConfig) GetCallsCount ¶
func (mock *MockConfig) GetCallsCount() int
GetCallsCount returns the no. of times Get() method was called.
func (*MockConfig) SetGetCallback ¶
func (mock *MockConfig) SetGetCallback(callback func(key string, def ...interface{}))
SetGetCallback sets the given callback to be executed inside Get() method. You can inject yourself to make assertions upon passed parameter(s) this way.
Usage example:
mock.SetGetCallback(func(key string, def ...interface{}) { switch mock.GetCallsCount() { case 1: if key != "expectedKeyAtCall1" { t.Error("...") } case 2: if key != "expectedKeyAtCall2" { t.Error("...") } } })
func (*MockConfig) SetKeyValues ¶
func (mock *MockConfig) SetKeyValues(kv ...interface{})
SetKeyValues sets/resets given key-values. Make sure you pass an even number of elements and that the keys are strings.
type MultiLoader ¶
type MultiLoader struct {
// contains filtered or unexported fields
}
MultiLoader is a composite loader that returns configurations from multiple loaders.
Example ¶
Output: json_foo: bar json_year: 2022 json_temperature: 37.5 json_shopping_list: [bread milk eggs] yaml_foo: bar yaml_year: 2022 yaml_temperature: 37.5 yaml_shopping_list: [bread milk eggs] plain_key: plain value
func NewMultiLoader ¶
func NewMultiLoader(allowKeyOverwrite bool, loaders ...Loader) MultiLoader
NewMultiLoader instantiates a new MultiLoader object that loads and merges configuration from multiple loaders. The first parameter is a flag indicating whether a key is allowed to be overwritten, if found more than once. If not, a KeyConflictError will be returned. If yes, the order of loaders matters, meaning a later provided loader, will overwrite a previous provided loader's same found key. The rest of the parameters consist of the list of loaders configuration should be retrieved from.
func (MultiLoader) Load ¶
func (loader MultiLoader) Load() (map[string]interface{}, error)
Load returns a merged configuration key-value map of all encapsulated loaders, or an error if something bad happens along the process.
Source Files
¶
- config.go
- config_mock.go
- config_nop.go
- deepcopy.go
- doc.go
- loader.go
- loader_consul.go
- loader_decorator_alias.go
- loader_decorator_alter_value.go
- loader_decorator_filecache_loader.go
- loader_decorator_filter_kv.go
- loader_decorator_flatten.go
- loader_decorator_ignore_error.go
- loader_dotenv.go
- loader_env.go
- loader_etcd.go
- loader_file.go
- loader_flagset.go
- loader_ini.go
- loader_json.go
- loader_multi.go
- loader_plain.go
- loader_properties.go
- loader_toml.go
- loader_yaml.go
- remote.go
- xlog_adapter.go