Usage
Basic Usage and Examples
Declare your configuration and run Configure[]()
package main
import (
"fmt"
"net"
co "github.com/imoore76/configurature"
)
type AppConfig struct {
ListenIP net.IP `help:"IP address on which to listen" default:"127.0.0.1"`
ListenPort uint `help:"port on which to listen" default:"8080"`
}
func main() {
conf := co.Configure[AppConfig](nil)
fmt.Printf("IP: %s\n", conf.ListenIP)
fmt.Printf("Port: %d\n", conf.ListenPort)
}
The tags help provide help text for the fields.
default specifies a default value.
See also
See Tags for a complete list of tags.
Help text
Running this app with --help displays the app usage:
user@host $ myapp --help
Command usage:
-h, --help show help and exit
--listen_ip ip IP address on which to listen (default 127.0.0.1)
--listen_port uint port on which to listen (default 8080)
Specifying Config Values
The following methods can be used to set configuration values in order of precedence.
Default Value
The default value (if specified) in the struct field’s
default tag will be used
if no other value is specified.
type AppConfig struct {
ListenIP net.IP `help:"IP address on which to listen" default:"127.0.0.1"`
ListenPort uint `help:"port on which to listen" default:"8080"`
}
user@host ~$ myapp
IP: 127.0.0.1
Port: 8080
Without a default value, the zero value of the type will be used.
CLI Flags
Flags can be specified on the command line. Short flags are also supported
by adding a short:"x" tag.
type AppConfig struct {
ListenIP net.IP `help:"IP address on which to listen" short:"i" default:"127.0.0.1"`
ListenPort uint `help:"port on which to listen" default:"8080"`
}
user@host ~$ myapp -i 2.2.2.2
IP: 2.2.2.2
Port: 8080
user@host ~$ myapp --listen_ip 0.0.0.0
IP: 0.0.0.0
Port: 8080
Environment variables
You can also use environment variables in the form of uppercase arguments
prefixed with the EnvPrefix option.
type AppConfig struct {
ListenIP net.IP `help:"IP address on which to listen" short:"i" default:"127.0.0.1"`
ListenPort uint `help:"port on which to listen" default:"8080"`
}
conf := co.Configure[AppConfig](&co.Options{
EnvPrefix: "MYAPP_",
})
user@host ~$ MYAPP_LISTEN_PORT=443 myapp --listen_ip 0.0.0.0
IP: 0.0.0.0
Port: 443
See also
See the --print_env_template flag documented in Using env files.
This can be used to list all the environment variables that can be set.
Using .env files
Configurature itself does not provide anything that
parses .env files since there are many other tools
that have filled this space. Here are a couple favorites:
godotenv - https://github.com/joho/godotenv
direnv - https://direnv.net/
Since Configurature automatically uses environment variables,
there is no further action needed after loading environment variables from a .env file.
To create a template .env file, you can run your app with a --print_env_template flag.
This flag is hidden so won’t appear in your app’s Usage() text when using --help.
user@host ~$ myapp --print_env_template
# IP address on which to listen (default 127.0.0.1)
APP_LISTEN_IP="127.0.0.1"
# port on which to listen (default 8080)
APP_LISTEN_PORT="8080"
Copy and paste, or redirect its output to a .env file,
then edit as needed.
Config Files
A config file can be added by adding a special ConfigFile field to the
configuration struct. ConfigFile is part of the configurature package.
type AppConfig struct {
ListenIP net.IP `help:"IP address on which to listen" default:"127.0.0.1"`
ListenPort uint `help:"port on which to listen" default:"8080"`
Conf co.ConfigFile `help:"configuration file" short:"c"`
}
The example above also adds a short tag to specify a short version of the option.
user@host ~$ myapp -h
Command usage:
-c, --conf configFile configuration file
-h, --help show help and exit
--listen_ip ip IP address on which to listen (default 127.0.0.1)
--listen_port uint port on which to listen (default 8080)
Supported configuration file formats are yaml and json
(determined by file extension). Adding the configuration options
to a conf.yaml file looks like
# conf.yaml
listen_ip: 0.0.0.0
listen_port: 80
user@host ~$ myapp -c conf.yaml
IP: 0.0.0.0
Port: 80
Resolution order of values is command line, environment variable, and finally configuration file.
Generating Config Files
You can use the internal hidden flag --print_yaml_template
to generate a YAML template file. Specifying values along
with using the flag uses those values for the configuration
file output.
user@host ~$ myapp --listen_ip 0.0.0.0 --print_yaml_template
# Generated from
# [--listen_ip 0.0.0.0 --print_yaml_template]
# IP address on which to listen (default 127.0.0.1)
listen_ip: 0.0.0.0
# port on which to listen (default 8080)
listen_port: 8080
Copy and paste, or redirect its output to a .yaml file,
and edit as needed.
Slices
Slices are specified on the CLI and in environment variables in CSV format.
user@host ~$ myapp --ports="3144,5580"
user@host ~$ APP_PORTS="3144,5580" myapp
In configuration files, slices can be specified as lists.
# config.yaml
ports:
- 3144
- 5580
Maps
Maps are specified on the CLI and in environment variables in key=value format.
user@host ~$ myapp --codes="red=5,yellow=3"
user@host ~$ APP_CODES="red=5,yellow=3" myapp
In configuration files, maps can be specified as dictionaries.
# config.yaml
codes:
red: 5
yellow: 3
Options
Configure[]() can be called with an Options pointer as input.
// Config options
type Options struct {
EnvPrefix string // Prefix for environment variables
Args []string // Arguments to parse
NilPtrs bool // Leave pointers set to nil if values aren't specified
Usage func(*flag.FlagSet) // Usage function called when configuration is incorrect or for --help
NoRecover bool // Don't recover from panic
ShowInternalFlags bool // Show hidden internal flags
NoShortHelp bool // Don't add "h" as a short help flag
RequireNoDefaults bool // Require any fields that don't have a default value
}
If not specified, the defaults are:
Options{
EnvPrefix: "",
Args: os.Args[1:],
NilPtrs: false,
Usage: // internally composed
NoRecover: false,
ShowInternalFlags: false,
NoShortHelp: false,
RequireNoDefaults: false
}
EnvPrefix
The prefix to use when checking for configuration values specified as environment variables.
Important
If not set, Configurature will not use environment variables.
Args
The string of arguments to parse. Typically this would be set to,
and defaults to os.Args[1:] (the first element of os.Args
is the name of the command being run, so is not included).
NilPtrs
When using config field pointers, leave them set to nil rather than a zero
value if no value is specified and no default is set.
type Config struct {
MaxConns *int `help:"Max number of connections"`
ListenPort *int `help:"Port on which to listen" default:"8080"`
}
conf := co.Configure[Config](&co.Opts{
NilPtrs: true,
})
if conf.MaxConns != nil {
fmt.Printf("MaxConns is %d\n", *conf.MaxConns)
}
fmt.Printf("ListenPort is %d\n", *conf.ListenPort)
This would result in ListenPort is 8080 since no value was specified and no default was provided for MaxConns. With the default behavior, MaxConns would be a pointer to a zero value (0 for ints).
NoRecover
The default behavior is to handle a panic() that occurs
during parsing, print its message to os.Stderr and exit.
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "error parsing configuration: %s\n", r)
os.Exit(1)
}
You can disable this behavior by setting NoRecover to true.
You may then handle panics in your app however you’d like.
var err error = nil
var conf *AppConfig
func() {
defer func() {
if r := recover(); r != nil {
err = errors.New(r.(string))
}
}()
conf = co.Configure[AppConfig](&co.Options{
EnvPrefix: "APP_",
Args: os.Args[1:],
NoRecover: true,
})
}()
if err != nil {
// custom handling
}
ShowInternalFlags
Show internal flags --print_env_template and --print_yaml_template in
Usage() text.
Usage
Create and specify your own handler for command usage help. This occurs when incorrect configuration
flags are supplied or for --help.
The default Usage function is
func(f *pflag.FlagSet) {
fmt.Println("Command usage:")
fmt.Println(f.FlagUsages())
os.Exit(0)
}
NoShortHelp
Do not add -h as a short flag for help. This may be useful if there is a field that you want to use
-h for.
type Config struct {
HangTime time.Duration `help:"Time to hang" short:"h" default:"1m"`
}
func main() {
conf := co.Configure[Config](&co.Options{
NoShortHelp: true,
})
fmt.Println(conf.HangTime)
}
user@host ~$ myapp --help
Command usage:
-h, --hang_time duration Time to hang (default 1m0s)
--help show help and exit
user@host ~$ myapp -h 2h
2h0m0s
RequireNoDefaults
Make all fields that do not have a default value required.
type Config struct {
HangTime time.Duration `default:"1m"`
JumpTime time.Duration
Name string
}
func main() {
conf := co.Configure[Config](&co.Options{
RequireNoDefaults: true,
})
...
}
user@host ~$ myapp --jump_time 10s
error parsing configuration: name is required
exit status 1