konfig

package module
v0.4.4 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2020 License: ISC Imports: 16 Imported by: 2

README

Go Doc Build Status Go Report Card Test Coverage Maintainability

konfig

This is a very minimal and unopinionated utility for reading configuration values in Go applications based on The 12-Factor App.

The idea is that you just define a struct with fields, types, and defaults, then you just use this library to read and populate the values for fields of your struct from either command-line flags, environment variables, or configuration files. It can also watch for new values read from configuration files and notify subscribers.

This library does not use flag package for parsing flags, so you can still parse your flags separately.

Quick Start

package main

import (
  "fmt"
  "net/url"
  "time"

  "github.com/moorara/konfig"
)

var config = struct {
  Enabled   bool
  LogLevel  string
  Timeout   time.Duration
  Address   url.URL
  Endpoints []string
} {
  Enabled:  true,   // default
  LogLevel: "info", // default
}

func main() {
  konfig.Pick(&config)
  fmt.Printf("%+v\n", config)
}

Examples & Demos

You can find examples of using konfig alongside some demos here.

Documentation

The precedence of sources for reading values is as follows:

  1. command-line flags
  2. environment variables
  3. configuration files
  4. default values (set when creating the instance)

You can pass the configuration values with flags using any of the syntaxes below:

main  -enabled  -log.level info  -timeout 30s  -address http://localhost:8080  -endpoints url1,url2,url3
main  -enabled  -log.level=info  -timeout=30s  -address=http://localhost:8080  -endpoints=url1,url2,url3
main --enabled --log.level info --timeout 30s --address http://localhost:8080 --endpoints url1,url2,url3
main --enabled --log.level=info --timeout=30s --address=http://localhost:8080 --endpoints=url1,url2,url3

You can pass the configuration values using environment variables as follows:

export ENABLED=true
export LOG_LEVEL=info
export TIMEOUT=30s
export ADDRESS=http://localhost:8080
export ENDPOINTS=url1,url2,url3

You can also write the configuration values in files (or mount your configuration values and secrets as files) and pass the paths to the files using environment variables:

export ENABLED_FILE=...
export LOG_LEVEL_FILE=...
export TIMEOUT_FILE=...
export ADDRESS_FILE=...
export ENDPOINTS_FILE=...
Supported Types
  • string, *string, []string
  • bool, *bool, []bool
  • float32, float64
  • *float32, *float64
  • []float32, []float64
  • int, int8, int16, int32, int64
  • *int, *int8, *int16, *int32, *int64
  • []int, []int8, []int16, []int32, []int64
  • uint, uint8, uint16, uint32, uint64
  • *uint, *uint8, *uint16, *uint32, *uint64
  • []uint, []uint8, []uint16, []uint32, []uint64
  • url.URL, *url.URL, []url.URL
  • regexp.Regexp, *regexp.Regexp, []regexp.Regexp
  • time.Duration, *time.Duration, []time.Duration

The supported syntax for Regexp is POSIX Regular Expressions.

Skipping

If you want to skip a source for reading values, use - as follows:

type Config struct {
  GithubToken string `env:"-" fileenv:"-"`
}

In the example above, GithubToken can only be set using github.token command-line flag.

Customization

You can use Go struct tags to customize the name of expected command-line flags or environment variables.

type Config struct {
  Database string `flag:"config.database" env:"CONFIG_DATABASE" fileenv:"CONFIG_DATABASE_FILE_PATH"`
}

In the example above, Database will be read from either:

  1. The command-line flag config.databas
  2. The environment variable CONFIG_DATABASE
  3. The file specified by environment variable CONFIG_DATABASE_FILE_PATH
  4. The default value set on struct instance
Using flag Package

konfig plays nice with flag package since it does NOT use flag package for parsing command-line flags. That means you can define, parse, and use your own flags using built-in flag package.

If you use flag package, konfig will also add the command-line flags it is expecting. Here is an example:

package main

import (
  "flag"
  "time"

  "github.com/moorara/konfig"
)

var config = struct {
  Enabled   bool
  LogLevel  string
} {
  Enabled:  true,   // default
  LogLevel: "info", // default
}

func main() {
  konfig.Pick(&config)
  flag.Parse()
}

If you run this example with -help or --help flag, you will see -enabled and -log.level flags are also added with descriptions!

Options

Options are helpers for specific situations and setups. You can pass a list of options to Pick and Watch methods. If you want to test or debug something and you don't want to make code changes, you can set options through environment variables as well.

Option Environment Variable Description
konfig.Debug() KONFIG_DEBUG Printing debugging information.
konfig.ListSep() KONFIG_LIST_SEP Specifying list separator for all fields with slice type.
konfig.SkipFlag() KONFIG_SKIP_FLAG Skipping command-line flags as a source for all fields.
konfig.SkipEnv() KONFIG_SKIP_ENV Skipping environment variables as a source for all fields .
konfig.SkipFileEnv() KONFIG_SKIP_FILE_ENV Skipping file environment variables (and configuration files) as a source for all fields.
konfig.PrefixFlag() KONFIG_PREFIX_FLAG Prefixing all flag names with a string.
konfig.PrefixEnv() KONFIG_PREFIX_ENV Prefixing all environment variable names with a string.
konfig.PrefixFileEnv() KONFIG_PREFIX_FILE_ENV Prefixing all file environment variable names with a string.
konfig.Telepresence() KONFIG_TELEPRESENCE Reading configuration files in a Telepresence environment.
Debugging

If for any reason the configuration values are not read as you expected, you can view the debugging logs. You can enable debugging logs either by using Debug option or by setting KONFIG_DEBUG environment variable. In both cases you need to specify a verbosity level for logs.

Level Descriptions
0 No logging (default).
1 Logging all errors.
2 Logging initialization information.
3 Logging information related to new values read from files.
4 Logging information related to notifying subscribers.
5 Logging information related to setting values of fields.
6 Logging miscellaneous information.
Watching Changes

konfig allows you to watch configuration files and dynamically update your configurations as your application is running.

When using Watch() method, your struct should have a sync.Mutex field on it for synchronization and preventing data races. You can find an example of using Watch() method here.

Here you will find a real-world example of using konfig.Watch() for dynamic configuration management and secret injection for Go applications running in Kubernetes.

Documentation

Overview

Package konfig is a minimal and unopinionated library for reading configuration values in Go applications based on The 12-Factor App (https://12factor.net/config).

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pick

func Pick(config interface{}, opts ...Option) error

Pick reads values for exported fields of a struct from either command-line flags, environment variables, or configuration files. Default values can also be specified. You should pass the pointer to a struct for config; otherwise you will get an error.

Example
package main

import (
	"fmt"
	"net/url"
	"time"

	"github.com/moorara/konfig"
)

func main() {
	// First, you need to define a struct.
	// Each field of the struct represents a configuration value.
	// Create an object from the struct with default values for its fields.
	var config = struct {
		LogLevel    string
		Environment string
		Region      string
		Timeout     time.Duration
		Replicas    []url.URL
	}{
		LogLevel:    "info",           // default
		Environment: "dev",            // default
		Region:      "local",          // default
		Timeout:     10 * time.Second, // default
	}

	// Second, pass the pointer to the struct object to the Pick method.
	// For each field, a value will be read either from flags, environment variables, or files.
	_ = konfig.Pick(&config)

	// Now, you can access the configuration values on the struct object.
	fmt.Printf("%+v\n", config)
}
Output:

func Watch added in v0.3.0

func Watch(config sync.Locker, subscribers []chan Update, opts ...Option) (func(), error)

Watch first reads values for exported fields of a struct from either command-line flags, environment variables, or configuration files. It then watches any change to those fields that their values are read from configuration files and notifies subscribers on a channel.

Example
package main

import (
	"sync"

	"github.com/moorara/konfig"
)

func main() {
	// When using the Watch method, your struct needs to implement the sync.Locker interface.
	// You can simply achieve that by embedding the sync.Mutex type in your struct.
	var config = struct {
		sync.Mutex
		LogLevel string
	}{
		LogLevel: "info", // default
	}

	// For using the Watch method, you need to define a channel for receiving updates.
	// If a configuration value gets a new value (through files), you will get notified on this channel.
	ch := make(chan konfig.Update, 1)

	// In a separate goroutine, you can receive the new configuration values and re-configure your application accordingly.
	go func() {
		for update := range ch {
			if update.Name == "LogLevel" {
				config.Lock()
				// logger.SetLevel(config.LogLevel)
				config.Unlock()
			}
		}
	}()

	// You can now watch for configuration values.
	close, _ := konfig.Watch(&config, []chan konfig.Update{ch})
	defer close()
}
Output:

Types

type Option added in v0.2.1

type Option func(*reader)

Option sets optional parameters for reader.

func Debug added in v0.3.0

func Debug(verbosity uint) Option

Debug is the option for enabling logs for debugging purposes. verbosity is the verbosity level of logs. You can also enable this option by setting KONFIG_DEBUG environment variable to a verbosity level. You should not use this option in production.

func ListSep added in v0.3.2

func ListSep(sep string) Option

ListSep is the option for specifying list separator for all fields with slice type. You can specify a list separator for each field using `sep` struct tag. Using `tag` struct tag for a field will override this option for that field.

func PrefixEnv added in v0.3.1

func PrefixEnv(prefix string) Option

PrefixEnv is the option for prefixing all environment variable names with a given string. You can specify a custom name for environment variable for each field using `env` struct tag. Using `env` struct tag for a field will override this option for that field.

func PrefixFileEnv added in v0.3.1

func PrefixFileEnv(prefix string) Option

PrefixFileEnv is the option for prefixing all file environment variable names with a given string. You can specify a custom name for file environment variable for each field using `fileenv` struct tag. Using `fileenv` struct tag for a field will override this option for that field.

func PrefixFlag added in v0.3.1

func PrefixFlag(prefix string) Option

PrefixFlag is the option for prefixing all flag names with a given string. You can specify a custom name for command-line flag for each field using `flag` struct tag. Using `flag` struct tag for a field will override this option for that field.

func SkipEnv added in v0.3.2

func SkipEnv() Option

SkipEnv is the option for skipping environment variables as a source for all fields. You can skip environment variables as a source for each field by setting `env` struct tag to `-`.

func SkipFileEnv added in v0.3.2

func SkipFileEnv() Option

SkipFileEnv is the option for skipping file environment variables as a source for all fields. You can skip file environment variable as a source for each field by setting `fileenv` struct tag to `-`.

func SkipFlag added in v0.3.2

func SkipFlag() Option

SkipFlag is the option for skipping command-line flags as a source for all fields. You can skip command-line flag as a source for each field by setting `flag` struct tag to `-`.

func Telepresence added in v0.2.1

func Telepresence() Option

Telepresence is the option for reading files when running in a Telepresence shell. If the TELEPRESENCE_ROOT environment variable exist, files will be read from mounted volume. See https://telepresence.io/howto/volumes.html for details.

type Update added in v0.3.0

type Update struct {
	Name  string
	Value interface{}
}

Update represents a configuration field that received a new value.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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