A simple config manager for Go applications.
Use the following:
go get -u github.com/shivanshkc/confetti/v2
Confetti only has a few, but well implemented set of features. It makes it really easy to use and understand.
If your application fits the following use-case, Confetti is the best config manager you can get.
- The configs have to be loaded/unmarshalled into a struct.
- The configs are loaded once at application startup and do not change for the entire runtime of the application.
- The configs are loaded either from the environment or command-line flags (No JSON/YAML files or remote servers).
If your application agrees with the above restrictions, you can enjoy the following features of Confetti:
-
package main type Configs struct { Port string `def:"8080" env:"PORT" arg:"port"` }
This is all you need to make a struct usable with Confetti. Use the following code to load the configs:
import ( "fmt" "github.com/shivanshkc/confetti/v2" ) func main() { loader := confetti.NewDefLoader() configs := &Configs{} if err := loader.Load(configs); err != nil { panic(err) } fmt.Println("Configs:", configs) }
Here, as you may have guessed:
a. ThePort
config has the default value of8080
.
b. If the environment variablePORT
is provided, it will override the default value.
c. If the-port
or--port
flag is provided, it will override both the default value and the environment variable. -
If you use the code in the last point, and execute
go run main.go -h
, you will see the following on your console:Usage of configs: -port value Doc: not provided Default: 8080 Environment: PORT panic: failed to parse flags: flag: help requested
Confetti auto-generates this help documentation for your application using Go's
flag
package.
In the output above, notice theDoc: not provided
line. This is because we did not provide any doc on thePort
config. It can be provided as follows:type Configs struct { Port string `def:"8080" env:"PORT" arg:"port,HTTP server port"` }
Now, the output will read:
Usage of configs: -port value Doc: HTTP server port Default: 8080 Environment: PORT panic: failed to parse flags: flag: help requested
Next, you must be getting annoyed by the panic message at the bottom. This is because Go's
flag
package returns an error when a-h
or-help
flag is provided. To get rid of this, use the following:import ( "errors" "fmt" "github.com/shivanshkc/confetti/v2" ) func main() { loader := confetti.NewDefLoader() configs := &Configs{} if err := loader.Load(configs); err != nil { if errors.Is(err, flag.ErrHelp) { return } panic(err) } fmt.Println("Configs:", configs) }
-
Confetti is built to handle nested structs. Just make sure that the flag names for all fields are always different, otherwise you'll get a panic.
type Configs struct { HTTP struct { Port string `def:"8080" env:"HTTP_PORT" arg:"http-port"` } GRPC struct { Port string `def:"7070" env:"GRPC_PORT" arg:"grpc-port"` } }
The above struct is a completely valid Confetti target.
-
Confetti is built to handle all types of configs, and not just strings. Consider the following example:
type Configs struct { CORS struct { TrustedOrigins []string `def:"[\"google.com\"]" env:"TRUSTED_ORIGINS" arg:"trusted-origins"` } Pagination struct { DefaultLimit int `def:"100" env:"DEFAULT_LIMIT" arg:"default-limit"` } RedisDetails map[string]string `def:"{}" env:"REDIS_DETAILS" arg:"redis-details"` }
This struct is also a valid Confetti target. Just make sure that the value of the environment variable or flag is a valid JSON string, otherwise Confetti will give you an error.
Confetti exposes a NewLoader
function and a NewDefLoader
function (as used in the examples above).
The NewDefLoader
uses the default options, but users can provide their own options by using the NewLoader
function.
Here is the explanation of all available options:
Name | Description | Default value |
---|---|---|
Title | The title that shows up on help documentation. | configs |
DefTagName | The name of the tag that controls the default value. | def |
EnvTagName | The name of the tag that controls the env variable name. | env |
ArgTagName | The name of the tag that controls the flag name. | arg |
UseDotEnv | Whether to use the .env file if present. | false |