configr

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2015 License: MIT Imports: 12 Imported by: 0

README

Build Status Coverage Status GoDoc

configr

Configr provides an abstraction above configuration sources, allowing you to use a single interface to expect and get all your configuration values.

Features:

  • Single interface for configuration values: Simple API (Get(), String(), Bool()...)
  • Extendable config sources: Load config from a file, database, environmental variables or any source you can get data from
  • Multiple source support: Add as many sources as you can manage, FILO merge strategy employed (first source added has highest priority)
  • Nested Key Support: production.payment_gateway.public_key production.payment_gateway.private_key
  • Value validation support: Any matching key from every source is validated by your custom validators
  • Required keys support: Ensure keys exist after parsing, otherwise error out
  • Blank config generator: Register as many keys as you need and use the blank config generator
  • Custom blank config encoder support: Implement an encoder for any data format and have a blank config generated in it
  • Type conversion support: Your config has string "5" but you want an int 5? No problem
  • Comes pre-baked with JSON and TOML file support

Built for a project at HomeMade Digital, configrs primary goal was to eliminate user error when deploying projects with heavy configuration needs. The inclusion of required key support, value validators, descriptions and blank config generator allowed us to reduce pain for seperated client ops teams when deploying our apps. Our secondary goal was flexible configuration sources be it pulling from Mongo Document, DynamoDB Table, JSON or TOML files.

Example

Simple JSON File

Pre register some keys to expect from your configuration sources (typically via init() for small projects, or via your own object initiation system for larger projects):

	configr.RequireKey("email.fromAddress", "Email from address")
	configr.RequireKey("email.subject", "Email subject")
	configr.RegisterKey("email.retryOnFail", "Retry sending email if it fails", false)
	configr.RegisterKey("email.maxRetries", "How many times to retry email resending", 3)

Create some configuration:

{
	"email": {
		"fromAddress": "my@email.com",
		"subject": "A Subject",
		"retryOnFail": true,
		"maxRetries": 5
	}
}

Add a source:

	configr.AddSource(configr.NewFileSource("/tmp/config.json"))

Parse your config:

	if err := configr.Parse(); err != nil {
		...
	}

And use at your own leisure:

	fromAddress, err := configr.String("email.fromAddress")
	if err != nil {
		...
	}

More examples can be found in the examples/ dir.

TODO:

  • Concurrent safety, particularly in multi Parse()'ing systems and when adding sources (will allow for hot reloads)
  • FileSource needs to be refactored to reduce dependency needs, something similar to sql package with a central register and blank importing the flavour you need

Documentation

Overview

Configr provides an abstraction above configuration sources, allowing you to use a single interface to get all your configuration values

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrKeyNotFound          = errors.New("configr: Key not found")
	ErrParseHasntBeenCalled = errors.New("configr: Trying to get values before calling Parse()")
	ErrNoRegisteredValues   = errors.New("configr: No registered values to generate")
)
View Source
var (
	SupportedFileExtensions = []string{"json", "toml"}
	ErrUnknownEncoding      = errors.New("configr: Unable to determine file encoding, please set manually")
)

Functions

func AddSource

func AddSource(p Source)

AddSource registers Sources with the Configr instance to Unmarshal() when Parse() is called. Sources are parsed in a FILO order, meaning the first source added is considered the highest priority, and any keys from lower priority sources that are present in a higher will be overwritten

func Bool

func Bool(key string) (bool, error)

Bool wraps Get() and will attempt to cast the resulting value to a bool or error

func Float64

func Float64(key string) (float64, error)

Float64 wraps Get() and will attempt to cast the resulting value to a float64 or error

func GenerateBlank

func GenerateBlank(e Encoder) ([]byte, error)

GenerateBlank generates a 'blank' configuration using the passed Encoder, it will honour nested keys, use default values where possible and when not fall back to placing the description as the value.

func Get

func Get(key string) (interface{}, error)

Get can only be called after a Parse() has been done. Keys support the nested notation format:

"user.age.month"

If a key is not found but has been registered with a default, the default will be returned

func Int

func Int(key string) (int, error)

Int wraps Get() and will attempt to cast the resulting value to a int or error

func MustParse

func MustParse()

MustParse wraps Parse() and will panic if there are any resulting errors

func Parse

func Parse() error

Parse calls Unmarshal on all registered sources, and caches the subsequent key/value's. Additional calls to Parse can be made to add additional config from sources.

Sources are called in a FILO order, meaning the first source added is considered the highest priority, any keys set from lower priority sources found in higher priority will be overwritten.

func Parsed

func Parsed() bool

Parsed lets the caller know if a Parse() call has been made or not

func RegisterKey

func RegisterKey(name, description string, defaultVal interface{}, validators ...Validator)

RegisterKey registers a configuration key (name) along with a description of what the configuration key is for, a default value and optional validators

name supports nested notation in the form of '.' delimitered keys (unless changed) e.g.

"user.age.month"

func RequireKey

func RequireKey(name, description string, validators ...Validator)

RequireValue wraps the RegisterValue() call but upon parsing sources, if the configuration key (name) is not found, Parse() will return a ErrRequiredValuesMissing error

func SetConfigr

func SetConfigr(c *Configr)

func String

func String(key string) (string, error)

String wraps Get() and will attempt to cast the resulting value to a string or error

Types

type Config

type Config interface {
	Parse() error
	Parsed() bool
	MustParse()

	Get(string) (interface{}, error)

	String(string) (string, error)
	Bool(string) (bool, error)
	Int(string) (int, error)
	Float64(string) (float64, error)
}

type Configr

type Configr struct {
	// contains filtered or unexported fields
}

func GetConfigr

func GetConfigr() *Configr

func New

func New() *Configr

func (*Configr) AddSource

func (c *Configr) AddSource(p Source)

func (*Configr) Bool

func (c *Configr) Bool(key string) (bool, error)

func (*Configr) Float64

func (c *Configr) Float64(key string) (float64, error)

func (*Configr) GenerateBlank

func (c *Configr) GenerateBlank(e Encoder) ([]byte, error)

func (*Configr) Get

func (c *Configr) Get(key string) (interface{}, error)

func (*Configr) Int

func (c *Configr) Int(key string) (int, error)

func (*Configr) MustParse

func (c *Configr) MustParse()

func (*Configr) Parse

func (c *Configr) Parse() error

func (*Configr) Parsed

func (c *Configr) Parsed() bool

func (*Configr) RegisterKey

func (c *Configr) RegisterKey(name, description string, defaultVal interface{}, validators ...Validator)

func (*Configr) RequireKey

func (c *Configr) RequireKey(name, description string, validators ...Validator)

func (*Configr) SetDescriptionWrapper

func (c *Configr) SetDescriptionWrapper(wrapper string)

func (*Configr) SetIsCaseSensitive

func (c *Configr) SetIsCaseSensitive(isCaseSensitive bool)

func (*Configr) SetKeyPathDelimeter

func (c *Configr) SetKeyPathDelimeter(delimeter string)

func (*Configr) String

func (c *Configr) String(key string) (string, error)

type Encoder

type Encoder interface {
	Marshal(interface{}) ([]byte, error)
}

Encoder would be used to encode registered and required values (along with their defaults or descriptions) into bytes.

type Encoding

type Encoding int
const (
	Unknown Encoding = iota - 1
	JSON
	TOML
)

type ErrRequiredKeysMissing

type ErrRequiredKeysMissing []string

func (ErrRequiredKeysMissing) Error

func (e ErrRequiredKeysMissing) Error() string

type FileSource

type FileSource struct {
	// contains filtered or unexported fields
}

func NewFileSource

func NewFileSource(filePath string) *FileSource

func (*FileSource) FilePath

func (f *FileSource) FilePath() string

func (*FileSource) Marshal

func (f *FileSource) Marshal(v interface{}) ([]byte, error)

func (*FileSource) SetEncoding

func (f *FileSource) SetEncoding(encoding Encoding)

SetEncoding allows the caller to override the infered file encoding format

func (*FileSource) SetFilePath

func (f *FileSource) SetFilePath(path string)

SetFilePath sets the file path of the configuration file and try to determine the encoding of the file using its extension. See SupportedFileExtensions for a list of supported extensions

func (*FileSource) Unmarshal

func (f *FileSource) Unmarshal() (map[string]interface{}, error)

type Manager

type Manager interface {
	RegisterKey(string, string, interface{}, ...Validator)
	RequireKey(string, string, ...Validator)

	AddSource(Source)

	GenerateBlank(Encoder) ([]byte, error)
	SetIsCaseSensitive(bool)
}

type Source

type Source interface {
	Unmarshal() (map[string]interface{}, error)
}

Source is a source of configuration keys and values, calling unmarshal should return a map[string]interface{} of all key/value pairs (nesting is supported) with multiple types.

type SourceAdapter

type SourceAdapter func() (map[string]interface{}, error)

func (SourceAdapter) Unmarshal

func (f SourceAdapter) Unmarshal() (map[string]interface{}, error)

type Validator

type Validator func(interface{}) error

Validator is a validation function which would be coupled with a configuration key, anytime the config key is found in a Source it's value is validated.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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