# 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 ofNOTAGS
and a cli ofN0TAGS
and have a description offlag: NOTAGS or env: NOTAGS
EnvConfig
will look for an env ofEX_CONF
and a cli ofEX_CONF
and have a description offlag: EX_CONF or env: EX_CONF
EnvCliConfig
will look for an env ofCONF
and a cli ofconf
and have a description offlag: conf or env: CONF
CliDesc
will look for an env ofCLIDESC
and a cli ofCliDesc
and have a description ofsimple 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 theenvconfig
tag on the fieldOptionJSONName
is used to set thejson
tag on the fieldOptionCLIName
is used to set theenvcli
tag on the fieldOptionCLIUsage
is used to set theclidesc
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.