conf

package module
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2023 License: Apache-2.0 Imports: 9 Imported by: 1

README

Go Report Card GitHub Actions Go Reference

conf

Package conf provides a set of utilities for mapping configuration settings from env vars, flags and secret managers to struct fields.

import "github.com/fritzkeyzer/conf"

Features

Load struct fields from environment variables

var Config struct {
    DBConn string `env:"DB_CONN"`
}

_ = conf.LoadEnv(&Config)

Load struct fields from CLI flags

var Config struct {
    DBConn string `flag:"db-conn"`
}

_ = conf.LoadFlags(&Config)

Load struct fields from a secret manager

var Config struct {
    DBConn string `secret:"db-conn"`
}

_ = conf.LoadSecrets(&Config, secretMgr) // where secretMgr implements the SecretSource interface

Utilities

Parse flags from []string, eg: os.Args

args := []string{"nonsense", "--xyz=abc", "nonsense", "-v"}

// get value, found from []string
value, found := GetFlag("--xyz", args) // value = "abc", found = true

// eg:
_, verbose := GetFlag("-v", args) // verbose = true

Print a config to stdout

type Config struct {
    Host    string `env:"HOST" flag:"--host"`
    Verbose bool   `flag:"-v"`
    Count   int    `flag:"--count"`
    DB      struct {
    Name string `env:"DB_NAME"`
    User string `env:"DB_USER" secret:"db-user"`
    Pass string `env:"DB_PASS" secret:"db-pass"`
}

conf.Print(&cfg) // notice how the secret fields are masked with ***

// Output:
// ---------------------------
//  Host      = "localhost"
//  Verbose   = false
//  DB
//    .Name   = "app"
//    .User   = "user"
//    .Pass   ***
// ---------------------------

Flatten struct fields and iterate over them, eg: to export to a .env file

fields, _ := conf.FlattenStructFields(&cfg)

envFile := ""
for _, field := range fields {
    envVar, e := field.EnvVar()
    if !e {
        continue
    }
    
    envVal, _ := field.ExportValue() // exports values in a way that is suitable for env vars and for loading back into the struct
    envFile += "export " + envVar + "=" + envVal + "\n"
}

Example

Example from examples/main.go

package main

import (
	"fmt"
	"os"

	"github.com/fritzkeyzer/conf"
)

type Config struct {
	Host    string `env:"HOST" flag:"--host"`
	Verbose bool   `flag:"-v"`
	Count   int    `flag:"--count"`
	DB      struct {
		Name string `env:"DB_NAME"`
		User string `env:"DB_USER" secret:"db-user"`
		Pass string `env:"DB_PASS" secret:"db-pass"`
	}
}

// main demonstrates various functions of the conf package
//   - LoadEnv loads fields from environment variables
//   - LoadFlags loads fields from command line flags
//   - LoadSecrets loads fields from a secret manager
//   - Print prints the config to stdout
func main() {
	// for demo purposes, we set the env vars here
	os.Setenv("HOST", "localhost")
	os.Setenv("DB_NAME", "app")
	os.Setenv("DB_USER", "user from env")
	os.Setenv("DB_PASS", "pass from env")

	var cfg Config

	if err := conf.LoadEnv(&cfg); err != nil {
		panic(err)
	}

	// fields can be overridden by flags, eg: host, verbose or count
	if err := conf.LoadFlags(&cfg); err != nil {
		panic(err)
	}

	// fields can be loaded from a secret manager
	if err := conf.LoadSecrets(&cfg, &SecretManager{}); err != nil {
		panic(err)
	}

	// notice how the secret fields are masked with ***
	conf.Print(&cfg)

	// Output:
	// ---------------------------
	//  Host      = "localhost"
	//  Verbose   = false
	//  DB
	//    .Name   = "app"
	//    .User   = "user"
	//    .Pass   ***
	// ---------------------------

	// other features include flattening the struct fields
	fields, _ := conf.FlattenStructFields(&cfg)

	// this way you can iterate over the fields and do something with them
	// eg: exporting the values to a .env file
	envFile := ""
	for _, field := range fields {
		envVar, e := field.EnvVar()
		if !e {
			continue
		}

		envVal, _ := field.ExportValue()
		envFile += "export " + envVar + "=" + envVal + "\n"
	}

	fmt.Println(envFile)
	// Output:
	//export HOST=localhost
	//export DB_NAME=app
	//export DB_USER=user from secret manager
	//export DB_PASS=secret password 1337
}

// SecretManager is a mock secret manager, for demo purposes
type SecretManager struct{}

func (sm *SecretManager) Load(key string) ([]byte, bool, error) {
	if key == "db-user" {
		return []byte("user from secret manager"), true, nil
	}

	if key == "db-pass" {
		return []byte("secret password 1337"), true, nil
	}

	return nil, false, nil
}

Documentation

Overview

Package conf provides a set of utilities for mapping configuration settings (from env vars, flags and secret managers) to struct fields.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetFlag

func GetFlag(flag string, args []string) (val string, found bool)

GetFlag is a utility to extract a flag from a slice of CLI args. It returns the value of the flag and a boolean indicating whether the flag was found. For example, args could be os.Args[1:]. flag should include the prefix, eg: "--verbose" or "-v" GetFlag supports the following formats:

flag=value
flag="value"
flag='value'
flag value
flag "value"
flag 'value'
Example
args := []string{"nonsense", "--xyz=abc", "nonsense", "-v"}

xyz, _ := GetFlag("--xyz", args)
_, verbose := GetFlag("-v", args)

fmt.Printf("xyz = %q, verbose = %v", xyz, verbose)
Output:

xyz = "abc", verbose = true

func LoadEnv

func LoadEnv(ptr any) error

LoadEnv recursively scans struct fields for the env tag then sets the values from the corresponding env var. Eg:

type Config struct {
	Host string `env:"HOST"`
}

func LoadFlags

func LoadFlags(ptr any) error

LoadFlags recursively scans struct fields for the `flag` tag then sets the values from CLI flags. Eg:

type Config struct {
	Host    string `flag:"--host"`
	Verbose bool   `flag:"-v"`
}

func LoadSecrets

func LoadSecrets(ptr any, source SecretSource) error

LoadSecrets recursively scans struct fields for the secret tag then sets the values from the secret SecretSource. Eg:

type Config struct {
	Host string `secret:"host"`
}

func Print

func Print(ptr any)

Print wraps PrintToString and prints the result to stdout. Example output:

Host      = "localhost"
Verbose   = false
DB
  .Name   = "app"
  .User   = "user"
  .Pass   ***

func PrintToString

func PrintToString(ptr any) string

PrintToString returns a string representation of the config struct. Secrets are masked. Example output:

Host      = "localhost"
Verbose   = false
DB
  .Name   = "app"
  .User   = "user"
  .Pass   ***

Types

type Field added in v1.0.3

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

Field represents a struct field

func FlattenStructFields added in v1.0.3

func FlattenStructFields(ptr any) ([]Field, error)

FlattenStructFields returns a flat slice of Field from recursively traversing the struct fields of v.

  • unexported fields are omitted
  • fields marked with an env, flag or secret tag are included, but their children are not

func (*Field) EnvVar added in v1.0.3

func (f *Field) EnvVar() (string, bool)

EnvVar returns the `env` tag value and a bool indicating if the field has the `env` tag.

func (*Field) ExportValue added in v1.0.3

func (f *Field) ExportValue() (string, error)

ExportValue returns the value of the field as a string.

  • []byte fields are base64 encoded
  • string fields are not pre-processed
  • all other types marshalled to JSON

func (*Field) FlagName added in v1.0.3

func (f *Field) FlagName() (string, bool)

FlagName returns the `flag` tag value and a bool indicating if the field has the `flag` tag.

func (*Field) SecretKey added in v1.0.3

func (f *Field) SecretKey() (string, bool)

SecretKey returns the `secret` tag value and a bool indicating if the field has the `secret` tag.

type SecretSource

type SecretSource interface {
	// Load a secret from the source. Returns the secret value, a boolean indicating if the secret was found and an error.
	// NOTE: Load should not return an error if the secret was not found, but should instead return "", false, nil.
	Load(key string) ([]byte, bool, error)
}

SecretSource interface allows any secret manager to be used, by wrapping it in a type that implements this interface.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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