envconfig

package module
v0.0.0-...-09524dc Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2022 License: Apache-2.0 Imports: 9 Imported by: 3

README

envconfig

PkgGoDev Go Report Card Quality Assurance Coverage Status

envconfig populates struct members based on environment variables.

Yes, there are several popular existing solutions:

This one has several attractive properties:

  • It is designed to "meet you where you are". You probably have an existing codebase that does a bunch of ad-hoc env-var parsing with weird semantics. It allows you to clean up your code internally without changing the behavior for your users.
  • It supports falling back to a default value not just if an env-var is missing, but if the env-var's value is invalid.
  • It allows one member's default value to refer to another.
  • Distinguishes between warnings and fatal errors
  • Allows setting different parse-modes ("parser"), without using weird types. It is easy to add new parsers.
  • Supports nested structs, though it is not possible to add a prefix (as https://github.com/sethvargo/go-envconfig allows you to do).
  • Tag options are parsed more idiomatically ("env:comma,separated,list") than https://github.com/kelseyhightower/envconfig.

Example

import (
	"os"
	"time"

	"github.com/datawire/envconfig"
)

type Config struct {
	Port    int           `env:"PORT    ,parser=strconv.ParseInt               "`
	Timeout time.Duration `env:"TIMEOUT ,parser=time.ParseDuration ,default=5s "`
}

func ConfigFromEnv() (cfg Config, warn []error, fatal []error) {
	parser, err := envconfig.GenerateParser(reflect.TypeOf(Config{}), nil)
	if err != nil {
		// panic, because it means that the definition of
		// 'Config' is invalid, which is a bug, not a
		// runtime error.
		panic(err)
	}
	warn, fatal = parser.ParseFromEnv(&cfg, os.LookupEnv)
	return
}

Tag Syntax

As is idiomatic for struct-tag systems, envconfig interprets struct tags as sequence of whitespace-separated key:"value" pairs. It looks exclusively at the env key, and interprets the value as NAME[,CFG1[,CFG2]] where NAME is the name of the environment variable to look at, and the CFG$N configuration flags are as listed below. Each item in this comma-separated sequence gets whitespace-trimmed; it is allowable to pad your options with whitespace for readability.

  • parser=parsername

    The parser= flag is required. It tells envconfig how to parse the env-var and the default value (if you specify a default). You pass your list of parsers to envconfig.GenerateParser, or pass in nil to use the list from envconfig.DefaultFieldTypeHandlers(). See envconfig_types.go for how to define your own parsers.

  • const

    The const flag indicates that this value should not be read from an environment variable, but instead should be the constant value specified in the default= flag. If const is set, then the NAME must be empty; conversely, if const is not set, then the NAME must not be empty.

    struct {
    	NonConfigurableDir   string   `env:",const=true   ,parser=nonempty-string    ,default=/opt/some-dir  "`
    }
    
  • default=defaultstring

    The default= flag is optional, and specifies a default value for this member if the env-var is not set or if it contains a value that the parser= could not interpret without error. If the default= flag is not present, then this struct member is considered to be required, and ParseFromEnv will return an error if the env-var is unset or invalid. The string passed to the default= flag is interpreted according to the parser=.

    The value following default= can contain commas, so this item must be the last one in the env tag.

  • defaultFrom=membername

    Similar to default=, the defaultFrom= flag specifies a default value for this member, but it does so by referring to another member earlier in the same struct. The member being referred to must be mentioned earlier (forward references do not work). The member being referred to must be it must of the same type as this member; the value is copied directly, rather than going through the parser. This allows members to be chained to support multiple ways of setting the same thing.

    It is invalid to set both default= and defaultFrom=.

    The following example, allows a legacy TIMEOUT_S variable to be set to an integer number of seconds, but that is overridden by a newer TIMEOUT variable that takes a friendlier duration-string, and then that gets copied in to a Timeout member for easy access in your Go code.

    struct {
    	Timeout_LowPrecendence   time.Duration  `env:"TIMEOUT_S  ,parser=integer-seconds     ,default=5                         "`
    	Timeout_HighPrecendence  time.Duration  `env:"TIMEOUT    ,parser=time.ParseDuration  ,defaultFrom=TimeoutLowPrecedence  "`
    	Timeout                  time.Duration  `env:",const     ,parser=time.ParseDuration  ,defaultFrom=TimeoutHighPrecedence "`
    }
    

Documentation

Overview

Package envconfig is a work-alike of github.com/kelseyhightower/envconfig, but:

  • Has more idiomatic "tag options" (comma separated things)
  • Supports falling back to a default if a provided value is invalid
  • Distinguishes between warnings and fatal errors
  • Allows setting different parse-modes ("parser"), without using weird types

Index

Constants

This section is empty.

Variables

View Source
var ErrNotSet = errors.New("is not set")

ErrNotSet is the error that gets wrapped when a "required" env-var is not set.

Functions

func DefaultFieldTypeHandlers

func DefaultFieldTypeHandlers() map[reflect.Type]FieldTypeHandler

DefaultFieldTypeHandlers returns a map of the struct field type handlers that are used if a nil map is passed to GenerateParser. A new map is allocated on each call; mutating the map will not change the defaults.

Types

type FieldTypeHandler

type FieldTypeHandler struct {
	Parsers map[string]func(string) (interface{}, error)
	Setter  func(reflect.Value, interface{})
}

A FieldTypeHandler adds support for a struct member type.

type LookupFunc

type LookupFunc func(key string) (string, bool)

LookupFunc is a function that performs lookup of an environment variable. It's typically set to os.LookupEnv.

type StructParser

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

A StructParser inspects and parses the environment to set fields in a struct.

func GenerateParser

func GenerateParser(structInfo reflect.Type, typeHandlers map[reflect.Type]FieldTypeHandler) (StructParser, error)

GenerateParser takes a struct (not a struct pointer) type with `"env:..."` tags on each of its fields, and returns a parser for it.

func (StructParser) ParseFromEnv

func (p StructParser) ParseFromEnv(structPtr interface{}, lookup LookupFunc) (warn, fatal []error)

ParseFromEnv populates structPtr from values returned by the given LookupFunc function, returning warnings and fatal errors. It panics if structPtr is of the wrong type for this parser.

Jump to

Keyboard shortcuts

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