feat(agent): Add config check sub-command (#15732)

This commit is contained in:
Sven Rebhan 2024-08-16 19:36:35 +02:00 committed by GitHub
parent 7b5462692b
commit 9342f839b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 79 additions and 24 deletions

View File

@ -120,7 +120,7 @@ func (a *Agent) Run(ctx context.Context) error {
} }
log.Printf("D! [agent] Initializing plugins") log.Printf("D! [agent] Initializing plugins")
if err := a.initPlugins(); err != nil { if err := a.InitPlugins(); err != nil {
return err return err
} }
@ -207,8 +207,8 @@ func (a *Agent) Run(ctx context.Context) error {
return err return err
} }
// initPlugins runs the Init function on plugins. // InitPlugins runs the Init function on plugins.
func (a *Agent) initPlugins() error { func (a *Agent) InitPlugins() error {
for _, input := range a.Config.Inputs { for _, input := range a.Config.Inputs {
// Share the snmp translator setting with plugins that need it. // Share the snmp translator setting with plugins that need it.
if tp, ok := input.Input.(snmp.TranslatorPlugin); ok { if tp, ok := input.Input.(snmp.TranslatorPlugin); ok {
@ -1003,8 +1003,7 @@ func (a *Agent) Test(ctx context.Context, wait time.Duration) error {
// inputs to run. // inputs to run.
func (a *Agent) runTest(ctx context.Context, wait time.Duration, outputC chan<- telegraf.Metric) error { func (a *Agent) runTest(ctx context.Context, wait time.Duration, outputC chan<- telegraf.Metric) error {
log.Printf("D! [agent] Initializing plugins") log.Printf("D! [agent] Initializing plugins")
err := a.initPlugins() if err := a.InitPlugins(); err != nil {
if err != nil {
return err return err
} }
@ -1017,6 +1016,7 @@ func (a *Agent) runTest(ctx context.Context, wait time.Duration, outputC chan<-
if len(a.Config.Aggregators) != 0 { if len(a.Config.Aggregators) != 0 {
procC := next procC := next
if len(a.Config.AggProcessors) != 0 && !a.Config.Agent.SkipProcessorsAfterAggregators { if len(a.Config.AggProcessors) != 0 && !a.Config.Agent.SkipProcessorsAfterAggregators {
var err error
procC, apu, err = a.startProcessors(next, a.Config.AggProcessors) procC, apu, err = a.startProcessors(next, a.Config.AggProcessors)
if err != nil { if err != nil {
return err return err
@ -1028,6 +1028,7 @@ func (a *Agent) runTest(ctx context.Context, wait time.Duration, outputC chan<-
var pu []*processorUnit var pu []*processorUnit
if len(a.Config.Processors) != 0 { if len(a.Config.Processors) != 0 {
var err error
next, pu, err = a.startProcessors(next, a.Config.Processors) next, pu, err = a.startProcessors(next, a.Config.Processors)
if err != nil { if err != nil {
return err return err
@ -1098,8 +1099,7 @@ func (a *Agent) Once(ctx context.Context, wait time.Duration) error {
// inputs to run. // inputs to run.
func (a *Agent) runOnce(ctx context.Context, wait time.Duration) error { func (a *Agent) runOnce(ctx context.Context, wait time.Duration) error {
log.Printf("D! [agent] Initializing plugins") log.Printf("D! [agent] Initializing plugins")
err := a.initPlugins() if err := a.InitPlugins(); err != nil {
if err != nil {
return err return err
} }

View File

@ -12,17 +12,18 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/influxdata/telegraf/agent"
"github.com/influxdata/telegraf/config" "github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/logger" "github.com/influxdata/telegraf/logger"
"github.com/influxdata/telegraf/migrations" "github.com/influxdata/telegraf/migrations"
) )
func getConfigCommands(pluginFilterFlags []cli.Flag, outputBuffer io.Writer) []*cli.Command { func getConfigCommands(configHandlingFlags []cli.Flag, outputBuffer io.Writer) []*cli.Command {
return []*cli.Command{ return []*cli.Command{
{ {
Name: "config", Name: "config",
Usage: "commands for generating and migrating configurations", Usage: "commands for generating and migrating configurations",
Flags: pluginFilterFlags, Flags: configHandlingFlags,
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
// The sub_Filters are populated when the filter flags are set after the subcommand config // The sub_Filters are populated when the filter flags are set after the subcommand config
// e.g. telegraf config --section-filter inputs // e.g. telegraf config --section-filter inputs
@ -32,6 +33,61 @@ func getConfigCommands(pluginFilterFlags []cli.Flag, outputBuffer io.Writer) []*
return nil return nil
}, },
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
{
Name: "check",
Usage: "check configuration file(s) for issues",
Description: `
The 'check' command reads the configuration files specified via '--config' or
'--config-directory' and tries to initialize, but not start, the plugins.
Syntax and semantic errors detectable without starting the plugins will
be reported.
If no configuration file is explicitly specified the command reads the
default locations and uses those configuration files.
To check the file 'mysettings.conf' use
> telegraf config check --config mysettings.conf
`,
Flags: configHandlingFlags,
Action: func(cCtx *cli.Context) error {
// Setup logging
logConfig := &logger.Config{Debug: cCtx.Bool("debug")}
if err := logger.SetupLogging(logConfig); err != nil {
return err
}
// Collect the given configuration files
configFiles := cCtx.StringSlice("config")
configDir := cCtx.StringSlice("config-directory")
for _, fConfigDirectory := range configDir {
files, err := config.WalkDirectory(fConfigDirectory)
if err != nil {
return err
}
configFiles = append(configFiles, files...)
}
// If no "config" or "config-directory" flag(s) was
// provided we should load default configuration files
if len(configFiles) == 0 {
paths, err := config.GetDefaultConfigPath()
if err != nil {
return err
}
configFiles = paths
}
// Load the config and try to initialize the plugins
c := config.NewConfig()
c.Agent.Quiet = cCtx.Bool("quiet")
if err := c.LoadAll(configFiles...); err != nil {
return err
}
ag := agent.NewAgent(c)
return ag.InitPlugins()
},
},
{ {
Name: "create", Name: "create",
Usage: "create a full sample configuration and show it", Usage: "create a full sample configuration and show it",
@ -49,7 +105,7 @@ InfluxDB v2 output plugin use
> telegraf config create --section-filter "inputs:outputs" --input-filter "modbus" --output-filter "influxdb_v2" > telegraf config create --section-filter "inputs:outputs" --input-filter "modbus" --output-filter "influxdb_v2"
`, `,
Flags: pluginFilterFlags, Flags: configHandlingFlags,
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
filters := processFilterFlags(cCtx) filters := processFilterFlags(cCtx)
@ -74,7 +130,7 @@ those files unattended!
To migrate the file 'mysettings.conf' use To migrate the file 'mysettings.conf' use
> telegraf --config mysettings.conf config migrate > telegraf config migrate --config mysettings.conf
`, `,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{ &cli.BoolFlag{

View File

@ -99,7 +99,15 @@ func deleteEmpty(s []string) []string {
// runApp defines all the subcommands and flags for Telegraf // runApp defines all the subcommands and flags for Telegraf
// this abstraction is used for testing, so outputBuffer and args can be changed // this abstraction is used for testing, so outputBuffer and args can be changed
func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfig, m App) error { func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfig, m App) error {
pluginFilterFlags := []cli.Flag{ configHandlingFlags := []cli.Flag{
&cli.StringSliceFlag{
Name: "config",
Usage: "configuration file to load",
},
&cli.StringSliceFlag{
Name: "config-directory",
Usage: "directory containing additional *.conf files",
},
&cli.StringFlag{ &cli.StringFlag{
Name: "section-filter", Name: "section-filter",
Usage: "filter the sections to print, separator is ':'. " + Usage: "filter the sections to print, separator is ':'. " +
@ -127,7 +135,7 @@ func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfi
}, },
} }
extraFlags := append(pluginFilterFlags, cliFlags()...) mainFlags := append(configHandlingFlags, cliFlags()...)
// This function is used when Telegraf is run with only flags // This function is used when Telegraf is run with only flags
action := func(cCtx *cli.Context) error { action := func(cCtx *cli.Context) error {
@ -247,7 +255,7 @@ func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfi
} }
commands := append( commands := append(
getConfigCommands(pluginFilterFlags, outputBuffer), getConfigCommands(configHandlingFlags, outputBuffer),
getSecretStoreCommands(m)..., getSecretStoreCommands(m)...,
) )
commands = append(commands, getPluginCommands(outputBuffer)...) commands = append(commands, getPluginCommands(outputBuffer)...)
@ -259,15 +267,6 @@ func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfi
Writer: outputBuffer, Writer: outputBuffer,
Flags: append( Flags: append(
[]cli.Flag{ []cli.Flag{
// String slice flags
&cli.StringSliceFlag{
Name: "config",
Usage: "configuration file to load",
},
&cli.StringSliceFlag{
Name: "config-directory",
Usage: "directory containing additional *.conf files",
},
// Int flags // Int flags
&cli.IntFlag{ &cli.IntFlag{
Name: "test-wait", Name: "test-wait",
@ -368,7 +367,7 @@ func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfi
Usage: "DEPRECATED: path to directory containing external plugins", Usage: "DEPRECATED: path to directory containing external plugins",
}, },
// !!! // !!!
}, extraFlags...), }, mainFlags...),
Action: action, Action: action,
Commands: append([]*cli.Command{ Commands: append([]*cli.Command{
{ {