flexconfig

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2018 License: Apache-2.0 Imports: 13 Imported by: 0

README

Go Flexible Configuration

Go package providing a uniform interface to configuration, independent of how or where that configuration is defined.

API Reference Go Report Card

Installation

Install:

go get github.com/zadoo/flexconfig

Import:

import "github.com/zadoo/flexconfig"

Test:

ETCDCTL_ENDPOINTS=0.0.0.0:2379 go test

Change 0.0.0.0 to the IP address of your ectd server, or expect 5 test failures if you do not intend to use an etcd configuration store.

Quickstart

package main

import (
	"fmt"
	"log"

	"github.com/zadoo/flexconfig"
)

func main() {
	// Connect to the etcd running on the local machine and use a prefix
	// of "/example/" for all property keys accessed by this program.
	cfgstore, err := flexconfig.NewFlexConfigStore(
		flexconfig.FlexConfigStoreEtcd,
		[]string{"127.0.0.1:2379"},
		"/example")
	if err != nil {
		log.Print("Failed connecting to config store: ", err)
	}

	// Create Config. Search for config files for the application "example".
	// Convert all environment variables beginning with "EXAMPLE_" to
	// properties. Use a configuration store. Also, all command line
	// variables of the form --<name>=<value> set properties (e.g.
	// --example.log.filepath=/var/log/myapp.log).
	cfg, err := flexconfig.NewFlexibleConfiguration(
		flexconfig.ConfigurationParameters{
			ApplicationName:             "example",
			EnvironmentVariablePrefixes: []string{"EXAMPLE_"},
			ConfigurationStore:          cfgstore,
		})
	if err != nil {
		log.Fatal("Failed creating configuration: ", err)
	}

	logPath := cfg.Get("log.path")
	fmt.Printf("%s = %s\n", "log.path", logPath)

	fooPluginName := cfg.Get("example.plugins.foo.name")
	fmt.Printf("%s = %s\n", "example.plugins.foo.name", fooPluginName)
}

The program can be invoked as follows (assuming it is called main.go):

EXAMPLE_PLUGINS_FOO_NAME=univeral.xyz go run main.go --log.path=/var/xyz/www.log

and it will print:

log.path = /var/xyz/www.log
example.plugins.foo.name = universal.xyz

Alternatively, create a directory named ".example" (this is the application name passed to NewFlexibleConfiguration), and add a file having a suffix of ".conf" (e.g. config.conf) to the directory with the following contents:

log:
  path: /var/xyz/www.log
example:
  plugins:
    foo:
      name: universal.xyz

and invoke it with no arguments or environment variables:

go run main.go

Experiment with a combination of file configuration values, environment variables and command line arguments to see the priority each source has in defining the configuration. Also, omit the application name, or array of environment variable prefixes to control which sources contribute to the final configuration.

If no instance of etcd is available, remove the code to connect to the FlexConfigStore and delete the line setting ConfigurationStore in the request to create a new Config.

Copyright (C) 2018 The flexconfig authors.

flexconfig package released under Apache 2.0 License. See LICENSE for details.

Documentation

Overview

Package flexconfig provides a uniform interface to retrieve configuration properties, independent of how or where the properties are specified. Files, environment variables, command line arguments, and a configuration store can be used alone or in combination with each other to define the configuration for the application.

An application can retrieve and set property values using a key with a canonical form. The canonical form is all lowercase with hierarchical fields separated by dots. For example,

animal.bear.polar.habitat

Initialization of a configuration is done by an application near the beginning of its main function by calling NewFlexibleConfiguration. The application can specify several parameters about how and where configuration properties will be obtained from. Configuration sources include (in priority order, lowest to highest):

  • directories on the local file system
  • environment variables
  • command line arguments
  • configuration store

The static configuration sources (not including configuration store) are read from lowest priority to highest priority, creating configuration properties from data found in the sources. If the same canonical property key is set in a data source read later, its value will override a value from a data source read earlier.

Configuration directory names are derived from the ApplicationName in the ConfigurationParameters. A non-empty ApplicationName indicates that file-based properties will be searched for. Multiple directories are searched as described under ConfigurationParameters. The subset of files read in these directories is controlled by AcceptedFileSuffixes, where the suffix ".conf" is used if none are specified. The contents of the files may have formats that include JSON, YAML, and INI.

Hierarchical properties (multiple fields separated by dots) are defined by parsing JSON and YAML files. Arrays defined in these files result in property names that include fields consisting of digits. For example, the YAML file:

myapp:
  plugins:
    - name: foo
      loglevel: debug
    - name: bar
      server:
        address: 192.168.1.1

will result in the following properties in the configuration:

myapp.plugins.0.name
myapp.plugins.0.loglevel
myapp.plugins.1.name
myapp.plugins.1.server.address

Environment variables will be searched if EnvironmentVariablePrefixes includes non-empty members. The members specify prefixes for environment variable names. For instance, specifying a prefix of "SUN" will match both

SUNSHINE_DAILY
SUN_MICROSYSTEMS

whereas, specifying "SUN_" will only match

SUN_MICROSYSTEMS

Environment variable names are converted into the canonical form before storing in the configuration.

Command line arguments are checked for property definitions without the application needing to manage arguments beyond calling NewFlexibleConfiguration. Any argument beginning with a double dash (--) and being all lowercase is used to create configuration properties. Arguments are checked up to the point where all arguments have been read, or an argument consisting entirely of "--" is found. The argument name matches the canonical form for names while the value can be anything. For example, given the following commandline:

hello -v --smiley.face=true -n --happy.day -- --dont.check.sig=true "Hi!"

will result in the following properties being defined in the configuration:

smiley.face: true

Note, the '=' separating name and value is required with no intermediate spaces. Single or double quotes can enclose the value of a property.

Accessing the configuration to obtain property values will consult the configuration store first, if it has been configured. If this results in an error or an empty value, the in-memory configuration read from files, env vars, and the command line, is consulted.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrParmNameNotValid indicates the application name is either
	// missing or uses characters outside those accepted as property names.
	ErrParmNameNotValid = errors.New("Application name not valid")

	// ErrParmEnvPrefixNotValid indicates an environment prefix uses
	// characters outside those accepted as property names.
	ErrParmEnvPrefixNotValid = errors.New("Environment variable prefix not valid")
)
View Source
var (
	// ErrStoreUnsupportedType indicates that the value of
	// FlexConfigStoreType is not supported.
	ErrStoreUnsupportedType = errors.New("Unsupported FlexConfigStoreType")

	// ErrStoreKeyRequired indicates that the requested function requires a
	// property key as a parameter.
	ErrStoreKeyRequired = errors.New("Key is required")
)

Functions

func Exists

func Exists(key string) bool

Exists returns whether the specified key is present in the global configuration. If the global configuration does not exist (no call has been made to NewFlexibleConfiguration), an empty configuration is created. The configuration store, if set, is checked first. If not found in the configuration store or the store was not set, the key is retrieved from the memory store created from files, environment variables, and arguments.

func Get

func Get(key string) string

Get returns the value for the specified key from the global configuration. If the global configuration does not exist (no call has been made to NewFlexibleConfiguration), an empty configuration is created. The configuration store, if set, is checked first. If not found in the configuration store or the store was not set, the property value is retrieved from the memory store created from files, environment variables, and arguments.

func Set

func Set(key string, val string)

Set stores the key with value in the global configuration. If the global configuration does not exist (no call has been made to NewFlexibleConfiguration), an empty configuration is created. If they key already exists, its value will be overwritten. If the configuration store is set, the key with value will be stored in both the configuration store as well as the memory store. Otherwise, it will be stored only in the memory store.

Types

type Config

type Config interface {
	// Exists returns whether the specified key has a non empty value in
	// the configuration.
	Exists(key string) bool

	// Get returns the value of the specified property from the
	// configuration.
	Get(key string) string

	// Set creates or modifies the specified property with the specified
	// value.
	Set(key, val string)
}

Config is the interface used to interact with a FlexibleConfiguration and is returned by NewFlexibleConfiguration and GetConfiguration.

func GetConfiguration

func GetConfiguration() Config

GetConfiguration returns a previously initialized configuration. If there is no existing configuration, a new configuration will be created by calling NewFlexibleConfiguration with an empty ConfigurationParameters structure.

func NewFlexibleConfiguration

func NewFlexibleConfiguration(
	parameters ConfigurationParameters) (Config, error)

NewFlexibleConfiguration initializes and returns a new Configuration. The default Configuration is overwritten with this new Configuration.

type ConfigurationParameters

type ConfigurationParameters struct {
	ApplicationName             string
	EnvironmentVariablePrefixes []string
	AcceptedFileSuffixes        []string
	IniNamePrefix               string
	ConfigurationStore          FlexConfigStore
}

ConfigurationParameters specifies how a Config should be initialized.

ApplicationName specifies the name used to find directories that may contain configuration files. If ApplicationName is empty (this is the default), no search for configuration files is done. If ApplicationName has a value, directories are searched in the following order, where directories later in the list that define properties will override the same property found in a directory listed earlier in the list:

/usr/local/etc/<name>
/opt/etc/<name>
/etc/opt/<name>
/etc/<name>
$HOME/.<name>
./.<name>

where <name> is the value of ApplicationName.

EnvironmentVariablePrefixes is a list of prefixes used to determine which environment variables should be added to the configuration. Environment variable names have a canonical conversion to configuration property names: convert to all lower case and change all '_' to '.'. The default value for this field is nil, which means environment variables will not be included in the configuration.

AcceptedFileSuffixes indicates which files in the directories mentioned for ApplicationName will be read to find configuration properties. If AcceptedFileSuffixes is nil or empty, files with the suffix ".conf" will be read.

IniNamePrefix indicates the property name prefix that should be used for properties that are created from reading an INI file. The default is an empty string which will result in property names consisting of only the section and key names in the INI file.

ConfigurationStore is an interface to a configuration store. When it is non-nil all interactions with the configuration will consult with the configuration store before asking the in-memory store resulting from reading configuration files, environment variables, and command line parameters.

type FlexConfigStore

type FlexConfigStore interface {
	// Get returns a single configuration property value given the key
	// for the property.
	Get(key string) (string, error)

	// GetAll returns all properties in the FlexConfigStore having the
	// prefix used by the store.
	GetAll() ([]KeyValue, error)

	// Set creates or modifies the property indicated by key with the
	// specified value.
	Set(key, val string) error

	// Delete removes the specified property.
	Delete(key string) error

	// GetPrefix returns the "namespace" prefix specified when the
	// FlexConfigStore was created by calling NewFlexConfigStore.
	GetPrefix() string
}

FlexConfigStore describes the interface to a flexible configuration store. A Config optionally uses a FlexConfigStore to provide dynamic configuration properties.

func NewFlexConfigStore

func NewFlexConfigStore(
	storeType FlexConfigStoreType,
	endpoints []string,
	prefix string) (FlexConfigStore, error)

NewFlexConfigStore creates a FlexConfigStore instance for the specified store type. Supported store types include: etcd. The store type may require passing zero or more endpoints for the store in order to instantiate it, as well as a prefix used to differentiate from other uses of the store.

type FlexConfigStoreType

type FlexConfigStoreType int

FlexConfigStoreType is an enumerated type defining the type of a FlexConfigStore.

const (
	// FlexConfigStoreUnknown is a value of FlexConfigStoreType
	// indicating the type of configuration store is unknown.
	FlexConfigStoreUnknown FlexConfigStoreType = iota

	// FlexConfigStoreEtcd is a value of FlexConfigStoreType
	// indicating the type of configuration store is etcd.
	FlexConfigStoreEtcd
)

func (FlexConfigStoreType) String

func (fcst FlexConfigStoreType) String() string

String returns the string representation of the FlexConfigStoreType.

type KeyValue

type KeyValue struct {
	Key   string
	Value string
}

KeyValue describes a property key and value.

Jump to

Keyboard shortcuts

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