Skip to content

Repository files navigation

CFG

Go DocBuild Status

This package is designed to house a common set of configuration-related features & patterns for Golang services. This include:

  • Support for multiple sources of configuration.
  • Providing default values and validation logic for specific settings.
  • Package API which encourages high cohesion and low coupling with the rest of the application.

Usage

package config
import (
"context""strconv""time""github.com/zpatrick/cfg""github.com/zpatrick/cfg/envvar""github.com/zpatrick/cfg/ini"
)
typeConfigstruct {
ServerPortintServerTimeout time.DurationDatabaseAddressstringDatabaseUsernamestring
}
funcLoadConfig(ctx context.Context, pathstring) (*Config, error) {
iniFile, err:=ini.Load(path)
iferr!=nil {
returnnil, err
}
varcConfigiferr:=cfg.Load(ctx, cfg.Schemas{
"database address": cfg.Schema[string]{
Dest: &c.DatabaseAddress,
Default: cfg.Addr("localhost:3306"),
Provider: envvar.New("APP_DATABASE_ADDR"),
},
"database username": cfg.Schema[string]{
Dest: &c.DatabaseUsername,
Default: cfg.Addr("readonly"),
Validator: cfg.OneOf("admin", "readonly", "readwrite"),
Provider: envvar.New("APP_DATABASE_USERNAME"),
},
"server port": cfg.Schema[int]{
Dest: &c.ServerPort,
Default: cfg.Addr(8080),
Validator: cfg.Between(8000, 9000),
Provider: cfg.MultiProvider {
envvar.Newf("APP_SERVER_PORT", strconv.Atoi),
iniFile.Int("server", "port"),
},
},
"server timeout": cfg.Schema[time.Duration]{
Dest: &c.ServerTimeout,
Default: cfg.Addr(time.Second*30),
Validator: cfg.Between(time.Second, time.Minute*5),
Provider: cfg.MultiProvider {
envvar.Newf("APP_SERVER_TIMEOUT", time.ParseDuration),
iniFile.Duration("server", "timeout"),
},
},
}); err!=nil {
returnnil, err
}
returnc, nil
}

Built in Providers

For YAML files, please see the example.

Validation

A setting may specify a Validator which will check whether or not a provided value is valid. The built in validators are:

  • Between - Ensures a given value is between the specified parameters.
  • OneOf - Ensures a given value is one of the specified parameters.
  • Or - Combines multiple Validators, ensures at least one passes.
  • And - Combines multiple Validators, ensures all pass.
  • Not - Ensures a given validator does not pass.

Advanced

Custom Validation

A custom Validator must satisfy the Validator interface. The simplest way to achieve this is by using the ValidatorFunc type.

cfg.Setting[string]{
Default: cfg.Addr("name@email.com"),
Validator: cfg.ValidatorFunc(func(addrstring) error {
_, err:=mail.ParseAddr(addr)
returnerr
}),
}

Custom Providers

import (
"net/mail"
)
// Create a helper function which wraps the underlying type.funcprovideMailAddr(provider cfg.Provider[string]) cfg.Provider[*mail.Addr] {
return cfg.ProviderFunc[*mail.Addr](func(ctx context.Context) (*mail.Addr, error) {
// Get the underlying value from the given provider.raw, err:=provider.Provide(ctx)
iferr!=nil {
returnout, err
}
// Convert the underlying.returnmail.ParseAddr(raw)
})
}
// Use the helper function in your cfg.Setting definition.funcLoadConfig() (*Config, error) {
yamlFile, err:=cfg.YAMLFile("config.yaml")
iferr!=nil {
returnnil, err
}
email:= cfg.Setting[*mail.Addr]{
Providers: []cfg.Provider[*mail.Addr]{
provideMailAddr(yamlFile.String("email")),
},
}
...
}

About

Consolidate and validate application configuration.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages