-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Elastic-Agent] Enable introspecting configuration (#18124)
* introspection * changelog * mage fmt * introspect -> inspect * follow -c argument * conflicts
- Loading branch information
1 parent
6ea21a9
commit 1c2e4b9
Showing
6 changed files
with
418 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
x-pack/elastic-agent/pkg/agent/application/introspect_config_cmd.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package application | ||
|
||
import ( | ||
"fmt" | ||
|
||
yaml "gopkg.in/yaml.v2" | ||
|
||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/info" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/storage" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/fleetapi" | ||
) | ||
|
||
// IntrospectConfigCmd is an introspect subcommand that shows configurations of the agent. | ||
type IntrospectConfigCmd struct { | ||
cfgPath string | ||
} | ||
|
||
// NewIntrospectConfigCmd creates a new introspect command. | ||
func NewIntrospectConfigCmd(configPath string, | ||
) (*IntrospectConfigCmd, error) { | ||
return &IntrospectConfigCmd{ | ||
cfgPath: configPath, | ||
}, nil | ||
} | ||
|
||
// Execute introspects agent configuration. | ||
func (c *IntrospectConfigCmd) Execute() error { | ||
return c.introspectConfig() | ||
} | ||
|
||
func (c *IntrospectConfigCmd) introspectConfig() error { | ||
cfg, err := loadConfig(c.cfgPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
isLocal, err := isLocalMode(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if isLocal { | ||
return printConfig(cfg) | ||
} | ||
|
||
fleetConfig, err := loadFleetConfig(cfg) | ||
if err != nil { | ||
return err | ||
} else if fleetConfig == nil { | ||
return errors.New("no fleet config retrieved yet") | ||
} | ||
|
||
return printMapStringConfig(fleetConfig) | ||
} | ||
|
||
func loadConfig(configPath string) (*config.Config, error) { | ||
rawConfig, err := config.LoadYAML(configPath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := InjectAgentConfig(rawConfig); err != nil { | ||
return nil, err | ||
} | ||
|
||
return rawConfig, nil | ||
} | ||
|
||
func loadFleetConfig(cfg *config.Config) (map[string]interface{}, error) { | ||
log, err := newErrorLogger() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
as, err := newActionStore(log, storage.NewDiskStore(info.AgentActionStoreFile())) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, c := range as.Actions() { | ||
cfgChange, ok := c.(*fleetapi.ActionConfigChange) | ||
if !ok { | ||
continue | ||
} | ||
|
||
fmt.Println("Action ID:", cfgChange.ID()) | ||
return cfgChange.Config, nil | ||
} | ||
return nil, nil | ||
} | ||
|
||
func isLocalMode(rawConfig *config.Config) (bool, error) { | ||
c := localDefaultConfig() | ||
if err := rawConfig.Unpack(&c); err != nil { | ||
return false, errors.New(err, "initiating application") | ||
} | ||
|
||
managementConfig := struct { | ||
Mode string `config:"mode" yaml:"mode"` | ||
}{} | ||
|
||
if err := c.Management.Unpack(&managementConfig); err != nil { | ||
return false, errors.New(err, "initiating application") | ||
} | ||
return managementConfig.Mode == "local", nil | ||
} | ||
|
||
func printMapStringConfig(mapStr map[string]interface{}) error { | ||
data, err := yaml.Marshal(mapStr) | ||
if err != nil { | ||
return errors.New(err, "could not marshal to YAML") | ||
} | ||
|
||
fmt.Println(string(data)) | ||
return nil | ||
} | ||
|
||
func printConfig(cfg *config.Config) error { | ||
mapStr, err := cfg.ToMapStr() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return printMapStringConfig(mapStr) | ||
} |
211 changes: 211 additions & 0 deletions
211
x-pack/elastic-agent/pkg/agent/application/introspect_output_cmd.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package application | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/urso/ecslog" | ||
"github.com/urso/ecslog/backend" | ||
"github.com/urso/ecslog/backend/appender" | ||
"github.com/urso/ecslog/backend/layout" | ||
|
||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/filters" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/program" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/logger" | ||
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/plugin/app/monitoring/noop" | ||
) | ||
|
||
// IntrospectOutputCmd is an introspect subcommand that shows configurations of the agent. | ||
type IntrospectOutputCmd struct { | ||
cfgPath string | ||
output string | ||
program string | ||
} | ||
|
||
// NewIntrospectOutputCmd creates a new introspect command. | ||
func NewIntrospectOutputCmd(configPath, output, program string) (*IntrospectOutputCmd, error) { | ||
return &IntrospectOutputCmd{ | ||
cfgPath: configPath, | ||
output: output, | ||
program: program, | ||
}, nil | ||
} | ||
|
||
// Execute tries to enroll the agent into Fleet. | ||
func (c *IntrospectOutputCmd) Execute() error { | ||
if c.output == "" { | ||
return c.introspectOutputs() | ||
} | ||
|
||
return c.introspectOutput() | ||
} | ||
|
||
func (c *IntrospectOutputCmd) introspectOutputs() error { | ||
cfg, err := loadConfig(c.cfgPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
isLocal, err := isLocalMode(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
l, err := newErrorLogger() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if isLocal { | ||
return listOutputsFromConfig(l, cfg) | ||
} | ||
|
||
fleetConfig, err := loadFleetConfig(cfg) | ||
if err != nil { | ||
return err | ||
} else if fleetConfig == nil { | ||
return errors.New("no fleet config retrieved yet") | ||
} | ||
|
||
return listOutputsFromMap(l, fleetConfig) | ||
} | ||
|
||
func listOutputsFromConfig(log *logger.Logger, cfg *config.Config) error { | ||
programsGroup, err := getProgramsFromConfig(log, cfg) | ||
if err != nil { | ||
return err | ||
|
||
} | ||
|
||
for k := range programsGroup { | ||
fmt.Println(k) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func listOutputsFromMap(log *logger.Logger, cfg map[string]interface{}) error { | ||
c, err := config.NewConfigFrom(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return listOutputsFromConfig(log, c) | ||
} | ||
|
||
func (c *IntrospectOutputCmd) introspectOutput() error { | ||
cfg, err := loadConfig(c.cfgPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
l, err := newErrorLogger() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
isLocal, err := isLocalMode(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if isLocal { | ||
return printOutputFromConfig(l, c.output, c.program, cfg) | ||
} | ||
|
||
fleetConfig, err := loadFleetConfig(cfg) | ||
if err != nil { | ||
return err | ||
} else if fleetConfig == nil { | ||
return errors.New("no fleet config retrieved yet") | ||
} | ||
|
||
return printOutputFromMap(l, c.output, c.program, fleetConfig) | ||
} | ||
|
||
func printOutputFromConfig(log *logger.Logger, output, programName string, cfg *config.Config) error { | ||
programsGroup, err := getProgramsFromConfig(log, cfg) | ||
if err != nil { | ||
return err | ||
|
||
} | ||
|
||
for k, programs := range programsGroup { | ||
if k != output { | ||
continue | ||
} | ||
|
||
var programFound bool | ||
for _, p := range programs { | ||
if programName != "" && programName != p.Spec.Cmd { | ||
continue | ||
} | ||
|
||
programFound = true | ||
fmt.Printf("[%s] %s:\n", k, p.Spec.Cmd) | ||
printMapStringConfig(p.Configuration()) | ||
fmt.Println("---") | ||
} | ||
|
||
if !programFound { | ||
fmt.Printf("program '%s' is not recognized within output '%s', try running `elastic-agent introspect output` to find available outputs.\n", | ||
programName, | ||
output) | ||
} | ||
return nil | ||
} | ||
|
||
fmt.Printf("output '%s' is not recognized, try running `elastic-agent introspect output` to find available outputs.\n", output) | ||
|
||
return nil | ||
} | ||
|
||
func printOutputFromMap(log *logger.Logger, output, programName string, cfg map[string]interface{}) error { | ||
c, err := config.NewConfigFrom(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return printOutputFromConfig(log, output, programName, c) | ||
} | ||
|
||
func getProgramsFromConfig(log *logger.Logger, cfg *config.Config) (map[string][]program.Program, error) { | ||
monitor := noop.NewMonitor() | ||
router := &inmemRouter{} | ||
emit := emitter( | ||
log, | ||
router, | ||
&configModifiers{ | ||
Decorators: []decoratorFunc{injectMonitoring}, | ||
Filters: []filterFunc{filters.ConstraintFilter}, | ||
}, | ||
monitor, | ||
) | ||
|
||
if err := emit(cfg); err != nil { | ||
return nil, err | ||
} | ||
return router.programs, nil | ||
} | ||
|
||
type inmemRouter struct { | ||
programs map[string][]program.Program | ||
} | ||
|
||
func (r *inmemRouter) Dispatch(id string, grpProg map[routingKey][]program.Program) error { | ||
r.programs = grpProg | ||
return nil | ||
} | ||
|
||
func newErrorLogger() (*logger.Logger, error) { | ||
backend, err := appender.Console(backend.Error, layout.Text(true)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return ecslog.New(backend), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.