Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support loading configuration from both YAML files and env vars #831

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/goccy/go-yaml v1.13.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/icinga/icinga-go-library v0.4.0
github.com/icinga/icinga-go-library v0.5.0
github.com/jessevdk/go-flags v1.6.1
github.com/jmoiron/sqlx v1.4.0
github.com/mattn/go-sqlite3 v1.14.24
Expand All @@ -23,7 +23,7 @@ require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/caarlos0/env/v11 v11.2.2 // indirect
github.com/caarlos0/env/v11 v11.3.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA=
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creasty/defaults v1.8.0 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk=
Expand All @@ -36,8 +36,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/icinga/icinga-go-library v0.4.0 h1:awAHVXbR8ubmKiq7RuIZCm/7xWM7pLLI8TnnPC4HNYE=
github.com/icinga/icinga-go-library v0.4.0/go.mod h1:lnJBQWTyAJITSPA4k6MvvkmMzwjOM7r2gf2pOdCLRr4=
github.com/icinga/icinga-go-library v0.5.0 h1:ECPgrGTb1i5OJ1he7ZgQt56FRHOpIFND+aLsbfUvZc8=
github.com/icinga/icinga-go-library v0.5.0/go.mod h1:0PTW/N+Xio77P0QnxxMQeqRrETsJ8cVoFs88V4nDA3M=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
Expand Down
5 changes: 4 additions & 1 deletion internal/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ func New() *Command {
}

var cfg icingadbconfig.Config
if err := config.FromYAMLFile(flags.Config, &cfg); err != nil {
if err := config.Load(&cfg, config.LoadOptions{
Flags: flags,
EnvOptions: config.EnvOptions{Prefix: "ICINGADB_"},
}); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works as far as I have tested it.

However, the error output may be misleading for a non-existing /etc/icingadb/config.yml file when not explicitly setting the --config flag, relying on the default.

$ stat /etc/icingadb/config.yml
stat: cannot statx '/etc/icingadb/config.yml': No such file or directory

$ ./icingadb
invalid configuration: database host missing
$ ./icingadb -c /etc/icingadb/config.yml
can't open YAML file /etc/icingadb/config.yml: open /etc/icingadb/config.yml: no such file or directory

If there are no ICINGADB_ environment variables and the default config is not existing, the reported error does not state that the expected file does not exist, but says that certain fields are absent. But honestly, I don't know how to address this. For a package installations the config file should be present.

if errors.Is(err, config.ErrInvalidArgument) {
panic(err)
}
Expand Down
38 changes: 32 additions & 6 deletions internal/config/config.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the config_test.go file, testing against the now unused config.FromYAMLFile function. Maybe you want to remove this test case and create another one for YAML-only, environment-only, and mixed-setups.

Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import (
"time"
)

// DefaultConfigPath specifies the default location of Icinga DB's config.yml for package installations.
const DefaultConfigPath = "/etc/icingadb/config.yml"

// Config defines Icinga DB config.
type Config struct {
Database database.Config `yaml:"database"`
Redis redis.Config `yaml:"redis"`
Logging logging.Config `yaml:"logging"`
Retention RetentionConfig `yaml:"retention"`
Database database.Config `yaml:"database" envPrefix:"DATABASE_"`
Redis redis.Config `yaml:"redis" envPrefix:"REDIS_"`
Logging logging.Config `yaml:"logging" envPrefix:"LOGGING_"`
Retention RetentionConfig `yaml:"retention" envPrefix:"RETENTION_"`
}

func (c *Config) SetDefaults() {
Expand Down Expand Up @@ -46,11 +49,34 @@ func (c *Config) Validate() error {
}

// Flags defines CLI flags.
//
// Flags implements the [github.com/icinga/icinga-go-library/config.Flags] interface.
type Flags struct {
oxzi marked this conversation as resolved.
Show resolved Hide resolved
// Version decides whether to just print the version and exit.
Version bool `long:"version" description:"print version and exit"`
// Config is the path to the config file
Config string `short:"c" long:"config" description:"path to config file" required:"true" default:"/etc/icingadb/config.yml"`

// Config is the path to the config file. If not provided, it defaults to DefaultConfigPath.
Config string `short:"c" long:"config" description:"path to config file (default: /etc/icingadb/config.yml)"`
// default must be kept in sync with DefaultConfigPath.
}

// GetConfigPath retrieves the path to the configuration file.
// It returns the path specified via the command line, or DefaultConfigPath if none is provided.
//
// GetConfigPath implements parts of the [github.com/icinga/icinga-go-library/config.Flags] interface.
func (f Flags) GetConfigPath() string {
if f.Config == "" {
return DefaultConfigPath
}
oxzi marked this conversation as resolved.
Show resolved Hide resolved

return f.Config
}

// IsExplicitConfigPath indicates whether the configuration file path was explicitly set.
//
// IsExplicitConfigPath implements parts of the [github.com/icinga/icinga-go-library/config.Flags] interface.
func (f Flags) IsExplicitConfigPath() bool {
return f.Config != ""
oxzi marked this conversation as resolved.
Show resolved Hide resolved
}

// RetentionConfig defines configuration for history retention.
Expand Down
Loading