multiconfig

package module
v0.0.0-...-69c2730 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2017 License: MIT Imports: 17 Imported by: 0

README

Multiconfig GoDoc Build Status

Load configuration from multiple sources. Multiconfig makes loading/parsing from different configuration sources an easy task. The problem with any app is that with time there are many options how to populate a set of configs. Multiconfig makes it easy by dynamically creating all necessary options. Checkout the example below to see it in action.

Features

Multiconfig is able to read configuration automatically based on the given struct's field names from the following sources:

  • Struct tags
  • TOML file
  • JSON file
  • YAML file
  • Environment variables
  • Flags

Install

go get github.com/koding/multiconfig

Usage and Examples

Lets define and struct that defines our configuration

type Server struct {
	Name    string `required:"true"`
	Port    int    `default:"6060"`
	Enabled bool
	Users   []string
}

Load the configuration into multiconfig:

// Create a new DefaultLoader without or with an initial config file
m := multiconfig.New()
m := multiconfig.NewWithPath("config.toml") // supports TOML, JSON and YAML

// Get an empty struct for your configuration
serverConf := new(Server)

// Populated the serverConf struct
err := m.Load(serverConf) // Check for error
m.MustLoad(serverConf)    // Panic's if there is any error

// Access now populated fields
serverConf.Port // by default 6060
serverConf.Name // "koding"

Run your app:

# Sets default values first which are defined in each field tag value. 
# Starts to load from config.toml
$ app

# Override any config easily with environment variables, environment variables
# are automatically generated in the form of STRUCTNAME_FIELDNAME
$ SERVER_PORT=4000 SERVER_NAME="koding" app

# Or pass via flag. Flags are also automatically generated based on the field
# name
$ app -port 4000 -users "gopher,koding"

# Print dynamically generated flags and environment variables:
$ app -help
Usage of app:
  -enabled=true: Change value of Enabled.
  -name=Koding: Change value of Name.
  -port=6060: Change value of Port.
  -users=[ankara istanbul]: Change value of Users.

Generated environment variables:
   SERVER_NAME
   SERVER_PORT
   SERVER_ENABLED
   SERVER_USERS

License

The MIT License (MIT) - see LICENSE for more details

Documentation

Overview

Package multiconfig provides a way to load and read configurations from multiple sources. You can read from TOML file, JSON file, YAML file, Environment Variables and flags. You can set the order of reader with MultiLoader. Package is extensible, you can add your custom Loader by implementing the Load interface.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrSourceNotSet states that neither the path or the reader is set on the loader
	ErrSourceNotSet = errors.New("config path or reader is not set")

	// ErrFileNotFound states that given file is not exists
	ErrFileNotFound = errors.New("config file not found")
)

Functions

func MustLoad

func MustLoad(conf interface{})

MustLoad loads with the DefaultLoader settings. It exits if the config cannot be parsed.

func MustLoadWithPath

func MustLoadWithPath(path string, conf interface{})

MustLoadWithPath loads with the DefaultLoader settings and from the given Path. It exits if the config cannot be parsed.

Types

type DefaultLoader

type DefaultLoader struct {
	Loader
	Validator
}

DefaultLoader implements the Loader interface. It initializes the given pointer of struct s with configuration from the default sources. The order of load is TagLoader, FileLoader, EnvLoader and lastly FlagLoader. An error in any step stops the loading process. Each step overrides the previous step's config (i.e: defining a flag will override previous environment or file config). To customize the order use the individual load functions.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name    string `default:"gopher"`
	Port    int    `default:"6060"`
	Enabled bool
	Users   []string
}

// Instantiate a default loader.
d := NewWithPath("testdata/config.toml")

s := &ServerConfig{}

// It first sets the default values for each field with tag values defined
// with "default", next it reads from config.toml, from environment
// variables and finally from command line flags. It panics if loading fails.
d.MustLoad(s)

fmt.Println("Host-->", s.Name)
fmt.Println("Port-->", s.Port)
Output:

Host--> koding
Port--> 6060

func New

func New() *DefaultLoader

New returns a new instance of DefaultLoader without any file loaders.

func NewWithPath

func NewWithPath(path string) *DefaultLoader

NewWithPath returns a new instance of Loader to read from the given configuration file.

func (*DefaultLoader) MustLoad

func (d *DefaultLoader) MustLoad(conf interface{})

MustLoad is like Load but panics if the config cannot be parsed.

func (*DefaultLoader) MustValidate

func (d *DefaultLoader) MustValidate(conf interface{})

MustValidate validates the struct. It exits with status 1 if it can't validate.

type EnvironmentLoader

type EnvironmentLoader struct {
	// Prefix prepends given string to every environment variable
	// {STRUCTNAME}_FIELDNAME will be {PREFIX}_FIELDNAME
	Prefix string

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a environment name of
	// "STRUCTNAME_ACCESSKEY". If CamelCase is enabled, the environment name
	// will be generated in the form of "STRUCTNAME_ACCESS_KEY"
	CamelCase bool
}

EnvironmentLoader satisifies the loader interface. It loads the configuration from the environment variables in the form of STRUCTNAME_FIELDNAME.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name     string
	Port     int
	Enabled  bool
	Users    []string
	Postgres Postgres
}

// Assume those values defined before running the Loader
os.Setenv("SERVERCONFIG_NAME", "koding")
os.Setenv("SERVERCONFIG_PORT", "6060")

// Instantiate loader
l := &EnvironmentLoader{}

s := &ServerConfig{}
err := l.Load(s)
if err != nil {
	panic(err)
}

fmt.Println("Host-->", s.Name)
fmt.Println("Port-->", s.Port)
Output:

Host--> koding
Port--> 6060

func (*EnvironmentLoader) Load

func (e *EnvironmentLoader) Load(s interface{}) error

Load loads the source into the config defined by struct s

func (*EnvironmentLoader) PrintEnvs

func (e *EnvironmentLoader) PrintEnvs(s interface{})

PrintEnvs prints the generated environment variables to the std out.

type FlagLoader

type FlagLoader struct {
	// Prefix prepends the prefix to each flag name i.e:
	// --foo is converted to --prefix-foo.
	// --foo-bar is converted to --prefix-foo-bar.
	Prefix string

	// Flatten doesn't add prefixes for nested structs. So previously if we had
	// a nested struct `type T struct{Name struct{ ...}}`, this would generate
	// --name-foo, --name-bar, etc. When Flatten is enabled, the flags will be
	// flattend to the form: --foo, --bar, etc.. Panics if the nested structs
	// has a duplicate field name in the root level of the struct (outer
	// struct). Use this option only if you know what you do.
	Flatten bool

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a flag name "--accesskey". If
	// CamelCase is enabled, the flag name will be generated in the form of
	// "--access-key"
	CamelCase bool

	// EnvPrefix is just a placeholder to print the correct usages when an
	// EnvLoader is used
	EnvPrefix string

	// ErrorHandling is used to configure error handling used by
	// *flag.FlagSet.
	//
	// By default it's flag.ContinueOnError.
	ErrorHandling flag.ErrorHandling

	// Args defines a custom argument list. If nil, os.Args[1:] is used.
	Args []string

	// FlagUsageFunc an optional function that is called to set a flag.Usage value
	// The input is the raw flag name, and the output should be a string
	// that will used in passed into the flag for Usage.
	FlagUsageFunc func(name string) string
	// contains filtered or unexported fields
}

FlagLoader satisfies the loader interface. It creates on the fly flags based on the field names and parses them to load into the given pointer of struct s.

func (*FlagLoader) Load

func (f *FlagLoader) Load(s interface{}) error

Load loads the source into the config defined by struct s

type JSONLoader

type JSONLoader struct {
	Path   string
	Reader io.Reader
}

JSONLoader satisifies the loader interface. It loads the configuration from the given json file or Reader.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name     string
	Port     int
	Enabled  bool
	Users    []string
	Postgres Postgres
}

// Instantiate loader
l := &JSONLoader{Path: testJSON}

s := &ServerConfig{}
err := l.Load(s)
if err != nil {
	panic(err)
}

fmt.Println("Host-->", s.Name)
fmt.Println("Users-->", s.Users)
Output:

Host--> koding
Users--> [ankara istanbul]

func (*JSONLoader) Load

func (j *JSONLoader) Load(s interface{}) error

Load loads the source into the config defined by struct s. Defaults to using the Reader if provided, otherwise tries to read from the file

type Loader

type Loader interface {
	// Load loads the source into the config defined by struct s
	Load(s interface{}) error
}

Loader loads the configuration from a source. The implementer of Loader is responsible for setting the default values of the struct.

func MultiLoader

func MultiLoader(loader ...Loader) Loader

MultiLoader creates a loader that executes the loaders one by one in order and returns on the first error.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name     string
	Port     int
	Enabled  bool
	Users    []string
	Postgres Postgres
}

os.Setenv("SERVERCONFIG_NAME", "koding")
os.Setenv("SERVERCONFIG_PORT", "6060")

// Create a custom multi loader intance based on your needs.
f := &FlagLoader{}
e := &EnvironmentLoader{}

l := MultiLoader(f, e)

// Load configs into our s variable from the sources above
s := &ServerConfig{}
err := l.Load(s)
if err != nil {
	panic(err)
}

fmt.Println("Host-->", s.Name)
fmt.Println("Port-->", s.Port)
Output:

Host--> koding
Port--> 6060

type RequiredValidator

type RequiredValidator struct {
	//  TagName holds the validator tag name. The default is "required"
	TagName string

	// TagValue holds the expected value of the validator. The default is "true"
	TagValue string
}

RequiredValidator validates the struct against zero values.

func (*RequiredValidator) Validate

func (e *RequiredValidator) Validate(s interface{}) error

Validate validates the given struct agaist field's zero values. If intentionaly, the value of a field is `zero-valued`(e.g false, 0, "") required tag should not be set for that field.

type TOMLLoader

type TOMLLoader struct {
	Path   string
	Reader io.Reader
}

TOMLLoader satisifies the loader interface. It loads the configuration from the given toml file or Reader.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name     string
	Port     int
	Enabled  bool
	Users    []string
	Postgres Postgres
}

// Instantiate loader
l := &TOMLLoader{Path: testTOML}

s := &ServerConfig{}
err := l.Load(s)
if err != nil {
	panic(err)
}

fmt.Println("Host-->", s.Name)
fmt.Println("Users-->", s.Users)
Output:

Host--> koding
Users--> [ankara istanbul]

func (*TOMLLoader) Load

func (t *TOMLLoader) Load(s interface{}) error

Load loads the source into the config defined by struct s Defaults to using the Reader if provided, otherwise tries to read from the file

type TagLoader

type TagLoader struct {
	// DefaultTagName is the default tag name for struct fields to define
	// default values for a field. Example:
	//
	//   // Field's default value is "koding".
	//   Name string `default:"koding"`
	//
	// The default value is "default" if it's not set explicitly.
	DefaultTagName string
}

TagLoader satisfies the loader interface. It parses a struct's field tags and populates the each field with that given tag.

func (*TagLoader) Load

func (t *TagLoader) Load(s interface{}) error

type Validator

type Validator interface {
	// Validate validates the config struct
	Validate(s interface{}) error
}

Validator validates the config against any predefined rules, those predefined rules should be given to this package. The implementer will be responsible for the logic.

func MultiValidator

func MultiValidator(validators ...Validator) Validator

MultiValidator accepts variadic validators and satisfies Validator interface.

type YAMLLoader

type YAMLLoader struct {
	Path   string
	Reader io.Reader
}

YAMLLoader satisifies the loader interface. It loads the configuration from the given yaml file.

Example
// Our struct which is used for configuration
type ServerConfig struct {
	Name     string
	Port     int
	Enabled  bool
	Users    []string
	Postgres Postgres
}

// Instantiate loader
l := &YAMLLoader{Path: testYAML}

s := &ServerConfig{}
err := l.Load(s)
if err != nil {
	panic(err)
}

fmt.Println("Host-->", s.Name)
fmt.Println("Users-->", s.Users)
Output:

Host--> koding
Users--> [ankara istanbul]

func (*YAMLLoader) Load

func (y *YAMLLoader) Load(s interface{}) error

Load loads the source into the config defined by struct s. Defaults to using the Reader if provided, otherwise tries to read from the file

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL