diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 25e2fa6fe08..d5941259ce6 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -52,6 +52,7 @@ https://github.com/elastic/beats/compare/v5.0.0-alpha4...master[Check the HEAD d - Add enable-setting to all output modules. {pull}1987[1987] - Command line flag -c can be used multiple times. {pull}1985[1985] - Add OR/AND/NOT to the condition associated with the processors. {pull}1983[1983] +- Add '-E' CLI flag for overwriting single config options via command line. {pull}1986[1986] *Metricbeat* diff --git a/libbeat/cfgfile/cfgfile.go b/libbeat/cfgfile/cfgfile.go index 27b6fda982c..3802cc06e50 100644 --- a/libbeat/cfgfile/cfgfile.go +++ b/libbeat/cfgfile/cfgfile.go @@ -15,6 +15,7 @@ var ( // when this variable is created. See ChangeDefaultCfgfileFlag which should // be called prior to flags.Parse(). configfiles = flagArgList("c", "beat.yml", "Configuration file") + overwrites = common.NewFlagConfig(nil, nil, "E", "Configuration overwrite") testConfig = flag.Bool("configtest", false, "Test configuration and exit.") ) @@ -51,10 +52,23 @@ func Read(out interface{}, path string) error { // this method reads from the configuration file specified by the '-c' command // line flag. func Load(path string) (*common.Config, error) { + var config *common.Config + var err error + if path == "" { - return common.LoadFiles(configfiles.list...) + config, err = common.LoadFiles(configfiles.list...) + } else { + config, err = common.LoadFile(path) + } + if err != nil { + return nil, err + } + + err = config.Merge(overwrites) + if err != nil { + return nil, err } - return common.LoadFile(path) + return config, nil } // IsTestConfig returns whether or not this is configuration used for testing diff --git a/libbeat/common/config.go b/libbeat/common/config.go index 420ad1f4a73..a1c857b4b37 100644 --- a/libbeat/common/config.go +++ b/libbeat/common/config.go @@ -1,8 +1,11 @@ package common import ( + "flag" + "github.com/elastic/go-ucfg" "github.com/elastic/go-ucfg/cfgutil" + cfgflag "github.com/elastic/go-ucfg/flag" "github.com/elastic/go-ucfg/yaml" ) @@ -34,6 +37,28 @@ func NewConfigWithYAML(in []byte, source string) (*Config, error) { return fromConfig(c), err } +func NewFlagConfig( + set *flag.FlagSet, + def *Config, + name string, + usage string, +) *Config { + opts := append( + []ucfg.Option{ + ucfg.MetaData(ucfg.Meta{"command line flag"}), + }, + configOpts..., + ) + + var to *ucfg.Config + if def != nil { + to = def.access() + } + + config := cfgflag.ConfigVar(set, to, name, usage, opts...) + return fromConfig(config) +} + func LoadFile(path string) (*Config, error) { c, err := yaml.NewConfigWithFile(path, configOpts...) return fromConfig(c), err diff --git a/libbeat/tests/system/test_base.py b/libbeat/tests/system/test_base.py index 8dad618ab31..c7c6ed8678a 100644 --- a/libbeat/tests/system/test_base.py +++ b/libbeat/tests/system/test_base.py @@ -39,6 +39,29 @@ def test_invalid_config(self): assert exit_code == 1 assert self.log_contains("error loading config file") is True + def test_invalid_config_cli_param(self): + """ + Checks CLI overwrite actually overwrites some config variable by + writing an invalid value. + """ + + self.render_config_template( + console={"pretty": "false"} + ) + + # first run with default config, validating config being + # actually correct. + proc = self.start_beat() + self.wait_until(lambda: self.log_contains("Setup Beat")) + proc.check_kill_and_wait() + + # start beat with invalid config setting on command line + exit_code = self.run_beat( + extra_args=["-E", "output.console=invalid"]) + + assert exit_code == 1 + assert self.log_contains("error unpacking config data") is True + def test_config_test(self): """ Checks if -configtest works as expected