diff --git a/x-pack/elastic-agent/CHANGELOG.next.asciidoc b/x-pack/elastic-agent/CHANGELOG.next.asciidoc index 2f07abbda97c..af28608cc1cc 100644 --- a/x-pack/elastic-agent/CHANGELOG.next.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.next.asciidoc @@ -89,4 +89,5 @@ - Add status subcommand {pull}24856[24856] - Add leader_election provider for k8s {pull}24267[24267] - Add --fleet-server-service-token and FLEET_SERVER_SERVICE_TOKEN options {pull}25083[25083] +- Keep http and logging config during enroll {pull}25132[25132] - Log output of container to $LOGS_PATH/elastic-agent-start.log when LOGS_PATH set {pull}25150[25150] diff --git a/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go b/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go index c560a7102715..b0011bd7352a 100644 --- a/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go +++ b/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go @@ -19,6 +19,7 @@ import ( "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" + monitoringConfig "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/monitoring/config" ) // defaultAgentConfigFile is a name of file used to store agent information @@ -27,8 +28,9 @@ const defaultLogLevel = "info" const maxRetriesloadAgentInfo = 5 type persistentAgentInfo struct { - ID string `json:"id" yaml:"id" config:"id"` - LogLevel string `json:"logging.level,omitempty" yaml:"logging.level,omitempty" config:"logging.level,omitempty"` + ID string `json:"id" yaml:"id" config:"id"` + LogLevel string `json:"logging.level,omitempty" yaml:"logging.level,omitempty" config:"logging.level,omitempty"` + MonitoringHTTP *monitoringConfig.MonitoringHTTPConfig `json:"monitoring.http,omitempty" yaml:"monitoring.http,omitempty" config:"monitoring.http,omitempty"` } type ioStore interface { @@ -90,7 +92,8 @@ func getInfoFromStore(s ioStore, logLevel string) (*persistentAgentInfo, error) agentInfoSubMap, found := configMap[agentInfoKey] if !found { return &persistentAgentInfo{ - LogLevel: logLevel, + LogLevel: logLevel, + MonitoringHTTP: monitoringConfig.DefaultConfig().HTTP, }, nil } @@ -100,7 +103,8 @@ func getInfoFromStore(s ioStore, logLevel string) (*persistentAgentInfo, error) } pid := &persistentAgentInfo{ - LogLevel: logLevel, + LogLevel: logLevel, + MonitoringHTTP: monitoringConfig.DefaultConfig().HTTP, } if err := cc.Unpack(&pid); err != nil { return nil, errors.New(err, "failed to unpack stored config to map") diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go index 968af23c9fef..086742a816b9 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go @@ -184,9 +184,12 @@ func fleetToReader(agentInfo *info.AgentInfo, cfg *configuration.Configuration) configToStore := map[string]interface{}{ "fleet": cfg.Fleet, "agent": map[string]interface{}{ - "id": agentInfo.AgentID(), + "id": agentInfo.AgentID(), + "logging.level": cfg.Settings.LoggingConfig.Level, + "monitoring.http": cfg.Settings.MonitoringConfig.HTTP, }, } + data, err := yaml.Marshal(configToStore) if err != nil { return nil, err diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go index b4a8cb24afd8..9b51d4c36929 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go @@ -28,8 +28,10 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/control/proto" "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/core/authority" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/logger" + monitoringConfig "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/monitoring/config" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/process" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/fleetapi" fleetclient "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/fleetapi/client" @@ -62,6 +64,7 @@ type enrollCmd struct { configStore saver remoteConfig remote.Config agentProc *process.Info + configPath string } // enrollCmdFleetServerOption define all the supported enrollment options for bootstrapping with Fleet Server. @@ -149,6 +152,7 @@ func newEnrollCmdWithStore( log: log, options: options, configStore: store, + configPath: configPath, }, nil } @@ -156,6 +160,12 @@ func newEnrollCmdWithStore( func (c *enrollCmd) Execute(ctx context.Context) error { var err error defer c.stopAgent() // ensure its stopped no matter what + + persistentConfig, err := getPersistentConfig(c.configPath) + if err != nil { + return err + } + if c.options.FleetServer.ConnStr != "" { token, err := c.fleetServerBootstrap(ctx) if err != nil { @@ -182,7 +192,7 @@ func (c *enrollCmd) Execute(ctx context.Context) error { errors.M(errors.MetaKeyURI, c.options.URL)) } - err = c.enrollWithBackoff(ctx) + err = c.enrollWithBackoff(ctx, persistentConfig) if err != nil { return errors.New(err, "fail to enroll") } @@ -323,10 +333,10 @@ func (c *enrollCmd) daemonReload(ctx context.Context) error { return daemon.Restart(ctx) } -func (c *enrollCmd) enrollWithBackoff(ctx context.Context) error { +func (c *enrollCmd) enrollWithBackoff(ctx context.Context, persistentConfig map[string]interface{}) error { delay(ctx, enrollDelay) - err := c.enroll(ctx) + err := c.enroll(ctx, persistentConfig) signal := make(chan struct{}) backExp := backoff.NewExpBackoff(signal, 60*time.Second, 10*time.Minute) @@ -344,14 +354,14 @@ func (c *enrollCmd) enrollWithBackoff(ctx context.Context) error { } backExp.Wait() c.log.Info("Retrying to enroll...") - err = c.enroll(ctx) + err = c.enroll(ctx, persistentConfig) } close(signal) return err } -func (c *enrollCmd) enroll(ctx context.Context) error { +func (c *enrollCmd) enroll(ctx context.Context, persistentConfig map[string]interface{}) error { cmd := fleetapi.NewEnrollCmd(c.client) metadata, err := info.Metadata() @@ -380,15 +390,12 @@ func (c *enrollCmd) enroll(ctx context.Context) error { if err != nil { return err } - agentConfig := map[string]interface{}{ - "id": resp.Item.ID, - } - if c.options.Staging != "" { - staging := fmt.Sprintf("https://staging.elastic.co/%s-%s/downloads/", release.Version(), c.options.Staging[:8]) - agentConfig["download"] = map[string]interface{}{ - "sourceURI": staging, - } + + agentConfig, err := c.createAgentConfig(resp.Item.ID, persistentConfig) + if err != nil { + return err } + if c.options.FleetServer.ConnStr != "" { serverConfig, err := createFleetServerBootstrapConfig( c.options.FleetServer.ConnStr, c.options.FleetServer.ServiceToken, @@ -751,3 +758,57 @@ func createFleetConfigFromEnroll(accessAPIKey string, cli remote.Config) (*confi } return cfg, nil } + +func (c *enrollCmd) createAgentConfig(agentID string, pc map[string]interface{}) (map[string]interface{}, error) { + agentConfig := map[string]interface{}{ + "id": agentID, + } + + if c.options.Staging != "" { + staging := fmt.Sprintf("https://staging.elastic.co/%s-%s/downloads/", release.Version(), c.options.Staging[:8]) + agentConfig["download"] = map[string]interface{}{ + "sourceURI": staging, + } + } + + for k, v := range pc { + agentConfig[k] = v + } + + return agentConfig, nil +} + +func getPersistentConfig(pathConfigFile string) (map[string]interface{}, error) { + persistentMap := make(map[string]interface{}) + rawConfig, err := config.LoadFile(pathConfigFile) + if os.IsNotExist(err) { + return persistentMap, nil + } + if err != nil { + return nil, errors.New(err, + fmt.Sprintf("could not read configuration file %s", pathConfigFile), + errors.TypeFilesystem, + errors.M(errors.MetaKeyPath, pathConfigFile)) + } + + pc := &struct { + LogLevel string `json:"agent.logging.level,omitempty" yaml:"agent.logging.level,omitempty" config:"agent.logging.level,omitempty"` + MonitoringHTTP *monitoringConfig.MonitoringHTTPConfig `json:"agent.monitoring.http,omitempty" yaml:"agent.monitoring.http,omitempty" config:"agent.monitoring.http,omitempty"` + }{ + MonitoringHTTP: monitoringConfig.DefaultConfig().HTTP, + } + + if err := rawConfig.Unpack(&pc); err != nil { + return nil, err + } + + if pc.LogLevel != "" { + persistentMap["logging.level"] = pc.LogLevel + } + + if pc.MonitoringHTTP != nil { + persistentMap["monitoring.http"] = pc.MonitoringHTTP + } + + return persistentMap, nil +}