configo

package module
v1.29.0 Latest Latest
Warning

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

Go to latest
Published: Dec 17, 2021 License: MIT Imports: 9 Imported by: 7

README

Simple-Configo

Test Go Report Card codecov Total alerts

Simple-Configo streamlines the creation of multiple independent configuration structs to the implementation of a single interface, the Config interface, that has only two methods.

type Config interface {
    Options() (options Options)
}

The Options method returns a list of Option objects that contain all of the logic needed to parse a config file into your custom struct fields.

I usually fetch key-value pairs from a .env file as well the environment variables of your current user session. That's why the configo.Parsefunction looks the way it does, you pass an env map[string]string as a parameter to the funcion as well as a type implementing the Config interface.

Example

In order to create your own custom configuration struct that is supposed to fetch values from your environment or a .env file, use a third party package or the os package to fetch a map of your envirnonment variables.

Go Playground example: https://play.golang.org/p/cgTsQurR0Pm

package main

import (
    "encoding/json"
    "fmt"
    "sync"
    "time"

    configo "github.com/jxsl13/simple-configo"
    "github.com/jxsl13/simple-configo/parsers"
    "github.com/jxsl13/simple-configo/unparsers"
)

// MyConfig is a custom configuration that I want to use.
type MyConfig struct {
    SomeBool      bool
    SomeInt       int
    SomeFloat     float64
    SomeDelimiter string
    SomeDuration  time.Duration
    SomeList      []string
    SomeStringSet map[string]bool
}

// Options returns a list of available options that can be configured for this
// config object
func (m *MyConfig) Options() (options configo.Options) {
    // NOTE: delimiter is parsed before the other values, this order is important,
    // as the delimiter is used afterwards.
    optionsList := configo.Options{
        {
            Key:             "SOME_BOOL",
            Mandatory:       true,
            Description:     "This is some description text.",
            DefaultValue:    "no",
            ParseFunction:   parsers.Bool(&m.SomeBool),
            UnparseFunction: unparsers.Bool(&m.SomeBool),
        },
        {
            Key:             "SOME_INT",
            Description:     "This is some description text.",
            DefaultValue:    "42",
            ParseFunction:   parsers.Int(&m.SomeInt),
            UnparseFunction: unparsers.Int(&m.SomeInt),
        },
        {
            Key:             "SOME_FLOAT",
            Description:     "This is some description text.",
            DefaultValue:    "99.99",
            ParseFunction:   parsers.Float(&m.SomeFloat, 64),
            UnparseFunction: unparsers.Float(&m.SomeFloat, 64),
        },
        {
            Key:             "SOME_DELIMITER",
            Description:     "delimiter to split the lists below.",
            DefaultValue:    " ",
            ParseFunction:   parsers.String(&m.SomeDelimiter),
            UnparseFunction: unparsers.String(&m.SomeDelimiter),
        },
        {
            Key:             "SOME_DURATION",
            Description:     "This is some description text.",
            DefaultValue:    "24h12m44s",
            ParseFunction:   parsers.Duration(&m.SomeDuration),
            UnparseFunction: unparsers.Duration(&m.SomeDuration),
        },
        {
            Key:             "SOME_LIST",
            Description:     "Some IP list",
            DefaultValue:    "127.0.0.1 127.0.0.2 127.0.0.3",
            ParseFunction:   parsers.List(&m.SomeList, &m.SomeDelimiter),
            UnparseFunction: unparsers.List(&m.SomeList, &m.SomeDelimiter),
        },
        {
            Key:             "SOME_SET",
            Description:     "This is some description text.",
            DefaultValue:    "127.0.0.1 127.0.0.2 127.0.0.3 127.0.0.1",
            ParseFunction:   parsers.ListToSet(&m.SomeStringSet, &m.SomeDelimiter),
            UnparseFunction: unparsers.SetToList(&m.SomeStringSet, &m.SomeDelimiter),
        },
    }

    // add prefix
    for idx := range optionsList {
        optionsList[idx].Key = "MY_" + optionsList[idx].Key
    }

    return optionsList
}

func main() {

    env := map[string]string{
        "MY_SOME_BOOL":      "true",
        "MY_SOME_INT":       "10",
        "MY_SOME_FLOAT":     "12.5",
        "MY_SOME_DELIMITER": ";",
        "MY_SOME_DURATION":  "12h",
        "MY_SOME_LIST":      "99;15;13;77",
        "MY_SOME_SET":       "99;15;13;77;99",
    }

    myCfg := &MyConfig{}
    if err := configo.Parse(env, myCfg); err != nil {
        panic(err)
    }

    for _, opt := range myCfg.Options() {
        fmt.Println(opt.String())
    }

    b, err := json.MarshalIndent(&myCfg, " ", " ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))


    newEnvMap, err := configo.Unparse(myCfg)
    if err != nil {
        panic(err)
    }
    // write map to file, update some database, redis, etc.
    b, err = json.MarshalIndent(&newEnvMap, " ", " ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
}

This is everything you need to write in order to parse a configuration file with key value pairs into a struct of your choise.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrOptionMissingKey The option is missing the 'Key' field
	ErrOptionMissingKey = errors.New("the option is missing the 'Key' field")
	// ErrOptionMissingDescription The option is missing the 'Description' field
	ErrOptionMissingDescription = errors.New("the option is missing the 'Description' field")
	// ErrOptionInvalidDefaultValue the option has an invalid 'DefaultValue' field, please check its 'type' field
	ErrOptionInvalidDefaultValue = errors.New("the option has an invalid 'DefaultValue' field")
	// ErrOptionMissingParseFunction the option is missing its 'ParseFunc' field
	ErrOptionMissingParseFunction = errors.New("the option is missing its 'ParseFunc' field")
)
View Source
var (
	// ErrSkipUnparse can be returned by an UnparserFunc in order to skip the unparsing (serialization)
	// of a specific option without aborting whe whole unparsing process.
	// In the normal case the first returned error leads to the abortion of the unparsing process.
	ErrSkipUnparse = errors.New("skip unparsing")
)
View Source
var (
	// KeyToFlagNameTransformer is the function that takes an Option.Key and transforms it into a
	// cli flag name. e.g. FLAG_NAME to --flag-name for any Option that is NOT an .IsAction()
	KeyToFlagNameTransformer = DefaultKeyToFlagNameTransformer
)

Functions

func DefaultKeyToFlagNameTransformer added in v1.28.1

func DefaultKeyToFlagNameTransformer(key string) string

func GetEnv added in v1.2.6

func GetEnv() map[string]string

GetEnv returns a map of OS environment variables

func GetFlagMap added in v1.28.1

func GetFlagMap(osArgs []string, cfgs ...Config) (map[string]string, error)

GetFlagMap returns a map of flags that consists of flag values passed via osArgs that can be found in the cfg Options' keys.

func GetFlagSet added in v1.28.1

func GetFlagSet(setName string, errHandling flag.ErrorHandling, cfgs ...Config) *flag.FlagSet

GetFlagSet constructs a flag.FlagSet from your configs that may be registered with cli tools for auto completion purposes. e.g. Cobra/Viper you may iterate ove rthe flagset with .Visit//.VisitAll The main purpose of this is to define auto completion references.

func GetFlags added in v1.27.0

func GetFlags(cfgs ...Config) map[string]string

GetFlags parses your config options and extracts allof the option's keys, constructs flag names from the option keys, parses the os.Args and then returns a map with all non null flag values This function may exit the application in case the flag parsing fails somehow.

func OptionDefaults added in v1.29.0

func OptionDefaults(cfgs ...Config) map[string]string

OptionDefaults returns a map of option keys and option default values for options that define at least a ParseFunction or UnparseFunction

func Parse

func Parse(env map[string]string, cfgs ...Config) error

Parse the passed envoronment map into the config struct. Every Config defines, how its Options look like and how those are parsed.

func ParseEnv added in v1.11.0

func ParseEnv(cfgs ...Config) error

ParseEnv parse the environment variables and fills all of the definied options on the configuration.

func ParseEnvFile added in v1.13.0

func ParseEnvFile(filePathOrEnvKey string, cfgs ...Config) error

ParseEnVFile parses either the file at the provided location filePathOrEnvKey or checks if the povided location is actually an environment variable pointing to a file location.

func ParseEnvFileOrEnv added in v1.13.0

func ParseEnvFileOrEnv(filePathOrEnvKey string, cfgs ...Config) error

ParseEnvFileOrEnv tries to parse the env file first and then the environment in case the file parsing fails. filePathOrEnvKey may be a file path or an environment key containing a file path In case a variable is not found in theenv file the next level is tried which is the environment.

func ParseEnvFileOrEnvOrFlags added in v1.27.0

func ParseEnvFileOrEnvOrFlags(filePathOrEnvKey string, cfgs ...Config) error

ParseEnvFileOrEnvOrFlags fetches config values from the .env file, the environment and from the flags and parses the configurations with those values provided as key value map. Warning: do not call this function multiple times with the same configurations, as redefiition of flag names may cause a panic.

func ParseEnvOrFlags added in v1.27.0

func ParseEnvOrFlags(cfgs ...Config) error

ParseEnvOrFlags fetches config values from the .env file, the environment and from the flags and parses the configurations with those values provided as key value map.

func ParseFlags added in v1.27.0

func ParseFlags(cfgs ...Config) error

ParseFlags parses the flags provided to the application based on the provided option definitions in every passed Config

func ParseOptions added in v1.9.0

func ParseOptions(options Options, env map[string]string) error

for internal usage in order not to call cfg.Options() multiple times. INFO: ParseOptions is not goroutine safe.

func ReadEnvFile added in v1.13.0

func ReadEnvFile(filePathOrEnvKey string) (map[string]string, error)

ReadEnvFile allows to read the env map from a key value file File content: key=value

func SetEnv added in v1.14.0

func SetEnv(env map[string]string)

SetEnv sets the environment variables found in the env map.

func Unparse added in v1.7.0

func Unparse(cfgs ...Config) (map[string]string, error)

Unparse is the reverse operation of Parse. It retrieves the values from the configuration and serializes them to their respective string values in order to be able to writ ethem back to either the environment or to a file.

func UnparseEnvFile added in v1.13.0

func UnparseEnvFile(filePathOrEnvKey string, cfgs ...Config) error

UnparseEnvFile is the opposite of ParseEnvFile. It serializes the map back into the file.

func UnparseOptions added in v1.11.0

func UnparseOptions(options Options) (map[string]string, error)

UnparseOptions returns a key value map from the parsed options. This is the reverse operation of ParseOptions. Only options that define a UnparserFunction are serialized into their string values. Options that do not differ from their default values are ignored in order to keep the returned map as small as possible. INFO: Not goroutine safe

func UnparseValidate added in v1.12.0

func UnparseValidate(cfgs ...Config) (map[string]string, error)

UnparseValidate unparses the values and tries to parse the values again in order to validate their values this allows to have a complex ParserFunction but a simple UnparserFunction, as all of the validation logic is provided via the ParserFunction.

func UpdateEnvFile added in v1.18.0

func UpdateEnvFile(env map[string]string, filePathOrEnvKey string) error

UpdateEnvFile reads the file and update sits content to the new values.

func WriteEnvFile added in v1.13.0

func WriteEnvFile(env map[string]string, filePathOrEnvKey string) error

WriteEnvFile writes the map content into an env file

Types

type ActionFunc added in v1.20.0

type ActionFunc func() error

ActionFunc is a function that does something but contrary to ParseFunc doe snot evaluate the provided option value. An option that only consists of actions is in fact an action that is not expected to be found in the string map, e.g. env map, env file, etc..

type Config

type Config interface {
	Options() (options Options)
}

Config is an interface that implements only two methods. The first method simply returns the name of the configuration. The second method returns a list of Option objects that are everything that is needed to fill the struct fields of your custom interface implementation of Config.

type Option

type Option struct {
	Key          string
	Description  string
	Mandatory    bool
	DefaultValue string

	PreParseAction  ActionFunc
	ParseFunction   ParserFunc
	PostParseAction ActionFunc

	PreUnparseAction  ActionFunc   // used to prepare values for serialization, may return an ErrSkipUnparse to skip the unparsing step.
	UnparseFunction   UnparserFunc // execute string serialization, may return an ErrSkipUnparse
	PostUnparseAction ActionFunc   // may be used for closing handles after parameter serialization, cannot invoke unparse skipping
}

Option is a value that can be set to configure The key is any kind of key that defines the option's values in like an environment variable or and kind of map structure that is passed to the configo.Parse(config, map) function. The description describes this option with a long text The Mandatory parameter enforces this value to be present, either by having a non-empty DefaultValue string

or by being present in the map that is used to fill the resulting struct.

The DefaultValue can be any non-empty string value that can for example be configured, but must not be configured, as the default value is good enough without being changed. At specific constellations and with specific parsing functions this value is also checked for validity with the following ParseFunction. The ParseFunction heavily relies on side effects, as it does only return the error in case the parsing failed. Usually the pattern is followed where another function gets parameters or struct property references passed and returns a ParseFunc that modifies the parameters that were passed to the parent function which returns the ParseFunc. The UnparseFunction allows to do the opposite of the ParseFunvction. It is called once your application shuts down. This way you may serialize previously deserialized values back into a file, set environment variables, close client connections, and so on. IsPseudoOption is an option that does not necessary relate to any actual Key value in any configuration map but does actually just do some operation that relies on previously computed config values e.g. the construction of a file path that needs a previously configured and evaluated directory path and some filename in order to construct that path. INFO: A pseudo option enforces the execution of the parsing function, even if the corresponding key does not exist in e.g. the environment.

func (*Option) IsAction added in v1.20.0

func (o *Option) IsAction() bool

IsAction returns true in case the provided option has no ParseFunction nor UnparseFunction defined and at least one Action defined.

func (*Option) IsOption added in v1.20.0

func (o *Option) IsOption() bool

IsOption retursns true in case either ParseFunction or UnparseFunction is not nil.

func (*Option) Parse added in v1.20.0

func (o *Option) Parse(m map[string]string) error

Parse evaluates the passed key/value map. Initially the PreparseAction is executed in case it exists, then the ParseFunction is executed with the map value that may or may not exist. Depending on whether the option is mandatory and not default value is set in that option, it requires that the option value is provided by the key/value map. After parsing the PostParseAction is executed. In case that the expected value is not provided by the env map, the default value is parsed instead. The default value is always parsed in order to check whether it is valid according to the ParseFunction. In case a custom value is defined the default value is overwritten by the custom value.

func (*Option) String

func (o *Option) String() string

String returns a string representation of the option. w/o any function pointers

func (*Option) Unparse added in v1.20.0

func (o *Option) Unparse() (string, error)

Unparse executes the PreUnparseAction, UnparseFunction and the PostUnparseAction Depending on the UnparseFunction we get a string representation of a value back. This is the inverse operation of parsing, usually a serialization operation The returned value represents the value at the key o.Key in the resulting env map that is of type map[string]string. This function may return a configo.ErrSkipUnparse error which indicates that that the returned value is not added to any map or that we do not want to unparse (serialize) any values of this option struct.

type Options

type Options []Option

Options are usually unique, so one MUST NOT use redundant Option parameters

type ParserFunc

type ParserFunc func(value string) error

ParserFunc is a custom parser function that can be used to parse specific option values A Option struct must contain a ParseFunc in order to know, how to parse a specific value and where the Such a function is usually created using a generator function, that specifies the output type. This function is kept as simple as possible, in order to be handled exactly the same way for every possible return value

type UnparserFunc added in v1.7.0

type UnparserFunc func() (string, error)

UnparserFunc is a function that receives a key and returns the key's value UnparseFunctions go back to creating a map[string]string from the previously parse configuration struct.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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