Documentation
¶
Overview ¶
Package config provides utilities for configuration parsing and loading. It includes functionality for handling command-line flags and loading configuration from YAML files and environment variables, with additional support for setting default values and validation. Additionally, it provides a struct that defines common settings for a TLS client.
Index ¶
- Variables
- func FromEnv(v Validator, options EnvOptions) error
- func FromYAMLFile(name string, v Validator) error
- func Load(v Validator, options LoadOptions) error
- func LoadPasswordFile(password *string, passwordFile string) error
- func ParseFlags(v any) error
- type EnvOptions
- type Flags
- type LoadOptions
- type TLS
- type Validator
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidArgument = stderrors.New("invalid argument")
ErrInvalidArgument is the error returned by any function that loads configuration if the parsing result cannot be stored in the value pointed to by the specified argument, which must be a non-nil struct pointer.
var ErrInvalidConfiguration = stderrors.New("invalid configuration")
ErrInvalidConfiguration is attached to errors returned by any function that loads configuration when the configuration is invalid, i.e. if the Validate method of the provided Validator interface returns an error, which is then propagated by these functions. Note that for such errors, errors.Is() will recognize both ErrInvalidConfiguration and the original errors returned from Validate.
Functions ¶
func FromEnv ¶ added in v0.4.0
func FromEnv(v Validator, options EnvOptions) error
FromEnv parses environment variables and stores the result in the value pointed to by v. If v is nil or not a struct pointer, FromEnv returns an ErrInvalidArgument error.
It is possible to define default values via the struct tag `default`.
The function also validates the configuration using the Validate method of the provided Validator interface. Any error returned from Validate is propagated with ErrInvalidConfiguration attached, allowing errors.Is() checks on the returned errors to recognize both ErrInvalidConfiguration and the original errors returned from Validate.
Example usage:
type Config struct {
ServerAddress string `env:"SERVER_ADDRESS" default:"localhost:8080"`
TLS config.TLS
}
func (c *Config) Validate() error {
if _, _, err := net.SplitHostPort(c.ServerAddress); err != nil {
return errors.Wrapf(err, "invalid server address: %s", c.ServerAddress)
}
if err := c.TLS.Validate(); err != nil {
return errors.WithStack(err)
}
return nil
}
func main() {
var cfg Config
if err := config.FromEnv(cfg, config.EnvOptions{}); err != nil {
log.Fatalf("error loading config: %v", err)
}
tlsCfg, err := cfg.TLS.MakeConfig("icinga.com")
if err != nil {
log.Fatalf("error creating TLS config: %v", err)
}
// ...
}
func FromYAMLFile ¶
FromYAMLFile parses the given YAML file and stores the result in the value pointed to by v. If v is nil or not a struct pointer, FromYAMLFile returns an ErrInvalidArgument error.
It is possible to define default values via the struct tag `default`.
The function also validates the configuration using the Validate method of the provided Validator interface. Any error returned from Validate is propagated with ErrInvalidConfiguration attached, allowing errors.Is() checks on the returned errors to recognize both ErrInvalidConfiguration and the original errors returned from Validate.
Example usage:
type Config struct {
ServerAddress string `yaml:"server_address" default:"localhost:8080"`
TLS config.TLS `yaml:",inline"`
}
func (c *Config) Validate() error {
if _, _, err := net.SplitHostPort(c.ServerAddress); err != nil {
return errors.Wrapf(err, "invalid server address: %s", c.ServerAddress)
}
if err := c.TLS.Validate(); err != nil {
return errors.WithStack(err)
}
return nil
}
func main() {
var cfg Config
if err := config.FromYAMLFile("config.yml", &cfg); err != nil {
log.Fatalf("error loading config: %v", err)
}
tlsCfg, err := cfg.TLS.MakeConfig("icinga.com")
if err != nil {
log.Fatalf("error creating TLS config: %v", err)
}
// ...
}
func Load ¶ added in v0.5.0
func Load(v Validator, options LoadOptions) error
Load loads configuration from both YAML files and environment variables and stores the result in the value pointed to by v. If v is nil or not a struct pointer, Load returns an ErrInvalidArgument error.
It is possible to define default values via the struct tag `default`.
The function also validates the configuration using the Validate method of the provided Validator interface. Any error returned from Validate is propagated with ErrInvalidConfiguration attached, allowing errors.Is() checks on the returned errors to recognize both ErrInvalidConfiguration and the original errors returned from Validate.
This function handles configuration loading in three scenarios:
- Load configuration exclusively from YAML files when no applicable environment variables are set.
- Combine YAML file and environment variable configurations, allowing environment variables to supplement or override possible incomplete YAML data.
- Load entirely from environment variables if the default YAML config file is missing and no specific config path is provided.
Example usage:
const DefaultConfigPath = "/path/to/config.yml"
type Flags struct {
Config string `short:"c" long:"config" description:"Path to config file"`
}
func (f Flags) GetConfigPath() string {
if f.Config == "" {
return DefaultConfigPath
}
return f.Config
}
func (f Flags) IsExplicitConfigPath() bool {
return f.Config != ""
}
type Config struct {
ServerAddress string `yaml:"server_address" env:"SERVER_ADDRESS" default:"localhost:8080"`
TLS config.TLS `yaml:",inline"`
}
func (c *Config) Validate() error {
if _, _, err := net.SplitHostPort(c.ServerAddress); err != nil {
return errors.Wrapf(err, "invalid server address: %s", c.ServerAddress)
}
if err := c.TLS.Validate(); err != nil {
return errors.WithStack(err)
}
return nil
}
func main() {
var flags Flags
if err := config.ParseFlags(&flags); err != nil {
log.Fatalf("error parsing flags: %v", err)
}
var cfg Config
if err := config.Load(&cfg, config.LoadOptions{Flags: flags, EnvOptions: config.EnvOptions{}}); err != nil {
log.Fatalf("error loading config: %v", err)
}
tlsCfg, err := cfg.TLS.MakeConfig("icinga.com")
if err != nil {
log.Fatalf("error creating TLS config: %v", err)
}
// ...
}
func LoadPasswordFile ¶ added in v0.9.0
LoadPasswordFile populates the password field from the content of a password file.
This is a helper function to be used in Validator.Validate implementations on types where both a password and a password file field are available. If both a password and a password file are given, an error is returned.
func ParseFlags ¶
ParseFlags parses CLI flags and stores the result in the value pointed to by v. If v is nil or not a struct pointer, ParseFlags returns an ErrInvalidArgument error.
ParseFlags adds a default Help Options group, which contains the options -h and --help. If either option is specified on the command line, ParseFlags prints the help message to os.Stdout and exits.
Note that errors are not printed automatically, so error handling is the sole responsibility of the caller.
Example usage:
type Flags struct {
Config string `short:"c" long:"config" description:"Path to config file" required:"true"`
}
func main() {
var flags Flags
if err := config.ParseFlags(&flags); err != nil {
log.Fatalf("error parsing flags: %v", err)
}
// ...
}
Types ¶
type EnvOptions ¶ added in v0.4.0
EnvOptions is a type alias for env.Options, so that only this package needs to import env.
type Flags ¶ added in v0.5.0
type Flags interface {
// GetConfigPath retrieves the path to the configuration file as specified by command line flags,
// or returns a default path if none was provided.
GetConfigPath() string
// IsExplicitConfigPath indicates whether the configuration file path was
// explicitly set through command line flags.
IsExplicitConfigPath() bool
}
Flags is an interface that provides methods related to access the configuration file path specified via command line flags. This interface is meant to be implemented by flag structs containing a switch for the configuration file path.
type LoadOptions ¶ added in v0.5.0
type LoadOptions struct {
// Flags provides access to specific command line flag values.
Flags Flags
// EnvOptions contains options for loading configuration from environment variables.
EnvOptions EnvOptions
}
LoadOptions contains options for loading configuration from both files and environment variables.
type TLS ¶
type TLS struct {
// Enable indicates whether TLS is enabled.
Enable bool `yaml:"tls" env:"TLS"`
// Cert is either the path to the TLS certificate file or a raw PEM-encoded string representing it.
// If provided, Key must also be specified.
Cert string `yaml:"cert" env:"CERT"`
// Key is either the path to the TLS key file or a raw PEM-encoded string representing it.
// If specified, Cert must also be provided.
Key string `yaml:"key" env:"KEY,unset"`
// Ca is either the path to the CA certificate file or a raw PEM-encoded string representing it.
Ca string `yaml:"ca" env:"CA"`
// Insecure indicates whether to skip verification of the server's certificate chain and host name.
// If true, any certificate presented by the server and any host name in that certificate is accepted.
// In this mode, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used.
Insecure bool `yaml:"insecure" env:"INSECURE"`
}
TLS represents configuration for a TLS client. It provides options to enable TLS, specify certificate and key files, CA certificate, and whether to skip verification of the server's certificate chain and host name. Use the TLS.MakeConfig method to assemble a *tls.Config from the TLS struct.
Example usage:
func main() {
tlsConfig := &config.TLS{
Enable: true,
Cert: "path/to/cert.pem",
Key: "path/to/key.pem",
Ca: "path/to/ca.pem",
Insecure: false,
}
cfg, err := tlsConfig.MakeConfig("example.com")
if err != nil {
log.Fatalf("error creating TLS config: %v", err)
}
// ...
}
func (*TLS) MakeConfig ¶
MakeConfig assembles a *tls.Config from the TLS struct and the provided serverName. It returns a configured *tls.Config or an error if there are issues with the provided TLS settings. If TLS is not enabled (t.Enable is false), it returns nil without an error.
type Validator ¶
type Validator interface {
// Validate checks the configuration values and
// returns an error if any value is invalid or missing when required.
Validate() error
}
Validator is an interface that must be implemented by any struct into which configuration is intended to be loaded.
The Validate method checks the configuration values and returns an error if any value is invalid or missing when required.
For fields such as file paths, the responsibility of Validate is limited to verifying the presence and format of the value, not checking external conditions like file existence or readability. This principle applies generally to any field where external validation (e.g., network availability, resource accessibility) is beyond the scope of basic configuration validation.