ucfg

package module
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2018 License: Apache-2.0 Imports: 17 Imported by: 0

README

Build Status Go Report Card

ucfg - Universal Configuration

ucfg is a Golang library to handle yaml and json configuration files in your Golang project. It was developed for the libbeat framework and used by all beats.

API Documentation

The full API Documentation can be found here.

Examples

A few examples on how ucfg can be used. All examples below assume, that the following packages are imported:

import (
	"github.com/elastic/go-ucfg"
	"github.com/elastic/go-ucfg/yaml"
)
Dot notations

ufcg allows you to load yaml configuration files using dots instead of indentation. For example instead of having:

config:
  user: name

with ucfg you can write:

config.user: name

This makes configurations easier and simpler.

To load such a config file in Golang, use the following command:

config, err := yaml.NewConfigWithFile(path, ucfg.PathSep("."))
Validation and Defaults

ucfg allows to automatically validate fields and set defaults for fields in case they are not defined.

// Defines struct to read config from
type ExampleConfig struct {
    Counter  string 	`config:"counter" validate:"min=0, max=9"`
}

// Defines default config option
var (
    defaultConfig = ExampleConfig{
		    Counter: 4,
    }
)

func main() {
    appConfig := defaultConfig // copy default config so it's not overwritten
    config, err := yaml.NewConfigWithFile(path, ucfg.PathSep("."))
    if err != nil {
        fmt.Fprintln(err)
        os.Exit(1)
    }
    err = config.Unpack(&appConfig)
    if err != nil {
        fmt.Fprintln(err)
        os.Exit(1)
    }
}

The above uses Counter as the config variable. ucfg assures that the value is between 0 and 9 and will return an error if this is not the case. In addition, if the value is not set, it will default to 4.

Requirements

ucfg has the following requirements:

  • Golang 1.7+

Documentation

Overview

Package ucfg provides a common representation for hierarchical configurations.

The common representation provided by the Config type can be used with different configuration file formats like XML, JSON, HSJSON, YAML, or TOML.

Config provides a low level and a high level interface for reading settings with additional features like custom unpackers, validation and capturing sub-configurations for deferred interpretation, lazy intra-configuration variable expansion, and OS environment variable expansion.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMissing = errors.New("missing field")

	ErrCyclicReference = errors.New("cyclic reference detected")

	ErrDuplicateValidator = errors.New("validator already registered")

	ErrTypeNoArray = errors.New("field is no array")

	ErrTypeMismatch = errors.New("type mismatch")

	ErrKeyTypeNotString = errors.New("key must be a string")

	ErrIndexOutOfRange = errors.New("out of range index")

	ErrPointerRequired = errors.New("pointer required for unpacking configurations")

	ErrArraySizeMistach = errors.New("Array size mismatch")

	ErrExpectedObject = errors.New("expected object")

	ErrNilConfig = errors.New("config is nil")

	ErrNilValue = errors.New("nil value is invalid")

	ErrTODO = errors.New("TODO - implement me")

	ErrDuplicateKey = errors.New("duplicate key")

	ErrOverflow = errors.New("integer overflow")

	ErrNegative = errors.New("negative value")

	ErrZeroValue = errors.New("zero value")

	ErrRequired = errors.New("missing required field")

	ErrEmpty = errors.New("empty field")

	ErrUUIDGeneration = errors.New("failed to generate UUID for ID")
)

Error Reasons

View Source
var (
	ErrConfig         = errors.New("Configuration error")
	ErrImplementation = errors.New("Implementation error")
	ErrUnknown        = errors.New("Unspecified")
)

Error Classes

View Source
var (
	// ReplacesValues option configures all merging and unpacking operations to
	// replace old dictionaries and arrays while merging. Value merging can be
	// overwritten in unpack by using struct tags.
	ReplaceValues = makeOptValueHandling(cfgReplaceValue)

	// AppendValues option configures all merging and unpacking operations to
	// merge dictionaries and append arrays to existing arrays while merging.
	// Value merging can be overwritten in unpack by using struct tags.
	AppendValues = makeOptValueHandling(cfgArrAppend)

	// PrependValues option configures all merging and unpacking operations to
	// merge dictionaries and prepend arrays to existing arrays while merging.
	// Value merging can be overwritten in unpack by using struct tags.
	PrependValues = makeOptValueHandling(cfgArrPrepend)
)

Functions

func NewFieldSet added in v0.5.0

func NewFieldSet(parent *fieldSet) *fieldSet

func RegisterValidator added in v0.3.0

func RegisterValidator(name string, cb ValidatorCallback) error

RegisterValidator adds a new validator option to the "validate" struct tag. The callback will be executed when unpacking into a struct field.

Types

type BoolUnpacker added in v0.4.3

type BoolUnpacker interface {
	Unpack(b bool) error
}

BoolUnpacker interface specializes the Unpacker interface by casting values to bool when calling Unpack.

type Config

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

Config object to store hierarchical configurations into. Config can be both a dictionary and a list holding primitive values. Primitive values can be booleans, integers, float point numbers and strings.

Config provides a low level interface for setting and getting settings via SetBool, SetInt, SetUing, SetFloat, SetString, SetChild, Bool, Int, Uint, Float, String, and Child.

A more user-friendly high level interface is provided via Unpack and Merge.

func MustNewFrom added in v0.6.0

func MustNewFrom(from interface{}, opts ...Option) *Config

NustNewFrom creates a new config object normalizing and copying from into the new Config object. MustNewFrom uses Merge to copy from.

MustNewFrom supports the options: PathSep, MetaData, StructTag, VarExp

func New

func New() *Config

New creates a new empty Config object.

func NewFrom

func NewFrom(from interface{}, opts ...Option) (*Config, error)

NewFrom creates a new config object normalizing and copying from into the new Config object. NewFrom uses Merge to copy from.

NewFrom supports the options: PathSep, MetaData, StructTag, VarExp

func (*Config) Bool

func (c *Config) Bool(name string, idx int, opts ...Option) (bool, error)

Bool reads a boolean setting returning an error if the setting has no boolean value.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

Bool supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) Child

func (c *Config) Child(name string, idx int, opts ...Option) (*Config, error)

Child returns a child configuration or an error if the setting requested is a primitive value only.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

Child supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) CountField

func (c *Config) CountField(name string, opts ...Option) (int, error)

CountField returns number of entries in a table or 1 if entry is a primitive value. Primitives settings can be handled like a list with 1 entry.

If name is empty, the total number of top-level settings is returned.

CountField supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) FlattenedKeys added in v0.5.0

func (c *Config) FlattenedKeys(opts ...Option) []string

FlattenedKeys return a sorted flattened views of the set keys in the configuration

func (*Config) Float

func (c *Config) Float(name string, idx int, opts ...Option) (float64, error)

Float reads a float64 value returning an error if the setting is not a float value or the primitive value is not convertible to float.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

Float supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) GetFields

func (c *Config) GetFields() []string

GetFields returns a list of all top-level named keys in c.

func (*Config) HasField

func (c *Config) HasField(name string) bool

HasField checks if c has a top-level named key name.

func (*Config) Int

func (c *Config) Int(name string, idx int, opts ...Option) (int64, error)

Int reads an int64 value returning an error if the setting is not integer value, the primitive value is not convertible to int or a conversion would create an integer overflow.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

Int supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) IsArray added in v0.3.3

func (c *Config) IsArray() bool

IsArray checks if c has index only accessible settings.

func (*Config) IsDict added in v0.3.3

func (c *Config) IsDict() bool

IsDict checks if c has named keys.

func (*Config) Merge

func (c *Config) Merge(from interface{}, options ...Option) error

Merge a map, a slice, a struct or another Config object into c.

Merge traverses the value from recursively copying all values into a hierarchy of Config objects plus primitives into c.

Merge supports the options: PathSep, MetaData, StructTag, VarExp, ReplaceValues, AppendValues, PrependValues

Merge uses the type-dependent default encodings:

  • Boolean values are encoded as booleans.
  • Integer are encoded as int64 values, unsigned integer values as uint64 and floats as float64 values.
  • Strings are copied into string values. If the VarExp is set, string fields will be parsed into variable expansion expressions. The expression can reference any other setting by absolute name.
  • Array and slices are copied into new Config objects with index accessors only.
  • Struct values and maps with key type string are encoded as Config objects with named field accessors.
  • Config objects will be copied and added to the current hierarchy.

The `config` struct tag (configurable via StructTag option) can be used to set the field name and enable additional merging settings per field:

// field appears in Config as key "myName"
Field int `config:"myName"`

// field appears in sub-Config "mySub" as key "myName" (requires PathSep("."))
Field int `config:"mySub.myName"`

// field is processed as if keys are part of outer struct (type can be a
// struct, a slice, an array, a map or of type *Config)
Field map[string]interface{} `config:",inline"`

// field is ignored by Merge
Field string `config:",ignore"`

Returns an error if merging fails to normalize and validate the from value. If duplicate setting names are detected in the input, merging fails as well.

Config cannot represent cyclic structures and Merge does not handle them well. Passing cyclic structures to Merge will result in an infinite recursive loop.

func (*Config) Parent added in v0.3.0

func (c *Config) Parent() *Config

Parent returns the parent configuration or nil if c is already a root Configuration.

func (*Config) Path added in v0.3.0

func (c *Config) Path(sep string) string

Path gets the absolute path of c separated by sep. If c is a root-Config an empty string will be returned.

func (*Config) PathOf added in v0.3.0

func (c *Config) PathOf(field, sep string) string

PathOf gets the absolute path of a potential setting field in c with name separated by sep.

func (*Config) SetBool

func (c *Config) SetBool(name string, idx int, value bool, opts ...Option) error

SetBool sets a boolean primitive value. An error is returned if the new name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetBool supports the options: PathSep, MetaData

func (*Config) SetChild

func (c *Config) SetChild(name string, idx int, value *Config, opts ...Option) error

SetChild adds a sub-configuration. An error is returned if the name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetChild supports the options: PathSep, MetaData

func (*Config) SetFloat

func (c *Config) SetFloat(name string, idx int, value float64, opts ...Option) error

SetFloat sets an floating point primitive value. An error is returned if the name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetFloat supports the options: PathSep, MetaData

func (*Config) SetInt

func (c *Config) SetInt(name string, idx int, value int64, opts ...Option) error

SetInt sets an integer primitive value. An error is returned if the new name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetInt supports the options: PathSep, MetaData

func (*Config) SetString

func (c *Config) SetString(name string, idx int, value string, opts ...Option) error

SetString sets string value. An error is returned if the name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetString supports the options: PathSep, MetaData

func (*Config) SetUint added in v0.3.0

func (c *Config) SetUint(name string, idx int, value uint64, opts ...Option) error

SetUint sets an unsigned integer primitive value. An error is returned if the name is invalid.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

SetUint supports the options: PathSep, MetaData

func (*Config) String

func (c *Config) String(name string, idx int, opts ...Option) (string, error)

Strings reads a string setting returning an error if the setting has no string or primitive value convertible to string.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

String supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) Uint added in v0.3.0

func (c *Config) Uint(name string, idx int, opts ...Option) (uint64, error)

Uint reads an uint64 value returning an error if the setting is not unsigned value, the primitive value is not convertible to uint64 or a conversion would create an integer overflow.

The setting path is constructed from name and idx. If name is set and idx is -1, only the name is used to access the setting by name. If name is empty, idx must be >= 0, assuming the Config is a list. If both name and idx are set, the name must point to a list. The number of entries in a named list can be read using CountField.

Uint supports the options: PathSep, Env, Resolve, ResolveEnv

func (*Config) Unpack

func (c *Config) Unpack(to interface{}, options ...Option) error

Unpack unpacks c into a struct, a map, or a slice allocating maps, slices, and pointers as necessary.

Unpack supports the options: PathSep, StructTag, ValidatorTag, Env, Resolve, ResolveEnv, ReplaceValues, AppendValues, PrependValues.

When unpacking into a value, Unpack first will try to call Unpack if the value implements the Unpacker interface. Otherwise, Unpack tries to convert the internal value into the target type:

# Primitive types

bool: requires setting of type bool or string which parses into a
   boolean value (true, false, on, off)
int(8, 16, 32, 64): requires any number type convertible to int or a string
    parsing to int. Fails if the target value would overflow.
uint(8, 16, 32, 64): requires any number type convertible to int or a string
     parsing to int. Fails if the target value is negative or would overflow.
float(32, 64): requires any number type convertible to float or a string
     parsing to float. Fails if the target value is negative or would overflow.
string: requires any primitive value which is serialized into a string.

# Special types:

time.Duration: requires a number setting converted to seconds or a string
     parsed into time.Duration via time.ParseDuration.
*regexp.Regexp: requires a string being compiled into a regular expression
     using regexp.Compile.
*Config: requires a Config object to be stored by pointer into the target
     value. Can be used to capture a sub-Config without interpreting
     the settings yet.

 # Arrays/Slices:

Requires a Config object with indexed entries. Named entries will not be
unpacked into the Array/Slice. Primitive values will be handled like arrays
of length 1.

# Map

Requires a Config object with all named top-level entries being unpacked into
the map.

# Struct

Requires a Config object. All named values in the Config object will be unpacked
into the struct its fields, if the name is available in the struct.
A field its name is set using the `config` struct tag (configured by StructTag)
If tag is missing or no field name is configured in the tag, the field name
itself will be used.
If the tag sets the `,ignore` flag, the field will not be overwritten.
If the tag sets the `,inline` or `,squash` flag, Unpack will apply the current
configuration namespace to the fields.
If the tag option `replace` is configured, arrays and *ucfg.Config
convertible fields are replaced by the new values.
If the tag options `append` or `prepend` is used, arrays will be merged by
appending/prepending the new array contents.
The struct tag options `replace`, `append`, and `prepend` overwrites the
global value merging strategy (e.g. ReplaceValues, AppendValues, ...) for all sub-fields.

Fields available in a struct or a map, but not in the Config object, will not be touched. Default values should be set in the target value before calling Unpack.

Type aliases like "type myTypeAlias T" are unpacked using Unpack if the alias implements the Unpacker interface. Otherwise unpacking rules for type T will be used.

When unpacking a value, the Validate method will be called if the value implements the Validator interface. Unpacking a struct field the validator options will be applied to the unpacked value as well.

Struct field validators are set using the `validate` tag (configurable by ValidatorTag). Default validators options are:

required: check value is set and not empty
nonzero: check numeric value != 0 or string/slice not being empty
positive: check numeric value >= 0
min=<value>: check numeric value >= <value>. If target type is time.Duration,
     <value> can be a duration.
max=<value>: check numeric value <= <value>. If target type is time.Duration,
   <value> can be a duration.

If a config value is not the convertible to the target type, or overflows the target type, Unpack will abort immediately and return the appropriate error.

If validator tags or validation provided by Validate or Unmarshal fails, Unpack will abort immediately and return the validate error.

When unpacking into an interface{} value, Unpack will store a value of one of these types in the value:

bool for boolean values
int64 for signed integer values
uint64 for unsigned integer values
float64 for floating point values
string for string values
[]interface{} for list-only Config objects
map[string]interface{} for Config objects
nil for pointers if key has a nil value

type ConfigUnpacker added in v0.4.3

type ConfigUnpacker interface {
	Unpack(c *Config) error
}

ConfigUnpacker interface specializes the Unpacker interface by passing the the *Config object directly instead of transforming the *Config object into map[string]interface{}.

type Error added in v0.3.0

type Error interface {
	error

	// error class, one of ErrConfig, ErrImplementation, ErrUnknown
	Class() error

	// The internal reason error code like ErrMissing, ErrRequired,
	// ErrTypeMismatch and others.
	Reason() error

	// The error message.
	Message() string

	// [optional] path of config element error occurred for
	Path() string

	// [optional] stack trace
	Trace() string
}

Error type returned by all public functions in go-ucfg.

type FloatUnpacker added in v0.4.3

type FloatUnpacker interface {
	Unpack(f float64) error
}

FloatUnpacker interface specializes the Unpacker interface by casting values to float64 when calling Unpack.

type IntUnpacker added in v0.4.3

type IntUnpacker interface {
	Unpack(i int64) error
}

IntUnpacker interface specializes the Unpacker interface by casting values to int64 when calling Unpack.

type Meta added in v0.3.0

type Meta struct {
	Source string
}

Meta holds additional meta data per config value.

type Option

type Option func(*options)

Option type implementing additional options to be passed to go-ucfg library functions.

var ResolveEnv Option = doResolveEnv

ResolveEnv option adds a look up callback looking up values in the available OS environment variables.

var VarExp Option = doVarExp

VarExp option enables support for variable expansion. Resolve and Env options will only be effective if VarExp is set.

func Env added in v0.3.0

func Env(e *Config) Option

Env option adds another configuration for variable expansion to be used, if the path to look up does not exist in the actual configuration. Env can be used multiple times in order to add more lookup environments.

func MetaData added in v0.3.0

func MetaData(meta Meta) Option

MetaData option passes additional metadata (currently only source of the configuration) to be stored internally (e.g. for error reporting).

func PathSep

func PathSep(sep string) Option

PathSep sets the path separator used to split up names into a tree like hierarchy. If PathSep is not set, field names will not be split.

func Resolve added in v0.3.0

func Resolve(fn func(name string) (string, error)) Option

Resolve option adds a callback used by variable name expansion. The callback will be called if a variable can not be resolved from within the actual configuration or any of its environments.

func StructTag

func StructTag(tag string) Option

StructTag option sets the struct tag name to use for looking up field names and options in `Unpack` and `Merge`. The default struct tag in `config`.

func ValidatorTag added in v0.3.0

func ValidatorTag(tag string) Option

ValidatorTag option sets the struct tag name used to set validators on struct fields in `Unpack`. The default struct tag in `validate`.

type StringUnpacker added in v0.4.3

type StringUnpacker interface {
	Unpack(s string) error
}

StringUnpacker interface specializes the Unpacker interface by casting values to string when calling Unpack.

type UintUnpacker added in v0.4.3

type UintUnpacker interface {
	Unpack(u uint64) error
}

UintUnpacker interface specializes the Unpacker interface by casting values to uint64 when calling Unpack.

type Unpacker added in v0.3.0

type Unpacker interface {
	// Unpack is called if a setting of field has a type implementing Unpacker.
	//
	// The interface{} value passed to Unpack can be of type: bool, int64, uint64,
	// float64, string, []interface{} or map[string]interface{}.
	Unpack(interface{}) error
}

Unpacker type used by Unpack to allow types to implement custom configuration unpacking.

type Validator added in v0.3.0

type Validator interface {
	Validate() error
}

Validator interface provides additional validation support to Unpack. The Validate method will be executed for any type passed directly or indirectly to Unpack.

If Validate fails with an error message, Unpack will add some context - like setting being accessed and file setting was read from - to the error message before returning the actual error.

type ValidatorCallback added in v0.3.0

type ValidatorCallback func(interface{}, string) error

ValidatorCallback is the type of optional validator tags to be registered via RegisterValidator.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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