ruadan

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: May 1, 2020 License: MIT Imports: 10 Imported by: 0

README

ruadan

Environment Variable configuration with CLI flag override. Based on the amazing work of Kelsey Hightower's envconfig this aims to solve a similar problem with the addition of cli override flags for each part of your config. Currently you can configure everything with the tags of envconfig, envcli, json, and clidesc.

Note: Complex types are not supported yet and only basic, top level, arrays are set up

API Documentation

See godoc

Getting Started

$ go get github.com/bit-cmdr/ruadan
Example Usage
Predefined struct
package main

import (
  "log"
  "os"

  rd "github.com/bit-cmdr/ruadan"
)

type config struct {
  TestString string  `envconfig:"TEST_STRING"`
  TestInt    int     `envconfig:"TEST_INT" envcli:"testint"`
  TestFloat  float64 `envconfig:"TEST_FLOAT" envcli:"testfloat" clidesc:"set a float 64 value"`
  Pass       bool    `envcli:"pass"`
}

func main() {
  var cfg config

  fs, err := rd.GetConfigFlagSet(os.Args[1:], &cfg)
  if err != nil {
    log.Fatalf("Unable to configure:\n%v\n", err)
  }

  if !cfg.Pass {
    fs.PrintDefaults()
  }

  log.Printf("read so far:\n%+v\n", cfg)
}
Undefined struct method
package main

import (
  "log"
  "os"

  rd "github.com/bit-cmdr/ruadan"
)

func main() {
  cfg := rd.BuildConfig(
      rd.NewOptionString(
      "TestString", 
      rd.OptionENVName("TEST_STRING"), 
      rd.OptionCLIName("TEST_STRING"), 
      rd.OptionJSONName("testString"),
    ),
    rd.NewOptionInt(
      "TestInt", 
      rd.OptionENVName("TEST_INT"), 
      rd.OptionCLIName("testint"), 
      rd.OptionJSONName("testInt"),
    ),
    rd.NewOptionFloat(
      "TestFloat", 
      rd.OptionENVName("TEST_FLOAT"), 
      rd.OptionCLIName("testfloat"), 
      rd.OptionJSONName("testFloat"), 
      rd.OptionCLIUsage("set a float 64 value"),
    ),
    rd.NewOptionBool(
      "Pass", 
      rd.OptionENVName("PASS"), 
      rd.OptionCLIName("pass"), 
      rd.OptionJSONName("pass"),
    ),
  )
  
  // Note that the cfg.Config returned here is already a pointer, there's no need to pass by address
  fs, err := ruadan.GetConfigFlagSet(os.Args[1:], cfg.Config)
  if err != nil {
    log.Fatalf("Unable to configure:\n%v\n", err)
  }

  if !cfg.GetBool("Pass") {
    fs.PrintDefaults()
  }

  log.Printf("read so far:\n%+v\n", cfg)
}
Output for either method
$ go run main.go -pass
read so far:
{TestString: TestInt:0 TestFloat:0 Pass:true}

$ go run main.go -testint 1
  -TEST_STRING string
      flag: TEST_STRING or env: TEST_STRING
  -pass
      flag: pass or env: PASS
  -testfloat float
      set a float 64 value
  -testint int
      flag: testint or env: TEST_INT

read so far:
{TestString: TestInt:1 TestFloat:0 Pass:false}

$ go run main.go -TEST_STRING test
  -TEST_STRING string
      flag: TEST_STRING or env: TEST_STRING
  -pass
      flag: pass or env: PASS
  -testfloat float
      set a float 64 value
  -testint int
      flag: testint or env: TEST_INT

read so far:
{TestString:test TestInt:0 TestFloat:0 Pass:false}

$ PASS=true go run main.go -testint 5 -TEST_STRING testit -testfloat 3.14
read so far:
{TestString:testit TestInt:5 TestFloat:3.14 Pass:true}
Struct and Tags
type example struct {
    NoTags       int
    EnvConfig    int `envconfig:"EX_CONF"`
    EnvCliConfig int `envcli:"conf"`
    CliDesc      int `clidesc:"simple usage explanation"`
}
  • NoTags will look for an env of NOTAGS and a cli of N0TAGS and have a description of flag: NOTAGS or env: NOTAGS
  • EnvConfig will look for an env of EX_CONF and a cli of EX_CONF and have a description of flag: EX_CONF or env: EX_CONF
  • EnvCliConfig will look for an env of CONF and a cli of conf and have a description of flag: conf or env: CONF
  • CliDesc will look for an env of CLIDESC and a cli of CliDesc and have a description of simple usage explanation

It's meant to be as conventional as possible with the option to be incredibly specific

Build Config
cfg := rd.BuildConfig(
  rd.NewOptionBool(
    "Example",
    rd.OptionENVName("ENV_NAME")
    rd.OptionJSONName("jsonName")
    rd.OptionCLIName("cliflagname")
    rd.OptionCLIUsage("use this to describe how to use it from the cli")
  )
)
  • NewOptionBool will add a new field to your struct. The first parameter is the name of the field, remember Go's naming conventions for exposing a field and capitalize the first letter. The rest of the Option fields are optional.
  • OptionENVName is used to set the envconfig tag on the field
  • OptionJSONName is used to set the json tag on the field
  • OptionCLIName is used to set the envcli tag on the field
  • OptionCLIUsage is used to set the clidesc tag on the field

In addition to NewOptionBool there is also

  • NewOptionInt
  • NewOptionString
  • NewOptionFloat

There is also NewOptionComplex which takes a default value after the name argument in order to determine the underlying type, the value is not used. All of the NewOption... functions accept the same options, and their use is the same for all of them.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidConfig = errors.New("cfg must be a struct pointer")

ErrInvalidConfig is the default error message if you don't pass the cfg argument as a struct pointer to GetConfigFlagSet

Functions

func GetConfigFlagSet

func GetConfigFlagSet(args []string, cfg interface{}) (*flag.FlagSet, error)

GetConfigFlagSet takes in the args from the cli and a struct pointer to the struct it will parse. It will look at the tags to determine what keys and areas to look for. The base use case is that you can pass a struct pointer and it will use the envconfig: tag to find the matching environment variable and that can be overridden at launch with a command line flag. The flag will be the same as the envconfig: if not specified, or can be changed with the envcli: tag

Types

type Configuration added in v1.1.0

type Configuration struct {
	Config interface{}
}

Configuration is returned by BuildConfig as an unknown struct to read valued from after initial creation

func BuildConfig added in v1.1.0

func BuildConfig(options ...ConfigurationOption) Configuration

BuildConfig takes a variable amount of ConfigurationOption arguments and uses them to build a struct. This allows you to be very specific in how to build the struct if you don't want to have a struct at the top of your file and want to build it as you go

func (*Configuration) GetBool added in v1.1.0

func (c *Configuration) GetBool(name string) bool

GetBool gets a boolean value from the key that matches the provided name in the Configuration

func (*Configuration) GetComplex added in v1.1.0

func (c *Configuration) GetComplex(name string) interface{}

GetComplex gets an interface value from the key that matches the provided name in the Configuration. This assumes you know what you're asking for and how to cast the result

func (*Configuration) GetFloat64 added in v1.1.0

func (c *Configuration) GetFloat64(name string) float64

GetFloat64 gets a float64 value from the key that matches the provided name in the Configuration

func (*Configuration) GetInt64 added in v1.1.0

func (c *Configuration) GetInt64(name string) int64

GetInt64 gets a int64 value from the key that matches the provided name in the Configuration

func (*Configuration) GetString added in v1.1.0

func (c *Configuration) GetString(name string) string

GetString gets a string value from the key that matches the provided name in the Configuration

type ConfigurationOption added in v1.1.0

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

ConfigurationOption is the extensible struct used to build up a struct field that will be returned as Configuration.Config

func NewOptionBool added in v1.1.0

func NewOptionBool(name string, options ...ConfigurationOptions) ConfigurationOption

NewOptionBool creates a new bool struct field with the given name and options. When considering the name, remember Go's syntax of an upper-case first letter

func NewOptionComplex added in v1.1.0

func NewOptionComplex(name string, defaultValue interface{}, options ...ConfigurationOptions) ConfigurationOption

NewOptionComplex creates a new interface{} struct field with the given name and options. When considering the name, remember Go's syntax of an upper-case first letter

func NewOptionFloat added in v1.1.0

func NewOptionFloat(name string, options ...ConfigurationOptions) ConfigurationOption

NewOptionFloat creates a new float64 struct field with the given name and options. When considering the name, remember Go's syntax of an upper-case first letter

func NewOptionInt added in v1.1.0

func NewOptionInt(name string, options ...ConfigurationOptions) ConfigurationOption

NewOptionInt creates a new int64 struct field with the given name and options. When considering the name, remember Go's syntax of an upper-case first letter

func NewOptionString added in v1.1.0

func NewOptionString(name string, options ...ConfigurationOptions) ConfigurationOption

NewOptionString creates a new string struct field with the given name and options. When considering the name, remember Go's syntax of an upper-case first letter

type ConfigurationOptions added in v1.1.0

type ConfigurationOptions func(*ConfigurationOption)

ConfigurationOptions function used to build the individual ConfigurationOption field

func OptionCLIName added in v1.1.0

func OptionCLIName(name string) ConfigurationOptions

OptionCLIName used to add a envcli: tag to a struct field; will also assume that there is a cli flag

func OptionCLIUsage added in v1.1.0

func OptionCLIUsage(usage string) ConfigurationOptions

OptionCLIUsage used to add a clidesc: tag to a struct field; will also assume that there is a cli flag

func OptionENVName added in v1.1.0

func OptionENVName(name string) ConfigurationOptions

OptionENVName used to add a envconfig: tag to a struct field

func OptionJSONName added in v1.1.0

func OptionJSONName(name string) ConfigurationOptions

OptionJSONName used to add a json: tag to a struct field

type Decoder

type Decoder interface {
	Decode(value string) error
}

Decoder interface to decode a string

type Setter

type Setter interface {
	Set(value string) error
}

Setter interface to set a string value

Jump to

Keyboard shortcuts

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