config

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2023 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package config provides single source of configuration management. The default providers are file, environment and command line (flag) configuration. You can set default values for specified key which will be loaded at first place and can be overridden by one of providers during loading process. The package contains also helpers to pass one struct fields to another struct to easily bind values to it.

Example
package main

import (
	"context"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/Prastiwar/Go-flow/config"
)

func main() {
	// Provide creates new Source instance with provided configs.
	cfg := config.Provide(
	// // { "queryTimeout": "10s" }
	// config.NewFileProvider("config.json", decoders.NewJson()),
	// // --dbName="my-collection" --errorDetails=true
	// config.NewFlagProvider(
	// 	config.StringFlag("dbName", "name for database"),
	// 	config.BoolFlag("errorDetails", "should show error details"),
	// ),
	// // CONNECTION_STRING="mongodb://localhost:8089"; ERROR_DETAILS="false"
	// config.NewEnvProvider(),
	)

	// ShareOptions provides options to set default options for all provider.
	cfg.ShareOptions(
		// KeyInterceptor allows to intercept field name before it's used to find it in provider.
		// It's useful when you want to use different field names than they're defined in struct.
		// For example you can use tag to define field name and intercept it there.
		config.WithInterceptor(func(providerName string, field reflect.StructField) string {
			if providerName == config.EnvProviderName {
				return strings.ToUpper(field.Name)
			}
			return field.Name
		}),
	)

	// Use default values for options in case they are not included in providers.
	err := cfg.SetDefault(
		config.Opt("connectionString", "mongodb://localhost:27017"),
		config.Opt("dbName", "go-flow"),
		config.Opt("errorDetails", true),
		config.Opt("queryTimeout", time.Second*15),
		config.Opt("access-key", "ABC123EFGH456IJK789"),
	)
	if err != nil {
		// some default value couldn't be marshaled as json
		panic(err)
	}

	type DbOptions struct {
		DbName           string
		ConnectionString string
		ErrorDetails     bool
		QueryTimeout     time.Duration
		AccessKey        string `json:"access-key"`
	}

	var dbOptions DbOptions

	// dbOptions will be loaded starting from the first passed provider up to the last one.
	// All values will be also overridden by each provider in this order.
	// The default value is not overridden by provider if it doesn't exist in it.
	err = cfg.Load(context.Background(), &dbOptions)
	if err != nil {
		// One of the providers failed to load config values
		panic(err)
	}

	fmt.Println(dbOptions.DbName)
	fmt.Println(dbOptions.ConnectionString)
	fmt.Println(dbOptions.ErrorDetails)
	fmt.Println(dbOptions.QueryTimeout)
	fmt.Println(dbOptions.AccessKey)

}
Output:

go-flow
mongodb://localhost:27017
true
15s
ABC123EFGH456IJK789

Index

Examples

Constants

View Source
const (
	EnvProviderName  = "env"
	FlagProviderName = "flag"
)

Variables

View Source
var (
	ErrDuplicateKey        = errors.New("cannot pass duplicated key")
	ErrNonPointer          = errors.New("cannot pass non pointer values")
	ErrNonStruct           = errors.New("cannot load config to non struct value")
	ErrMustImplementGetter = errors.New("must implement flag.Getter interface")
)

Functions

func Bind

func Bind(from any, to any) error

Bind sets each 'to' field value from corresponding field from 'from'. It will not return an error if will not find matching field.

Example
package main

import (
	"fmt"

	"github.com/Prastiwar/Go-flow/config"
)

func main() {
	type DbOptions struct {
		AccessKey string `json:"access-key"`
	}

	type AccessOptions struct {
		AccessKey string
	}

	dbOptions := DbOptions{
		AccessKey: "ABC123EFGH456IJK789",
	}
	var aOptions AccessOptions

	fmt.Println(dbOptions.AccessKey)
	fmt.Println(aOptions.AccessKey)

	// Bind will try to copy corresponding field from dbOptions to aOptions
	err := config.Bind(&dbOptions, &aOptions)
	if err != nil {
		// Probably field type mismatch
		panic(err)
	}

	fmt.Println(aOptions.AccessKey)

}
Output:

ABC123EFGH456IJK789

ABC123EFGH456IJK789

func BoolFlag

func BoolFlag(name string, usage string) flag.Flag

func CustomFlag

func CustomFlag(name string, usage string, value flag.Value) flag.Flag

CustomFlag creates a flag with specified name, usage and flag.Value implementation.

func DurationFlag

func DurationFlag(name string, usage string) flag.Flag

func Float32Flag

func Float32Flag(name string, usage string) flag.Flag

func Float64Flag

func Float64Flag(name string, usage string) flag.Flag

func Int32Flag

func Int32Flag(name string, usage string) flag.Flag

func Int64Flag

func Int64Flag(name string, usage string) flag.Flag

func NewEnvProvider

func NewEnvProvider() *envProvider

NewEnvProvider returns a new environment provider used to load environments variables.

func NewEnvProviderWith

func NewEnvProviderWith(prefix string) *envProvider

NewEnvProviderWith returns a new environment provider with prefix used to load environments variables. Prefix is used to distinguish variables in different environments. Mostly used ones are "DEV_", "PROD_".

func NewFieldSetter

func NewFieldSetter(name string, o LoadOptions) *fieldSetter

NewFieldSetter returns a new FieldSetter implementation which can store found value for each v field.

func NewFileProvider

func NewFileProvider(filename string, decoder datas.ReaderUnmarshaler) *readerProvider

NewReaderProvider returns a new file provider with specified filename and decoder.

func NewFileReader

func NewFileReader(filename string) *fileReader

NewReader creates an instance of io.Reader reading from file found at filename.

func NewFlagProvider

func NewFlagProvider(flags ...flag.Flag) *flagProvider

NewFlagProvider returns a new flag provider with defined flags which will be used for command line arguments parsing. It panics if any value field of flag does not implement flag.Getter interface.

func NewReaderProvider

func NewReaderProvider(r io.Reader, d datas.ReaderUnmarshaler) *readerProvider

NewReaderProvider creates an instance of reader provider with specified reader and decoder.

func StringFlag

func StringFlag(name string, usage string) flag.Flag

func TimeFlag

func TimeFlag(name string, usage string) flag.Flag

func Uint32Flag

func Uint32Flag(name string, usage string) flag.Flag

func Uint64Flag

func Uint64Flag(name string, usage string) flag.Flag

Types

type DefaultOpt added in v0.8.0

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

func Opt

func Opt(key string, value any) DefaultOpt

Opts creates an instance of DefaultOpt used for initializing default value for named key.

func (DefaultOpt) Key added in v0.8.0

func (o DefaultOpt) Key() string

func (DefaultOpt) Value added in v0.8.0

func (o DefaultOpt) Value() any

type FieldSetter

type FieldSetter interface {
	SetFields(v any, findFn FieldValueFinder) error
}

FieldSetter is implemented by any value that has a SetFields method. The implementation controls how fields for v value are set.

type FieldValueFinder

type FieldValueFinder func(key string) (any, error)

FieldValueFinder defines function which should return field value or error for named key.

type KeyInterceptor

type KeyInterceptor func(providerName string, field reflect.StructField) string

KeyInterceptor allows to intercept field name before it's used to find it in provider. It's useful when you want to use different field names than they're defined in struct. For example you can use tag to define field name and intercept it there.

type LoadOption

type LoadOption func(*LoadOptions)

func WithIgnoreGlobalOptions added in v0.5.0

func WithIgnoreGlobalOptions() LoadOption

WithIgnoreGlobalOptions returns empty LoadOption to indicate no shared options should be used and no additional configuration is provided. This behaviour applies to Source provider. See Source.Load() for more information.

func WithInterceptor

func WithInterceptor(i KeyInterceptor) LoadOption

type LoadOptions

type LoadOptions struct {
	Interceptor KeyInterceptor
}

LoadOptions stores settings to control behaviour in configuration loading.

func NewLoadOptions

func NewLoadOptions(options ...LoadOption) *LoadOptions

func (*LoadOptions) Intercept

func (o *LoadOptions) Intercept(providerName string, f reflect.StructField) string

Intercept provides default behaviour in case Interceptor is not set the exact field name will be used.

type Provider

type Provider interface {
	Load(ctx context.Context, v any, opts ...LoadOption) error
}

Provider is implemented by any value that has a Load method, which loads configuration and overrides if applicable matching field values for v.

type Source

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

Source stores shared options, default values and configured providers to manage multi-source configuration loading.

func Provide

func Provide(providers ...Provider) *Source

Provide returns a Source of configuration. The order of passed providers matters in terms of overriding field value since each provider will be Load'ed in the same order as they were passed to this function.

func (*Source) Default

func (s *Source) Default(v any) error

Default parses the JSON-encoded default values and stores the result in the value pointed to by v. Read json.Unmarshal for more information.

func (*Source) Load

func (s *Source) Load(ctx context.Context, v any, opts ...LoadOption) error

Load calls LoadWithOptions with specified opts LoadOptions or if none is probided - it will use options stored by ShareOptions method. To ignore shared options without providing any, use WithIgnoreOptions() option.

func (*Source) LoadWithOptions

func (s *Source) LoadWithOptions(ctx context.Context, v any, opts ...LoadOption) error

LoadWithOptions calls Load method on each provider which binds matching v fields by corresponding key value. LoadWithOptions can return ErrNonPointer or ErrNonStruct if v is not valid. If field was not found in provider - it will not override the value. But it can be overridden by provider which will be called as next in order if the value can be found.

func (*Source) SetDefault

func (s *Source) SetDefault(defaults ...DefaultOpt) error

SetDefault sets default values in json format to be easily unmarshaled by Default method.

func (*Source) ShareOptions

func (s *Source) ShareOptions(options ...LoadOption)

ShareOptions shares provided options to be used across each call to Load.

Jump to

Keyboard shortcuts

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