diff --git a/x-pack/elastic-agent/CHANGELOG.next.asciidoc b/x-pack/elastic-agent/CHANGELOG.next.asciidoc index a132be48eab..ea33ac73ee2 100644 --- a/x-pack/elastic-agent/CHANGELOG.next.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.next.asciidoc @@ -78,3 +78,4 @@ - Add TLS support for Fleet Server {pull}24142[24142] - Add support for Fleet Server running under Elastic Agent {pull}24220[24220] - Add CA support to Elastic Agent docker image {pull}24486[24486] +- Add STATE_PATH, CONFIG_PATH, LOGS_PATH to Elastic Agent docker image {pull}24817[24817] diff --git a/x-pack/elastic-agent/pkg/agent/application/filters/stream_checker_test.go b/x-pack/elastic-agent/pkg/agent/application/filters/stream_checker_test.go index 893398fd6ea..961afb3e147 100644 --- a/x-pack/elastic-agent/pkg/agent/application/filters/stream_checker_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/filters/stream_checker_test.go @@ -249,7 +249,7 @@ func TestStreamCheck(t *testing.T) { }, } - log, err := logger.New("") + log, err := logger.New("", false) assert.NoError(t, err) for _, tc := range testCases { diff --git a/x-pack/elastic-agent/pkg/agent/application/fleet_server_bootstrap.go b/x-pack/elastic-agent/pkg/agent/application/fleet_server_bootstrap.go index 69e64fb5714..6f3dd09335b 100644 --- a/x-pack/elastic-agent/pkg/agent/application/fleet_server_bootstrap.go +++ b/x-pack/elastic-agent/pkg/agent/application/fleet_server_bootstrap.go @@ -56,7 +56,7 @@ func newFleetServerBootstrap( } if log == nil { - log, err = logger.NewFromConfig("", cfg.Settings.LoggingConfig) + log, err = logger.NewFromConfig("", cfg.Settings.LoggingConfig, false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/agent/application/gateway/fleet/fleet_gateway_test.go b/x-pack/elastic-agent/pkg/agent/application/gateway/fleet/fleet_gateway_test.go index 2c70937a454..f0254a17450 100644 --- a/x-pack/elastic-agent/pkg/agent/application/gateway/fleet/fleet_gateway_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/gateway/fleet/fleet_gateway_test.go @@ -118,7 +118,7 @@ func withGateway(agentInfo agentInfo, settings *fleetGatewaySettings, fn withGat client := newTestingClient() dispatcher := newTestingDispatcher() - log, _ := logger.New("fleet_gateway") + log, _ := logger.New("fleet_gateway", false) rep := getReporter(agentInfo, log, t) ctx, cancel := context.WithCancel(context.Background()) @@ -255,7 +255,7 @@ func TestFleetGateway(t *testing.T) { dispatcher := newTestingDispatcher() ctx, cancel := context.WithCancel(context.Background()) - log, _ := logger.New("tst") + log, _ := logger.New("tst", false) stateStore, err := store.NewStateStore(log, storage.NewDiskStore(paths.AgentStateStoreFile())) require.NoError(t, err) @@ -344,7 +344,7 @@ func TestFleetGateway(t *testing.T) { dispatcher := newTestingDispatcher() ctx, cancel := context.WithCancel(context.Background()) - log, _ := logger.New("tst") + log, _ := logger.New("tst", false) stateStore, err := store.NewStateStore(log, storage.NewDiskStore(paths.AgentStateStoreFile())) require.NoError(t, err) diff --git a/x-pack/elastic-agent/pkg/agent/application/local_mode.go b/x-pack/elastic-agent/pkg/agent/application/local_mode.go index ea9ec35c389..ffb59f281ff 100644 --- a/x-pack/elastic-agent/pkg/agent/application/local_mode.go +++ b/x-pack/elastic-agent/pkg/agent/application/local_mode.go @@ -76,7 +76,7 @@ func newLocal( } if log == nil { - log, err = logger.NewFromConfig("", cfg.Settings.LoggingConfig) + log, err = logger.NewFromConfig("", cfg.Settings.LoggingConfig, true) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/agent/application/managed_mode.go b/x-pack/elastic-agent/pkg/agent/application/managed_mode.go index 43427ef57d9..c0ce285fceb 100644 --- a/x-pack/elastic-agent/pkg/agent/application/managed_mode.go +++ b/x-pack/elastic-agent/pkg/agent/application/managed_mode.go @@ -193,11 +193,6 @@ func newManaged( storeSaver, ) - if cfg.Fleet.Server == nil { - // setters only set when not running a local Fleet Server - policyChanger.AddSetter(acker) - } - actionDispatcher.MustRegister( &fleetapi.ActionPolicyChange{}, policyChanger, @@ -272,9 +267,13 @@ func newManaged( if err != nil { return nil, err } - // add the gateway to setters, so the gateway can be updated - // when the hosts for Kibana are updated by the policy. - policyChanger.AddSetter(gateway) + // add the acker and gateway to setters, so the they can be updated + // when the hosts for Fleet Server are updated by the policy. + if cfg.Fleet.Server == nil { + // setters only set when not running a local Fleet Server + policyChanger.AddSetter(gateway) + policyChanger.AddSetter(acker) + } managedApplication.gateway = gateway return managedApplication, nil diff --git a/x-pack/elastic-agent/pkg/agent/application/managed_mode_test.go b/x-pack/elastic-agent/pkg/agent/application/managed_mode_test.go index aa419e8ccb6..177ab7cabf3 100644 --- a/x-pack/elastic-agent/pkg/agent/application/managed_mode_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/managed_mode_test.go @@ -41,7 +41,7 @@ func TestManagedModeRouting(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - log, _ := logger.New("") + log, _ := logger.New("", false) router, _ := router.New(log, streamFn) agentInfo, _ := info.NewAgentInfo() nullStore := &storage.NullStore{} diff --git a/x-pack/elastic-agent/pkg/agent/application/paths/common.go b/x-pack/elastic-agent/pkg/agent/application/paths/common.go index fca3dbd8828..d5d56d5d000 100644 --- a/x-pack/elastic-agent/pkg/agent/application/paths/common.go +++ b/x-pack/elastic-agent/pkg/agent/application/paths/common.go @@ -16,24 +16,33 @@ import ( ) const ( - tempSubdir = "tmp" + // DefaultConfigName is the default name of the configuration file. + DefaultConfigName = "elastic-agent.yml" + // AgentLockFileName is the name of the overall Elastic Agent file lock. + AgentLockFileName = "agent.lock" + tempSubdir = "tmp" ) var ( - topPath string - configPath string - logsPath string - tmpCreator sync.Once + topPath string + configPath string + configFilePath string + logsPath string + unversionedHome bool + tmpCreator sync.Once ) func init() { topPath = initialTop() configPath = topPath logsPath = topPath + unversionedHome = false // only versioned by container subcommand fs := flag.CommandLine fs.StringVar(&topPath, "path.home", topPath, "Agent root path") + fs.BoolVar(&unversionedHome, "path.home.unversioned", unversionedHome, "Agent root path is not versioned based on build") fs.StringVar(&configPath, "path.config", configPath, "Config path is the directory Agent looks for its config file") + fs.StringVar(&configFilePath, "c", DefaultConfigName, "Configuration file, relative to path.config") fs.StringVar(&logsPath, "path.logs", logsPath, "Logs path contains Agent log output") } @@ -43,6 +52,14 @@ func Top() string { return topPath } +// SetTop overrides the Top path. +// +// Used by the container subcommand to adjust the overall top path allowing state can be maintained between container +// restarts. +func SetTop(path string) { + topPath = path +} + // TempDir returns agent temp dir located within data dir. func TempDir() string { tmpDir := filepath.Join(Data(), tempSubdir) @@ -55,16 +72,55 @@ func TempDir() string { // Home returns a directory where binary lives func Home() string { + if unversionedHome { + return topPath + } return versionedHome(topPath) } +// IsVersionHome returns true if the Home path is versioned based on build. +func IsVersionHome() bool { + return !unversionedHome +} + +// SetVersionHome sets if the Home path is versioned based on build. +// +// Used by the container subcommand to adjust the home path allowing state can be maintained between container +// restarts. +func SetVersionHome(version bool) { + unversionedHome = !version +} + // Config returns a directory where configuration file lives func Config() string { return configPath } +// SetConfig overrides the Config path. +// +// Used by the container subcommand to adjust the overall config path allowing state can be maintained between container +// restarts. +func SetConfig(path string) { + configPath = path +} + +// ConfigFile returns the path to the configuration file. +func ConfigFile() string { + if configFilePath == "" || configFilePath == DefaultConfigName { + return filepath.Join(Config(), DefaultConfigName) + } + if filepath.IsAbs(configFilePath) { + return configFilePath + } + return filepath.Join(Config(), configFilePath) +} + // Data returns the data directory for Agent func Data() string { + if unversionedHome { + // unversioned means the topPath is the data path + return topPath + } return filepath.Join(Top(), "data") } @@ -73,6 +129,11 @@ func Logs() string { return logsPath } +// SetLogs updates the path for the logs. +func SetLogs(path string) { + logsPath = path +} + // initialTop returns the initial top-level path for the binary // // When nested in top-level/data/elastic-agent-${hash}/ the result is top-level/. diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change_test.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change_test.go index e7811318d1d..1ab7ee20fdd 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change_test.go @@ -34,7 +34,7 @@ func (m *mockEmitter) Emitter(policy *config.Config) error { } func TestPolicyChange(t *testing.T) { - log, _ := logger.New("") + log, _ := logger.New("", false) ack := noopacker.NewAcker() agentInfo, _ := info.NewAgentInfo() nullStore := &storage.NullStore{} @@ -89,7 +89,7 @@ func TestPolicyChange(t *testing.T) { } func TestPolicyAcked(t *testing.T) { - log, _ := logger.New("") + log, _ := logger.New("", false) agentInfo, _ := info.NewAgentInfo() nullStore := &storage.NullStore{} diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/dispatcher/dispatcher.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/dispatcher/dispatcher.go index 13ce1206879..7a1ea23a42d 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/dispatcher/dispatcher.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/dispatcher/dispatcher.go @@ -31,7 +31,7 @@ type ActionDispatcher struct { func New(ctx context.Context, log *logger.Logger, def actions.Handler) (*ActionDispatcher, error) { var err error if log == nil { - log, err = logger.New("action_dispatcher") + log, err = logger.New("action_dispatcher", false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/pipeline.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/pipeline.go index 13631ab496c..8286c1ee3a4 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/pipeline.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/pipeline.go @@ -23,7 +23,7 @@ type ConfigHandler interface { } // DefaultRK default routing keys until we implement the routing key / config matrix. -var DefaultRK = "DEFAULT" +var DefaultRK = "default" // RoutingKey is used for routing as pipeline id. type RoutingKey = string diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router.go index 6a916d9eb92..6c7a27a2bd9 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router.go @@ -26,7 +26,7 @@ type router struct { func New(log *logger.Logger, factory pipeline.StreamFunc) (pipeline.Router, error) { var err error if log == nil { - log, err = logger.New("router") + log, err = logger.New("router", false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router_test.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router_test.go index 3feb49c1565..421a0f4cc91 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/router/router_test.go @@ -87,14 +87,14 @@ func TestRouter(t *testing.T) { }) assertOps(t, []event{ - e(pipeline.DefaultRK, createOp), - e(pipeline.DefaultRK, executeOp), - e(k1, createOp), e(k1, executeOp), e(k2, createOp), e(k2, executeOp), + + e(pipeline.DefaultRK, createOp), + e(pipeline.DefaultRK, executeOp), }, recorder.events) recorder.reset() @@ -108,9 +108,9 @@ func TestRouter(t *testing.T) { e(nk, createOp), e(nk, executeOp), - e(pipeline.DefaultRK, closeOp), e(k1, closeOp), e(k2, closeOp), + e(pipeline.DefaultRK, closeOp), }, recorder.events) }) @@ -152,12 +152,12 @@ func TestRouter(t *testing.T) { }) assertOps(t, []event{ - e(pipeline.DefaultRK, createOp), - e(pipeline.DefaultRK, executeOp), e(k1, createOp), e(k1, executeOp), e(k2, createOp), e(k2, executeOp), + e(pipeline.DefaultRK, createOp), + e(pipeline.DefaultRK, executeOp), }, recorder.events) recorder.reset() @@ -165,9 +165,9 @@ func TestRouter(t *testing.T) { r.Route("hello-2", map[pipeline.RoutingKey][]program.Program{}) assertOps(t, []event{ - e(pipeline.DefaultRK, closeOp), e(k1, closeOp), e(k2, closeOp), + e(pipeline.DefaultRK, closeOp), }, recorder.events) }) } diff --git a/x-pack/elastic-agent/pkg/agent/application/upgrade/crash_checker_test.go b/x-pack/elastic-agent/pkg/agent/application/upgrade/crash_checker_test.go index b297431456e..811c75bf3b0 100644 --- a/x-pack/elastic-agent/pkg/agent/application/upgrade/crash_checker_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/upgrade/crash_checker_test.go @@ -129,7 +129,7 @@ func TestChecker(t *testing.T) { func testableChecker(t *testing.T, pider *testPider) (*CrashChecker, chan error) { errChan := make(chan error, 1) - l, _ := logger.New("") + l, _ := logger.New("", false) ch, err := NewCrashChecker(context.Background(), errChan, l) require.NoError(t, err) diff --git a/x-pack/elastic-agent/pkg/agent/cmd/common.go b/x-pack/elastic-agent/pkg/agent/cmd/common.go index 60f01cadf15..1251ea75967 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/common.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/common.go @@ -7,37 +7,16 @@ package cmd import ( "flag" "os" - "path/filepath" "github.com/spf13/cobra" // import logp flags _ "github.com/elastic/beats/v7/libbeat/logp/configure" - "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/basecmd" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -const ( - defaultConfig = "elastic-agent.yml" - hashLen = 6 - commitFile = ".elastic-agent.active.commit" - agentLockFileName = "agent.lock" -) - -type globalFlags struct { - PathConfigFile string -} - -// Config returns path which identifies configuration file. -func (f *globalFlags) Config() string { - if len(f.PathConfigFile) == 0 || f.PathConfigFile == defaultConfig { - return filepath.Join(paths.Config(), defaultConfig) - } - return f.PathConfigFile -} - // NewCommand returns the default command for the agent. func NewCommand() *cobra.Command { return NewCommandWithArgs(os.Args, cli.NewIOStreams()) @@ -49,13 +28,13 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command { Use: "elastic-agent [subcommand]", } - flags := &globalFlags{} - // path flags cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.home")) + cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.home.unversioned")) + cmd.PersistentFlags().MarkHidden("path.home.unversioned") // hidden used internally by container subcommand cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.config")) + cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("c")) cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.logs")) - cmd.PersistentFlags().StringVarP(&flags.PathConfigFile, "c", "c", defaultConfig, `Configuration file, relative to path.config`) // logging flags cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("v")) @@ -64,19 +43,19 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command { cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("environment")) // sub-commands - run := newRunCommandWithArgs(flags, args, streams) + run := newRunCommandWithArgs(args, streams) cmd.AddCommand(basecmd.NewDefaultCommandsWithArgs(args, streams)...) cmd.AddCommand(run) - cmd.AddCommand(newInstallCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newUninstallCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newUpgradeCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newEnrollCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newInspectCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newWatchCommandWithArgs(flags, args, streams)) - cmd.AddCommand(newContainerCommand(flags, args, streams)) + cmd.AddCommand(newInstallCommandWithArgs(args, streams)) + cmd.AddCommand(newUninstallCommandWithArgs(args, streams)) + cmd.AddCommand(newUpgradeCommandWithArgs(args, streams)) + cmd.AddCommand(newEnrollCommandWithArgs(args, streams)) + cmd.AddCommand(newInspectCommandWithArgs(args, streams)) + cmd.AddCommand(newWatchCommandWithArgs(args, streams)) + cmd.AddCommand(newContainerCommand(args, streams)) // windows special hidden sub-command (only added on windows) - reexec := newReExecWindowsCommand(flags, args, streams) + reexec := newReExecWindowsCommand(args, streams) if reexec != nil { cmd.AddCommand(reexec) } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/container.go b/x-pack/elastic-agent/pkg/agent/cmd/container.go index 6e66565353e..fabec69dd8f 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/container.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/container.go @@ -20,11 +20,12 @@ import ( "syscall" "time" + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/configuration" + "github.com/spf13/cobra" "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" "github.com/elastic/beats/v7/libbeat/kibana" - "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/program" @@ -38,8 +39,9 @@ import ( ) const ( - requestRetrySleep = 1 * time.Second // sleep 1 sec between retries for HTTP requests - maxRequestRetries = 30 // maximum number of retries for HTTP requests + requestRetrySleep = 1 * time.Second // sleep 1 sec between retries for HTTP requests + maxRequestRetries = 30 // maximum number of retries for HTTP requests + defaultStateDirectory = "/usr/share/elastic-agent/state" // directory that will hold the state data ) var ( @@ -48,7 +50,7 @@ var ( tokenNameStrip = regexp.MustCompile(`\s\([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)$`) ) -func newContainerCommand(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newContainerCommand(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := cobra.Command{ Hidden: true, // not exposed over help; used by container entrypoint only Use: "container", @@ -117,13 +119,7 @@ all the above actions will be skipped, because the Elastic Agent has already bee occurs on every start of the container set FLEET_FORCE to 1. `, Run: func(c *cobra.Command, args []string) { - var err error - if _, cloud := os.LookupEnv("ELASTIC_AGENT_CLOUD"); cloud { - err = containerCloudCmd(streams, c, flags, args) - } else { - err = containerCmd(streams, c, flags, defaultAccessConfig()) - } - if err != nil { + if err := containerCmd(streams, c); err != nil { logError(streams, err) os.Exit(1) } @@ -140,74 +136,81 @@ func logInfo(streams *cli.IOStreams, msg string) { fmt.Fprintln(streams.Out, msg) } -func containerCloudCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { - logInfo(streams, "Elastic Agent container in cloud mode") - // sync main process and apm-server legacy process - var wg sync.WaitGroup - wg.Add(1) // main process (always running) - mainProc, err := os.FindProcess(os.Getpid()) - if err != nil { - return errors.New(err, "finding current process") +func containerCmd(streams *cli.IOStreams, cmd *cobra.Command) error { + // set paths early so all action below use the defined paths + if err := setPaths(); err != nil { + return err + } + + // create access configuration from ENV and config files + cfg := defaultAccessConfig() + for _, f := range []string{"fleet-setup.yml", "credentials.yml"} { + c, err := config.LoadFile(filepath.Join(paths.Config(), f)) + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("parsing config file(%s): %s", f, err) + } + if c != nil { + err = c.Unpack(&cfg) + if err != nil { + return fmt.Errorf("unpacking config file(%s): %s", f, err) + } + } } + + // start apm-server legacy process when in cloud mode + var wg sync.WaitGroup var apmProc *process.Info - // run legacy APM Server as a daemon; send termination signal - // to the main process if the daemon is stopped + _, elasticCloud := os.LookupEnv("ELASTIC_AGENT_CLOUD") apmPath := os.Getenv("APM_SERVER_PATH") - if apmPath != "" { - apmProc, err = runLegacyAPMServer(streams, apmPath, args) - if err != nil { - return errors.New(err, "starting legacy apm-server") - } - logInfo(streams, "Legacy apm-server daemon started.") - wg.Add(1) // apm-server legacy process - go func() { - if err := func() error { - apmProcState, err := apmProc.Process.Wait() - if err != nil { - return err + if elasticCloud { + logInfo(streams, "Starting in elastic cloud mode") + if elasticCloud && apmPath != "" { + // run legacy APM Server as a daemon; send termination signal + // to the main process if the daemon is stopped + mainProc, err := os.FindProcess(os.Getpid()) + if err != nil { + return errors.New(err, "finding current process") + } + if apmProc, err = runLegacyAPMServer(streams, apmPath); err != nil { + return errors.New(err, "starting legacy apm-server") + } + wg.Add(1) // apm-server legacy process + logInfo(streams, "Legacy apm-server daemon started.") + go func() { + if err := func() error { + apmProcState, err := apmProc.Process.Wait() + if err != nil { + return err + } + if apmProcState.ExitCode() != 0 { + return fmt.Errorf("apm-server process exited with %d", apmProcState.ExitCode()) + } + return nil + }(); err != nil { + logError(streams, err) } - if apmProcState.ExitCode() != 0 { - return fmt.Errorf("apm-server process exited with %d", apmProcState.ExitCode()) + + wg.Done() + // sending kill signal to current process (elastic-agent) + logInfo(streams, "Initiate shutdown elastic-agent.") + mainProc.Signal(syscall.SIGTERM) + }() + + defer func() { + if apmProc != nil { + apmProc.Stop() + logInfo(streams, "Initiate shutdown legacy apm-server.") } - return nil - }(); err != nil { - logError(streams, err) - } + wg.Wait() + }() + } + } - wg.Done() - // sending kill signal to current process (elastic-agent) - logInfo(streams, "Initiate shutdown elastic-agent.") - mainProc.Signal(syscall.SIGTERM) - }() - } - // run Elastic Agent; send termination signal to the - // legacy apm-server process if stopped - go func() { - if err := func() error { - // create configuration for Elastic Agent - cfg := defaultAccessConfig() - if err := readYaml(filepath.Join(paths.Config(), "fleet-setup.yml"), &cfg); err != nil { - return errors.New(err, "parsing fleet-setup.yml") - } - if err := readYaml(filepath.Join(paths.Config(), "credentials.yml"), &cfg); err != nil { - return errors.New(err, "parsing credentials.yml") - } - return containerCmd(streams, cmd, flags, cfg) - }(); err != nil { - logError(streams, err) - } - wg.Done() - // sending kill signal to APM Server - if apmProc != nil { - apmProc.Stop() - logInfo(streams, "Initiate shutdown legacy apm-server.") - } - }() - wg.Wait() - return nil + // run the main elastic-agent container command + return runContainerCmd(streams, cmd, cfg) } -func containerCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, cfg setupConfig) error { +func runContainerCmd(streams *cli.IOStreams, cmd *cobra.Command, cfg setupConfig) error { var err error var client *kibana.Client executable, err := os.Executable() @@ -218,7 +221,7 @@ func containerCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags _, err = os.Stat(paths.AgentConfigFile()) if !os.IsNotExist(err) && !cfg.Fleet.Force { // already enrolled, just run the standard run - return run(flags, streams) + return run(streams, logToStderr) } if cfg.Kibana.Fleet.Setup { @@ -226,7 +229,7 @@ func containerCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags if err != nil { return err } - fmt.Fprintf(streams.Out, "Performing setup of Fleet in Kibana\n") + logInfo(streams, "Performing setup of Fleet in Kibana\n") err = kibanaSetup(client, streams) if err != nil { return err @@ -272,11 +275,20 @@ func containerCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags } } - return run(flags, streams) + return run(streams, logToStderr) } func buildEnrollArgs(cfg setupConfig, token string, policyID string) ([]string, error) { - args := []string{"enroll", "-f"} + args := []string{ + "enroll", "-f", + "-c", paths.ConfigFile(), + "--path.home", paths.Top(), // --path.home actually maps to paths.Top() + "--path.config", paths.Config(), + "--path.logs", paths.Logs(), + } + if !paths.IsVersionHome() { + args = append(args, "--path.home.unversioned") + } if cfg.FleetServer.Enable { connStr, err := buildFleetServerConnStr(cfg.FleetServer) if err != nil { @@ -505,7 +517,7 @@ func truncateString(b []byte) string { // runLegacyAPMServer extracts the bundled apm-server from elastic-agent // to path and runs it with args. -func runLegacyAPMServer(streams *cli.IOStreams, path string, args []string) (*process.Info, error) { +func runLegacyAPMServer(streams *cli.IOStreams, path string) (*process.Info, error) { name := "apm-server" logInfo(streams, "Preparing apm-server for legacy mode.") cfg := artifact.DefaultConfig() @@ -540,32 +552,115 @@ func runLegacyAPMServer(streams *cli.IOStreams, path string, args []string) (*pr if err != nil { return nil, errors.New(err, fmt.Sprintf("absPath for %s", files[0])) } - log, err := logger.New("apm-server") + log, err := logger.New("apm-server", false) if err != nil { return nil, err } // add APM Server specific configuration + var args []string addEnv := func(arg, env string) { if v := os.Getenv(env); v != "" { args = append(args, arg, v) } } - addEnv("--path.config", "APM_SERVER_CONFIG_PATH") - addEnv("--path.data", "APM_SERVER_DATA_PATH") - addEnv("--path.logs", "APM_SERVER_LOGS_PATH") - addEnv("--httpprof", "APM_SERVER_HTTPPROF") + addEnv("--path.home", "HOME_PATH") + addEnv("--path.config", "CONFIG_PATH") + addEnv("--path.data", "DATA_PATH") + addEnv("--path.logs", "LOGS_PATH") + addEnv("--httpprof", "HTTPPROF") return process.Start(log, f, nil, os.Geteuid(), os.Getegid(), args...) } -func readYaml(f string, cfg *setupConfig) error { - c, err := config.LoadFile(f) - if err != nil { - if os.IsNotExist(err) { +func logToStderr(cfg *configuration.Configuration) { + logsPath := envWithDefault("", "LOGS_PATH") + if logsPath == "" { + // when no LOGS_PATH defined the container should log to stderr + cfg.Settings.LoggingConfig.ToStderr = true + cfg.Settings.LoggingConfig.ToFiles = false + } +} + +func setPaths() error { + statePath := envWithDefault(defaultStateDirectory, "STATE_PATH") + if statePath == "" { + return errors.New("STATE_PATH cannot be set to an empty string") + } + topPath := filepath.Join(statePath, "data") + configPath := envWithDefault("", "CONFIG_PATH") + if configPath == "" { + configPath = statePath + } + // ensure that the directory and sub-directory data exists + if err := os.MkdirAll(topPath, 0755); err != nil { + return fmt.Errorf("preparing STATE_PATH(%s) failed: %s", statePath, err) + } + // ensure that the elastic-agent.yml exists in the state directory or if given in the config directory + baseConfig := filepath.Join(configPath, paths.DefaultConfigName) + if _, err := os.Stat(baseConfig); os.IsNotExist(err) { + if err := copyFile(baseConfig, paths.ConfigFile(), 0); err != nil { + return err + } + } + // sync the downloads to the data directory + if err := syncDownloads(statePath); err != nil { + return fmt.Errorf("syncing download directory to STATE_PATH(%s) failed: %s", statePath, err) + } + paths.SetTop(topPath) + paths.SetConfig(configPath) + // when custom top path is provided the home directory is not versioned + paths.SetVersionHome(false) + // set LOGS_PATH is given + if logsPath := envWithDefault("", "LOGS_PATH"); logsPath != "" { + paths.SetLogs(logsPath) + // ensure that the logs directory exists + if err := os.MkdirAll(filepath.Join(logsPath), 0755); err != nil { + return fmt.Errorf("preparing LOGS_PATH(%s) failed: %s", logsPath, err) + } + } + return nil +} + +func syncDownloads(dataPath string) error { + srcDownloads := filepath.Join(paths.Home(), "downloads") + destDownloads := filepath.Join(dataPath, "data", "downloads") + return filepath.Walk(srcDownloads, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + relativePath := strings.TrimPrefix(path, srcDownloads) + if info.IsDir() { + err = os.MkdirAll(filepath.Join(destDownloads, relativePath), info.Mode()) + if err != nil { + return err + } return nil } + return copyFile(filepath.Join(destDownloads, relativePath), path, info.Mode()) + }) +} + +func copyFile(destPath string, srcPath string, mode os.FileMode) error { + // if mode is unset; set to the same as the source file + if mode == 0 { + info, err := os.Stat(srcPath) + if err == nil { + // ignoring error because; os.Open will also error if the file cannot be stat'd + mode = info.Mode() + } + } + + src, err := os.Open(srcPath) + if err != nil { + return err + } + defer src.Close() + dest, err := os.OpenFile(destPath, os.O_CREATE|os.O_WRONLY, mode) + if err != nil { return err } - return c.Unpack(cfg) + defer dest.Close() + _, err = io.Copy(dest, src) + return err } type kibanaPolicy struct { @@ -624,7 +719,7 @@ type fleetConfig struct { type fleetServerConfig struct { Cert string `config:"cert"` - CertKey string `config:"certKey"` + CertKey string `config:"cert_key"` Elasticsearch elasticsearchConfig `config:"elasticsearch"` Enable bool `config:"enable"` Host string `config:"host"` @@ -647,7 +742,7 @@ type kibanaFleetConfig struct { } func defaultAccessConfig() setupConfig { - return setupConfig{ + cfg := setupConfig{ Fleet: fleetConfig{ CA: envWithDefault("", "FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA"), Enroll: envBool("FLEET_ENROLL", "FLEET_SERVER_ENABLE"), @@ -687,4 +782,5 @@ func defaultAccessConfig() setupConfig { }, }, } + return cfg } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go index 4606f363f94..ec7cec1211d 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go @@ -12,6 +12,8 @@ import ( "strconv" "syscall" + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" + "github.com/spf13/cobra" c "github.com/elastic/beats/v7/libbeat/common/cli" @@ -23,13 +25,13 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/logger" ) -func newEnrollCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newEnrollCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "enroll", Short: "Enroll the Agent into Fleet", Long: "This will enroll the Agent into Fleet.", Run: func(c *cobra.Command, args []string) { - if err := enroll(streams, c, flags, args); err != nil { + if err := enroll(streams, c, args); err != nil { fmt.Fprintf(streams.Err, "Error: %v\n", err) os.Exit(1) } @@ -145,13 +147,13 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string return args } -func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { +func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { fromInstall, _ := cmd.Flags().GetBool("from-install") if !fromInstall { warn.PrintNotGA(streams.Out) } - pathConfigFile := flags.Config() + pathConfigFile := paths.ConfigFile() rawConfig, err := config.LoadFile(pathConfigFile) if err != nil { return errors.New(err, @@ -197,7 +199,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args cfg.Settings.LoggingConfig.ToFiles = false cfg.Settings.LoggingConfig.ToStderr = true - logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig) + logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig, false) if err != nil { return 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 c21efafd2e2..84f801a515b 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go @@ -37,8 +37,9 @@ import ( const ( maxRetriesstoreAgentInfo = 5 - waitingForAgent = "waiting for Elastic Agent to start" - waitingForFleetServer = "waiting for Elastic Agent to start Fleet Server" + waitingForAgent = "Waiting for Elastic Agent to start" + waitingForFleetServer = "Waiting for Elastic Agent to start Fleet Server" + defaultFleetServerHost = "0.0.0.0" defaultFleetServerPort = 8220 ) @@ -227,6 +228,7 @@ func (c *enrollCmd) fleetServerBootstrap(ctx context.Context) error { return err } + var agentSubproc <-chan *os.ProcessState if agentRunning { // reload the already running agent err = c.daemonReload(ctx) @@ -235,13 +237,13 @@ func (c *enrollCmd) fleetServerBootstrap(ctx context.Context) error { } } else { // spawn `run` as a subprocess so enroll can perform the bootstrap process of Fleet Server - err = c.startAgent() + agentSubproc, err = c.startAgent() if err != nil { return err } } - err = waitForFleetServer(ctx, c.log) + err = waitForFleetServer(ctx, agentSubproc, c.log) if err != nil { return errors.New(err, "fleet-server never started by elastic-agent daemon", errors.TypeApplication) } @@ -413,18 +415,32 @@ func (c *enrollCmd) enroll(ctx context.Context) error { return nil } -func (c *enrollCmd) startAgent() error { +func (c *enrollCmd) startAgent() (<-chan *os.ProcessState, error) { cmd, err := os.Executable() if err != nil { - return err + return nil, err } c.log.Info("Spawning Elastic Agent daemon as a subprocess to complete bootstrap process.") - proc, err := process.Start(c.log, cmd, nil, os.Geteuid(), os.Getegid(), "run") + args := []string{ + "run", "-c", paths.ConfigFile(), + "--path.home", paths.Top(), "--path.config", paths.Config(), + "--path.logs", paths.Logs(), + } + if !paths.IsVersionHome() { + args = append(args, "--path.home.unversioned") + } + proc, err := process.Start( + c.log, cmd, nil, os.Geteuid(), os.Getegid(), args...) if err != nil { - return err + return nil, err } + resChan := make(chan *os.ProcessState) + go func() { + procState, _ := proc.Process.Wait() + resChan <- procState + }() c.agentProc = proc - return nil + return resChan, nil } func (c *enrollCmd) stopAgent() { @@ -467,7 +483,7 @@ type waitResult struct { err error } -func waitForFleetServer(ctx context.Context, log *logger.Logger) error { +func waitForFleetServer(ctx context.Context, agentSubproc <-chan *os.ProcessState, log *logger.Logger) error { ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() @@ -476,6 +492,7 @@ func waitForFleetServer(ctx context.Context, log *logger.Logger) error { defer innerCancel() go func() { msg := "" + msgCount := 0 for { <-time.After(1 * time.Second) status, err := getDaemonStatus(innerCtx) @@ -484,29 +501,50 @@ func waitForFleetServer(ctx context.Context, log *logger.Logger) error { return } if err != nil { - log.Debug(waitingForAgent) + log.Debugf("%s: %s", waitingForAgent, err) if msg != waitingForAgent { msg = waitingForAgent + msgCount = 0 log.Info(waitingForAgent) + } else { + msgCount++ + if msgCount > 5 { + msgCount = 0 + log.Infof("%s: %s", waitingForAgent, err) + } } continue } app := getAppFromStatus(status, "fleet-server") if app == nil { - log.Debug(waitingForFleetServer) + err = errors.New("no fleet-server application running") + log.Debugf("%s: %s", waitingForFleetServer, err) if msg != waitingForFleetServer { msg = waitingForFleetServer + msgCount = 0 log.Info(waitingForFleetServer) + } else { + msgCount++ + if msgCount > 5 { + msgCount = 0 + log.Infof("%s: %s", waitingForFleetServer, err) + } } continue } - log.Debugf("fleet-server status: %s - %s", app.Status, app.Message) + log.Debugf("%s: %s - %s", waitingForFleetServer, app.Status, app.Message) if app.Status == proto.Status_DEGRADED || app.Status == proto.Status_HEALTHY { // app has started and is running + if app.Message != "" { + log.Infof("Fleet Server - %s", app.Message) + } resChan <- waitResult{} break } else if app.Status == proto.Status_FAILED { // app completely failed; exit now + if app.Message != "" { + log.Infof("Fleet Server - %s", app.Message) + } resChan <- waitResult{err: errors.New(app.Message)} break } @@ -514,18 +552,36 @@ func waitForFleetServer(ctx context.Context, log *logger.Logger) error { appMsg := fmt.Sprintf("Fleet Server - %s", app.Message) if msg != appMsg { msg = appMsg + msgCount = 0 log.Info(appMsg) + } else { + msgCount++ + if msgCount > 5 { + msgCount = 0 + log.Info(appMsg) + } } } } }() var res waitResult - select { - case <-ctx.Done(): - innerCancel() - res = <-resChan - case res = <-resChan: + if agentSubproc == nil { + select { + case <-ctx.Done(): + innerCancel() + res = <-resChan + case res = <-resChan: + } + } else { + select { + case ps := <-agentSubproc: + res = waitResult{err: fmt.Errorf("spawned Elastic Agent exited unexpectedly: %s", ps)} + case <-ctx.Done(): + innerCancel() + res = <-resChan + case res = <-resChan: + } } if res.err != nil { @@ -584,6 +640,12 @@ func createFleetServerBootstrapConfig(connStr string, policyID string, host stri CAs: []string{esCA}, } } + if host == "" { + host = defaultFleetServerHost + } + if port == 0 { + port = defaultFleetServerPort + } cfg := configuration.DefaultFleetAgentConfig() cfg.Enabled = true cfg.Server = &configuration.FleetServerConfig{ diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go index 7c066d0aad8..8f5b7c4f8a5 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go @@ -45,7 +45,7 @@ func (m *mockStore) Save(in io.Reader) error { } func TestEnroll(t *testing.T) { - log, _ := logger.New("tst") + log, _ := logger.New("tst", false) t.Run("fail to save is propagated", withTLSServer( func(t *testing.T) *http.ServeMux { diff --git a/x-pack/elastic-agent/pkg/agent/cmd/inspect.go b/x-pack/elastic-agent/pkg/agent/cmd/inspect.go index 654f12dfc40..e66a15dfe3f 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/inspect.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/inspect.go @@ -34,26 +34,26 @@ import ( "github.com/elastic/go-sysinfo" ) -func newInspectCommandWithArgs(flags *globalFlags, s []string, streams *cli.IOStreams) *cobra.Command { +func newInspectCommandWithArgs(s []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "inspect", Short: "Shows configuration of the agent", Long: "Shows current configuration of the agent", Args: cobra.ExactArgs(0), Run: func(c *cobra.Command, args []string) { - if err := inspectConfig(flags.Config()); err != nil { + if err := inspectConfig(paths.ConfigFile()); err != nil { fmt.Fprintf(streams.Err, "%v\n", err) os.Exit(1) } }, } - cmd.AddCommand(newInspectOutputCommandWithArgs(flags, s, streams)) + cmd.AddCommand(newInspectOutputCommandWithArgs(s, streams)) return cmd } -func newInspectOutputCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newInspectOutputCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "output", Short: "Displays configuration generated for output", @@ -62,7 +62,7 @@ func newInspectOutputCommandWithArgs(flags *globalFlags, _ []string, streams *cl RunE: func(c *cobra.Command, args []string) error { outName, _ := c.Flags().GetString("output") program, _ := c.Flags().GetString("program") - cfgPath := flags.Config() + cfgPath := paths.ConfigFile() agentInfo, err := info.NewAgentInfo() if err != nil { return err @@ -129,7 +129,7 @@ func printConfig(cfg *config.Config) error { } func newErrorLogger() (*logger.Logger, error) { - return logger.NewWithLogpLevel("", logp.ErrorLevel) + return logger.NewWithLogpLevel("", logp.ErrorLevel, false) } func inspectOutputs(cfgPath string, agentInfo *info.AgentInfo) error { diff --git a/x-pack/elastic-agent/pkg/agent/cmd/install.go b/x-pack/elastic-agent/pkg/agent/cmd/install.go index 09a44bc67c4..090f6a9f2fe 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/install.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/install.go @@ -19,7 +19,7 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -func newInstallCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newInstallCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "install", Short: "Install Elastic Agent permanently on this system", @@ -29,7 +29,7 @@ Unless all the require command-line parameters are provided or -f is used this c would like the Agent to operate. `, Run: func(c *cobra.Command, args []string) { - if err := installCmd(streams, c, flags, args); err != nil { + if err := installCmd(streams, c, args); err != nil { fmt.Fprintf(streams.Err, "Error: %v\n", err) os.Exit(1) } @@ -42,7 +42,7 @@ would like the Agent to operate. return cmd } -func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { +func installCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { isAdmin, err := install.HasRoot() if err != nil { return fmt.Errorf("unable to perform install command while checking for administrator rights, %v", err) @@ -57,7 +57,7 @@ func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, } // check the lock to ensure that elastic-agent is not already running in this directory - locker := filelock.NewAppLocker(paths.Data(), agentLockFileName) + locker := filelock.NewAppLocker(paths.Data(), paths.AgentLockFileName) if err := locker.TryLock(); err != nil { if err == filelock.ErrAppAlreadyRunning { return fmt.Errorf("cannot perform installation as Elastic Agent is already running from this directory") @@ -141,7 +141,7 @@ func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, } } } - cfgFile := flags.Config() + cfgFile := paths.ConfigFile() err = install.Install(cfgFile) if err != nil { return err diff --git a/x-pack/elastic-agent/pkg/agent/cmd/reexec.go b/x-pack/elastic-agent/pkg/agent/cmd/reexec.go index 575828212a2..2ac2425b931 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/reexec.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/reexec.go @@ -12,6 +12,6 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -func newReExecWindowsCommand(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newReExecWindowsCommand(_ []string, streams *cli.IOStreams) *cobra.Command { return nil } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/reexec_windows.go b/x-pack/elastic-agent/pkg/agent/cmd/reexec_windows.go index b47678801fc..68c98c0534f 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/reexec_windows.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/reexec_windows.go @@ -20,7 +20,7 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -func newReExecWindowsCommand(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newReExecWindowsCommand(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Hidden: true, Use: "reexec_windows ", diff --git a/x-pack/elastic-agent/pkg/agent/cmd/run.go b/x-pack/elastic-agent/pkg/agent/cmd/run.go index 6daac21342a..e4d5b1c105c 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/run.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/run.go @@ -46,12 +46,14 @@ const ( agentName = "elastic-agent" ) -func newRunCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +type cfgOverrider func(cfg *configuration.Configuration) + +func newRunCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { return &cobra.Command{ Use: "run", Short: "Start the elastic-agent.", Run: func(_ *cobra.Command, _ []string) { - if err := run(flags, streams); err != nil { + if err := run(streams, nil); err != nil { fmt.Fprintf(streams.Err, "%v\n", err) os.Exit(1) } @@ -59,12 +61,12 @@ func newRunCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStream } } -func run(flags *globalFlags, streams *cli.IOStreams) error { // Windows: Mark service as stopped. +func run(streams *cli.IOStreams, override cfgOverrider) error { // Windows: Mark service as stopped. // After this is run, the service is considered by the OS to be stopped. // This must be the first deferred cleanup task (last to execute). defer service.NotifyTermination() - locker := filelock.NewAppLocker(paths.Data(), agentLockFileName) + locker := filelock.NewAppLocker(paths.Data(), paths.AgentLockFileName) if err := locker.TryLock(); err != nil { return err } @@ -81,7 +83,7 @@ func run(flags *globalFlags, streams *cli.IOStreams) error { // Windows: Mark se } service.HandleSignals(stopBeat, cancel) - pathConfigFile := flags.Config() + pathConfigFile := paths.ConfigFile() rawConfig, err := config.LoadFile(pathConfigFile) if err != nil { return errors.New(err, @@ -102,6 +104,10 @@ func run(flags *globalFlags, streams *cli.IOStreams) error { // Windows: Mark se errors.M(errors.MetaKeyPath, pathConfigFile)) } + if override != nil { + override(cfg) + } + agentInfo, err := info.NewAgentInfoWithLog(defaultLogLevel(cfg)) if err != nil { return errors.New(err, @@ -110,7 +116,7 @@ func run(flags *globalFlags, streams *cli.IOStreams) error { // Windows: Mark se errors.M(errors.MetaKeyPath, pathConfigFile)) } - logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig) + logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig, true) if err != nil { return err } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/uninstall.go b/x-pack/elastic-agent/pkg/agent/cmd/uninstall.go index f21f157a2d3..b6757ee464c 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/uninstall.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/uninstall.go @@ -17,7 +17,7 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -func newUninstallCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newUninstallCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "uninstall", Short: "Uninstall permanent Elastic Agent from this system", @@ -26,7 +26,7 @@ func newUninstallCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IO Unless -f is used this command will ask confirmation before performing removal. `, Run: func(c *cobra.Command, args []string) { - if err := uninstallCmd(streams, c, flags, args); err != nil { + if err := uninstallCmd(streams, c, args); err != nil { fmt.Fprintf(streams.Err, "Error: %v\n", err) os.Exit(1) } @@ -38,7 +38,7 @@ Unless -f is used this command will ask confirmation before performing removal. return cmd } -func uninstallCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { +func uninstallCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { isAdmin, err := install.HasRoot() if err != nil { return fmt.Errorf("unable to perform command while checking for administrator rights, %v", err) @@ -78,7 +78,7 @@ func uninstallCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags } } - err = install.Uninstall(flags.Config()) + err = install.Uninstall(paths.ConfigFile()) if err != nil { return err } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/upgrade.go b/x-pack/elastic-agent/pkg/agent/cmd/upgrade.go index 81a5c82b4ab..d3c8dc27e6c 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/upgrade.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/upgrade.go @@ -17,13 +17,13 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" ) -func newUpgradeCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newUpgradeCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "upgrade ", Short: "Upgrade the currently running Elastic Agent to the specified version", Args: cobra.ExactArgs(1), Run: func(c *cobra.Command, args []string) { - if err := upgradeCmd(streams, c, flags, args); err != nil { + if err := upgradeCmd(streams, c, args); err != nil { fmt.Fprintf(streams.Err, "%v\n", err) os.Exit(1) } @@ -35,7 +35,7 @@ func newUpgradeCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOSt return cmd } -func upgradeCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { +func upgradeCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { fmt.Fprintln(streams.Out, "The upgrade process of Elastic Agent is currently EXPERIMENTAL and should not be used in production") version := args[0] diff --git a/x-pack/elastic-agent/pkg/agent/cmd/watch.go b/x-pack/elastic-agent/pkg/agent/cmd/watch.go index 75ad178eb27..c8a51d33413 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/watch.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/watch.go @@ -34,13 +34,13 @@ const ( watcherLockFile = "watcher.lock" ) -func newWatchCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStreams) *cobra.Command { +func newWatchCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "watch", Short: "Watch watches Elastic Agent for failures and initiates rollback.", Long: `Watch watches Elastic Agent for failures and initiates rollback.`, Run: func(c *cobra.Command, args []string) { - if err := watchCmd(streams, c, flags, args); err != nil { + if err := watchCmd(streams, c, args); err != nil { fmt.Fprintf(streams.Err, "Error: %v\n", err) os.Exit(1) } @@ -50,8 +50,8 @@ func newWatchCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStre return cmd } -func watchCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error { - log, err := configuredLogger(flags) +func watchCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { + log, err := configuredLogger() if err != nil { return err } @@ -181,8 +181,8 @@ func gracePeriod(marker *upgrade.UpdateMarker) (bool, time.Duration) { return false, gracePeriodDuration } -func configuredLogger(flags *globalFlags) (*logger.Logger, error) { - pathConfigFile := flags.Config() +func configuredLogger() (*logger.Logger, error) { + pathConfigFile := paths.ConfigFile() rawConfig, err := config.LoadFile(pathConfigFile) if err != nil { return nil, errors.New(err, @@ -201,7 +201,7 @@ func configuredLogger(flags *globalFlags) (*logger.Logger, error) { cfg.Settings.LoggingConfig.Beat = watcherName - logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig) + logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig, false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/agent/control/addr.go b/x-pack/elastic-agent/pkg/agent/control/addr.go index 116f9d8dd95..4f210efca4f 100644 --- a/x-pack/elastic-agent/pkg/agent/control/addr.go +++ b/x-pack/elastic-agent/pkg/agent/control/addr.go @@ -9,6 +9,7 @@ package control import ( "crypto/sha256" "fmt" + "path/filepath" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/info" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" @@ -21,9 +22,12 @@ func Address() string { return paths.SocketPath } - // not install, adjust the path based on data path - data := paths.Data() - // entire string cannot be longer than 107 characters, this forces the - // length to always be 88 characters (but unique per data path) - return fmt.Sprintf(`unix:///tmp/elastic-agent-%x.sock`, sha256.Sum256([]byte(data))) + // unix socket path cannot be longer than 107 characters + path := fmt.Sprintf("unix://%s.sock", filepath.Join(paths.TempDir(), "elastic-agent-control")) + if len(path) <= 107 { + return path + } + // place in global /tmp to ensure that its small enough to fit; current path is way to long + // for it to be used, but needs to be unique per Agent (in the case that multiple are running) + return fmt.Sprintf(`unix:///tmp/elastic-agent-%x.sock`, sha256.Sum256([]byte(path))) } diff --git a/x-pack/elastic-agent/pkg/agent/control/control_test.go b/x-pack/elastic-agent/pkg/agent/control/control_test.go index bcda4a0e4ed..b37a161047f 100644 --- a/x-pack/elastic-agent/pkg/agent/control/control_test.go +++ b/x-pack/elastic-agent/pkg/agent/control/control_test.go @@ -72,7 +72,7 @@ func newErrorLogger(t *testing.T) *logger.Logger { loggerCfg := logger.DefaultLoggingConfig() loggerCfg.Level = logp.ErrorLevel - log, err := logger.NewFromConfig("", loggerCfg) + log, err := logger.NewFromConfig("", loggerCfg, false) require.NoError(t, err) return log } diff --git a/x-pack/elastic-agent/pkg/agent/install/uninstall.go b/x-pack/elastic-agent/pkg/agent/install/uninstall.go index bacac3ff22a..6a60a2c9258 100644 --- a/x-pack/elastic-agent/pkg/agent/install/uninstall.go +++ b/x-pack/elastic-agent/pkg/agent/install/uninstall.go @@ -124,7 +124,7 @@ func delayedRemoval(path string) { } func uninstallPrograms(ctx context.Context, cfgFile string) error { - log, err := logger.NewWithLogpLevel("", logp.ErrorLevel) + log, err := logger.NewWithLogpLevel("", logp.ErrorLevel, false) if err != nil { return err } diff --git a/x-pack/elastic-agent/pkg/agent/operation/common_test.go b/x-pack/elastic-agent/pkg/agent/operation/common_test.go index 12e20e9b0ff..4eb24a105d3 100644 --- a/x-pack/elastic-agent/pkg/agent/operation/common_test.go +++ b/x-pack/elastic-agent/pkg/agent/operation/common_test.go @@ -92,7 +92,7 @@ func getTestOperator(t *testing.T, downloadPath string, installPath string, p *a func getLogger() *logger.Logger { loggerCfg := logger.DefaultLoggingConfig() loggerCfg.Level = logp.ErrorLevel - l, _ := logger.NewFromConfig("", loggerCfg) + l, _ := logger.NewFromConfig("", loggerCfg, false) return l } diff --git a/x-pack/elastic-agent/pkg/agent/stateresolver/stateresolver_test.go b/x-pack/elastic-agent/pkg/agent/stateresolver/stateresolver_test.go index 3bc4a1ac547..e1adea3281a 100644 --- a/x-pack/elastic-agent/pkg/agent/stateresolver/stateresolver_test.go +++ b/x-pack/elastic-agent/pkg/agent/stateresolver/stateresolver_test.go @@ -25,7 +25,7 @@ func TestStateResolverAcking(t *testing.T) { } t.Run("when we ACK the should state", func(t *testing.T) { - log, _ := logger.New("") + log, _ := logger.New("", false) r, err := NewStateResolver(log) require.NoError(t, err) @@ -44,7 +44,7 @@ func TestStateResolverAcking(t *testing.T) { }) t.Run("when we don't ACK the should state", func(t *testing.T) { - log, _ := logger.New("") + log, _ := logger.New("", false) r, err := NewStateResolver(log) require.NoError(t, err) diff --git a/x-pack/elastic-agent/pkg/agent/storage/store/action_store_test.go b/x-pack/elastic-agent/pkg/agent/storage/store/action_store_test.go index 6f5fbe4046a..bf9cca915f8 100644 --- a/x-pack/elastic-agent/pkg/agent/storage/store/action_store_test.go +++ b/x-pack/elastic-agent/pkg/agent/storage/store/action_store_test.go @@ -18,7 +18,7 @@ import ( ) func TestActionStore(t *testing.T) { - log, _ := logger.New("action_store") + log, _ := logger.New("action_store", false) withFile := func(fn func(t *testing.T, file string)) func(*testing.T) { return func(t *testing.T) { dir, err := ioutil.TempDir("", "action-store") diff --git a/x-pack/elastic-agent/pkg/agent/storage/store/state_store_test.go b/x-pack/elastic-agent/pkg/agent/storage/store/state_store_test.go index 1b575599dd3..d19f4b1b453 100644 --- a/x-pack/elastic-agent/pkg/agent/storage/store/state_store_test.go +++ b/x-pack/elastic-agent/pkg/agent/storage/store/state_store_test.go @@ -31,7 +31,7 @@ func TestStateStore(t *testing.T) { } func runTestStateStore(t *testing.T, ackToken string) { - log, _ := logger.New("state_store") + log, _ := logger.New("state_store", false) withFile := func(fn func(t *testing.T, file string)) func(*testing.T) { return func(t *testing.T) { dir, err := ioutil.TempDir("", "state-store") diff --git a/x-pack/elastic-agent/pkg/basecmd/version/cmd_test.go b/x-pack/elastic-agent/pkg/basecmd/version/cmd_test.go index 2694ed1cd3f..81fb5a56d8f 100644 --- a/x-pack/elastic-agent/pkg/basecmd/version/cmd_test.go +++ b/x-pack/elastic-agent/pkg/basecmd/version/cmd_test.go @@ -128,7 +128,7 @@ func newErrorLogger(t *testing.T) *logger.Logger { loggerCfg := logger.DefaultLoggingConfig() loggerCfg.Level = logp.ErrorLevel - log, err := logger.NewFromConfig("", loggerCfg) + log, err := logger.NewFromConfig("", loggerCfg, false) require.NoError(t, err) return log } diff --git a/x-pack/elastic-agent/pkg/capabilities/capabilities_test.go b/x-pack/elastic-agent/pkg/capabilities/capabilities_test.go index 5dbd46a4303..ca84aad0c21 100644 --- a/x-pack/elastic-agent/pkg/capabilities/capabilities_test.go +++ b/x-pack/elastic-agent/pkg/capabilities/capabilities_test.go @@ -29,7 +29,7 @@ func TestLoadCapabilities(t *testing.T) { "no_caps", } - l, _ := logger.New("test") + l, _ := logger.New("test", false) for _, tc := range testCases { t.Run(tc, func(t *testing.T) { @@ -78,7 +78,7 @@ func TestInvalidLoadCapabilities(t *testing.T) { "invalid_output", } - l, _ := logger.New("test") + l, _ := logger.New("test", false) for _, tc := range testCases { t.Run(tc, func(t *testing.T) { @@ -342,7 +342,7 @@ func newErrorLogger(t *testing.T) *logger.Logger { loggerCfg := logger.DefaultLoggingConfig() loggerCfg.Level = logp.ErrorLevel - log, err := logger.NewFromConfig("", loggerCfg) + log, err := logger.NewFromConfig("", loggerCfg, false) require.NoError(t, err) return log } diff --git a/x-pack/elastic-agent/pkg/capabilities/input_test.go b/x-pack/elastic-agent/pkg/capabilities/input_test.go index 7a2707d8f83..dd92f360c8a 100644 --- a/x-pack/elastic-agent/pkg/capabilities/input_test.go +++ b/x-pack/elastic-agent/pkg/capabilities/input_test.go @@ -19,7 +19,7 @@ import ( func TestMultiInput(t *testing.T) { tr := &testReporter{} - l, _ := logger.New("test") + l, _ := logger.New("test", false) t.Run("no match", func(t *testing.T) { rd := &ruleDefinitions{ @@ -184,7 +184,7 @@ func TestMultiInput(t *testing.T) { } func TestInput(t *testing.T) { - l, _ := logger.New("test") + l, _ := logger.New("test", false) tr := &testReporter{} t.Run("invalid rule", func(t *testing.T) { r := &upgradeCapability{} diff --git a/x-pack/elastic-agent/pkg/capabilities/output_test.go b/x-pack/elastic-agent/pkg/capabilities/output_test.go index fca32effadc..62553cf026c 100644 --- a/x-pack/elastic-agent/pkg/capabilities/output_test.go +++ b/x-pack/elastic-agent/pkg/capabilities/output_test.go @@ -17,7 +17,7 @@ import ( func TestMultiOutput(t *testing.T) { tr := &testReporter{} - l, _ := logger.New("test") + l, _ := logger.New("test", false) t.Run("no match", func(t *testing.T) { rd := &ruleDefinitions{ Capabilities: []ruler{&outputCapability{ @@ -167,7 +167,7 @@ func TestMultiOutput(t *testing.T) { func TestOutput(t *testing.T) { tr := &testReporter{} - l, _ := logger.New("test") + l, _ := logger.New("test", false) t.Run("invalid rule", func(t *testing.T) { r := &upgradeCapability{} cap, err := newOutputCapability(l, r, tr) diff --git a/x-pack/elastic-agent/pkg/capabilities/upgrade_test.go b/x-pack/elastic-agent/pkg/capabilities/upgrade_test.go index 0dc82ed3507..64b36afad83 100644 --- a/x-pack/elastic-agent/pkg/capabilities/upgrade_test.go +++ b/x-pack/elastic-agent/pkg/capabilities/upgrade_test.go @@ -15,7 +15,7 @@ import ( func TestUpgrade(t *testing.T) { tr := &testReporter{} - l, _ := logger.New("test") + l, _ := logger.New("test", false) t.Run("invalid rule", func(t *testing.T) { r := &inputCapability{} cap, err := newUpgradeCapability(l, r, tr) diff --git a/x-pack/elastic-agent/pkg/composable/controller_test.go b/x-pack/elastic-agent/pkg/composable/controller_test.go index da05a41bfd3..c910a905d5e 100644 --- a/x-pack/elastic-agent/pkg/composable/controller_test.go +++ b/x-pack/elastic-agent/pkg/composable/controller_test.go @@ -75,7 +75,7 @@ func TestController(t *testing.T) { }) require.NoError(t, err) - log, err := logger.New("") + log, err := logger.New("", false) require.NoError(t, err) c, err := composable.New(log, cfg) require.NoError(t, err) diff --git a/x-pack/elastic-agent/pkg/composable/providers/host/host_test.go b/x-pack/elastic-agent/pkg/composable/providers/host/host_test.go index c2e467c5b04..c6c758a25c3 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/host/host_test.go +++ b/x-pack/elastic-agent/pkg/composable/providers/host/host_test.go @@ -31,7 +31,7 @@ func TestContextProvider(t *testing.T) { }) require.NoError(t, err) builder, _ := composable.Providers.GetContextProvider("host") - log, err := logger.New("host_test") + log, err := logger.New("host_test", false) require.NoError(t, err) provider, err := builder(log, c) require.NoError(t, err) diff --git a/x-pack/elastic-agent/pkg/config/operations/inspector.go b/x-pack/elastic-agent/pkg/config/operations/inspector.go index 755cafc6d07..15ef586799f 100644 --- a/x-pack/elastic-agent/pkg/config/operations/inspector.go +++ b/x-pack/elastic-agent/pkg/config/operations/inspector.go @@ -113,5 +113,5 @@ func loadFleetConfig(cfg *config.Config) (map[string]interface{}, error) { } func newErrorLogger() (*logger.Logger, error) { - return logger.NewWithLogpLevel("", logp.ErrorLevel) + return logger.NewWithLogpLevel("", logp.ErrorLevel, false) } diff --git a/x-pack/elastic-agent/pkg/core/logger/logger.go b/x-pack/elastic-agent/pkg/core/logger/logger.go index 6169022fea6..2ef2ce7f16d 100644 --- a/x-pack/elastic-agent/pkg/core/logger/logger.go +++ b/x-pack/elastic-agent/pkg/core/logger/logger.go @@ -30,33 +30,33 @@ type Logger = logp.Logger type Config = logp.Config // New returns a configured ECS Logger -func New(name string) (*Logger, error) { +func New(name string, logInternal bool) (*Logger, error) { defaultCfg := DefaultLoggingConfig() - return new(name, defaultCfg) + return new(name, defaultCfg, logInternal) } // NewWithLogpLevel returns a configured logp Logger with specified level. -func NewWithLogpLevel(name string, level logp.Level) (*Logger, error) { +func NewWithLogpLevel(name string, level logp.Level, logInternal bool) (*Logger, error) { defaultCfg := DefaultLoggingConfig() defaultCfg.Level = level - return new(name, defaultCfg) + return new(name, defaultCfg, logInternal) } // NewFromConfig takes the user configuration and generate the right logger. // TODO: Finish implementation, need support on the library that we use. -func NewFromConfig(name string, cfg *Config) (*Logger, error) { - return new(name, cfg) +func NewFromConfig(name string, cfg *Config, logInternal bool) (*Logger, error) { + return new(name, cfg, logInternal) } -func new(name string, cfg *Config) (*Logger, error) { +func new(name string, cfg *Config, logInternal bool) (*Logger, error) { commonCfg, err := toCommonConfig(cfg) if err != nil { return nil, err } var outputs []zapcore.Core - if cfg.ToFiles { + if logInternal { internal, err := makeInternalFileOutput(cfg) if err != nil { return nil, err diff --git a/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go b/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go index 3ece027a7aa..991d617f2b8 100644 --- a/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go +++ b/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go @@ -5,7 +5,9 @@ package beats import ( + "crypto/sha256" "fmt" + "path/filepath" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/program" @@ -17,13 +19,9 @@ const ( // args: data path, install path, pipeline name, application name logFileFormatWin = "%s\\logs\\%s\\%s-json.log" - // args: pipeline name, application name - mbEndpointFileFormat = "unix:///tmp/elastic-agent/%s/%s/%s.sock" // args: pipeline name, application name mbEndpointFileFormatWin = `npipe:///%s-%s` - // args: pipeline name, application name - agentMbEndpointFileFormat = "unix:///tmp/elastic-agent/elastic-agent.sock" // args: pipeline name, application name agentMbEndpointFileFormatWin = `npipe:///elastic-agent` ) @@ -35,7 +33,14 @@ func getMonitoringEndpoint(spec program.Spec, operatingSystem, pipelineID string if operatingSystem == "windows" { return fmt.Sprintf(mbEndpointFileFormatWin, pipelineID, spec.Cmd) } - return fmt.Sprintf(mbEndpointFileFormat, pipelineID, spec.Cmd, spec.Cmd) + // unix socket path cannot be longer than 107 characters + path := fmt.Sprintf("unix://%s.sock", filepath.Join(paths.TempDir(), pipelineID, spec.Cmd, spec.Cmd)) + if len(path) <= 107 { + return path + } + // place in global /tmp to ensure that its small enough to fit; current path is way to long + // for it to be used, but needs to be unique per Agent (in the case that multiple are running) + return fmt.Sprintf(`unix:///tmp/elastic-agent-%x.sock`, sha256.Sum256([]byte(path))) } func getLoggingFile(spec program.Spec, operatingSystem, installPath, pipelineID string) string { @@ -53,7 +58,14 @@ func AgentMonitoringEndpoint(operatingSystem string) string { if operatingSystem == "windows" { return agentMbEndpointFileFormatWin } - return agentMbEndpointFileFormat + // unix socket path cannot be longer than 107 characters + path := fmt.Sprintf("unix://%s.sock", filepath.Join(paths.TempDir(), "elastic-agent")) + if len(path) <= 107 { + return path + } + // place in global /tmp to ensure that its small enough to fit; current path is way to long + // for it to be used, but needs to be unique per Agent (in the case that multiple are running) + return fmt.Sprintf(`unix:///tmp/elastic-agent-%x.sock`, sha256.Sum256([]byte(path))) } // AgentPrefixedMonitoringEndpoint returns endpoint with exposed metrics for agent. diff --git a/x-pack/elastic-agent/pkg/core/server/server_test.go b/x-pack/elastic-agent/pkg/core/server/server_test.go index 9a8e1e9d385..d1d1aa5bf2e 100644 --- a/x-pack/elastic-agent/pkg/core/server/server_test.go +++ b/x-pack/elastic-agent/pkg/core/server/server_test.go @@ -627,7 +627,7 @@ func newErrorLogger(t *testing.T) *logger.Logger { loggerCfg := logger.DefaultLoggingConfig() loggerCfg.Level = logp.ErrorLevel - log, err := logger.NewFromConfig("", loggerCfg) + log, err := logger.NewFromConfig("", loggerCfg, false) require.NoError(t, err) return log } diff --git a/x-pack/elastic-agent/pkg/core/status/reporter_test.go b/x-pack/elastic-agent/pkg/core/status/reporter_test.go index 55fcd3e04fe..bc601155a43 100644 --- a/x-pack/elastic-agent/pkg/core/status/reporter_test.go +++ b/x-pack/elastic-agent/pkg/core/status/reporter_test.go @@ -14,7 +14,7 @@ import ( ) func TestReporter(t *testing.T) { - l, _ := logger.New("") + l, _ := logger.New("", false) t.Run("healthy by default", func(t *testing.T) { r := NewController(l) assert.Equal(t, Healthy, r.StatusCode()) diff --git a/x-pack/elastic-agent/pkg/filewatcher/watcher.go b/x-pack/elastic-agent/pkg/filewatcher/watcher.go index 03619a04135..1961ce1f030 100644 --- a/x-pack/elastic-agent/pkg/filewatcher/watcher.go +++ b/x-pack/elastic-agent/pkg/filewatcher/watcher.go @@ -50,7 +50,7 @@ type Watch struct { func New(log *logger.Logger, f Comparer) (*Watch, error) { var err error if log == nil { - log, err = logger.New("watcher") + log, err = logger.New("watcher", false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker_test.go b/x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker_test.go index 91533ff1ec8..4facc9c63ed 100644 --- a/x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker_test.go +++ b/x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker_test.go @@ -27,7 +27,7 @@ func TestAcker(t *testing.T) { Events []fleetapi.AckEvent `json:"events"` } - log, _ := logger.New("fleet_acker") + log, _ := logger.New("fleet_acker", false) client := newTestingClient() agentInfo := &testAgentInfo{} acker, err := NewAcker(log, agentInfo, client) diff --git a/x-pack/elastic-agent/pkg/fleetapi/acker/lazy/lazy_acker_test.go b/x-pack/elastic-agent/pkg/fleetapi/acker/lazy/lazy_acker_test.go index fb24d291207..1e34d303bc5 100644 --- a/x-pack/elastic-agent/pkg/fleetapi/acker/lazy/lazy_acker_test.go +++ b/x-pack/elastic-agent/pkg/fleetapi/acker/lazy/lazy_acker_test.go @@ -29,7 +29,7 @@ func TestLazyAcker(t *testing.T) { Events []fleetapi.AckEvent `json:"events"` } - log, _ := logger.New("") + log, _ := logger.New("", false) client := newTestingClient() agentInfo := &testAgentInfo{} acker, err := fleet.NewAcker(log, agentInfo, client) diff --git a/x-pack/elastic-agent/pkg/fleetapi/client/client.go b/x-pack/elastic-agent/pkg/fleetapi/client/client.go index 6fe59c14429..8f9fcd7bc98 100644 --- a/x-pack/elastic-agent/pkg/fleetapi/client/client.go +++ b/x-pack/elastic-agent/pkg/fleetapi/client/client.go @@ -50,7 +50,7 @@ func init() { return nil, err } - l, err := logger.New("fleet_client") + l, err := logger.New("fleet_client", false) if err != nil { return nil, errors.New(err, "could not create the logger for debugging HTTP request") } diff --git a/x-pack/elastic-agent/pkg/fleetapi/helper_test.go b/x-pack/elastic-agent/pkg/fleetapi/helper_test.go index 87e046dfe6c..4650eb5c4ff 100644 --- a/x-pack/elastic-agent/pkg/fleetapi/helper_test.go +++ b/x-pack/elastic-agent/pkg/fleetapi/helper_test.go @@ -46,7 +46,7 @@ func withServerWithAuthClient( ) func(t *testing.T) { return withServer(m, func(t *testing.T, host string) { - log, _ := logger.New("") + log, _ := logger.New("", false) cfg := &kibana.Config{ Host: host, } diff --git a/x-pack/elastic-agent/pkg/kibana/client.go b/x-pack/elastic-agent/pkg/kibana/client.go index 083aa8d0d83..24be2e7f05e 100644 --- a/x-pack/elastic-agent/pkg/kibana/client.go +++ b/x-pack/elastic-agent/pkg/kibana/client.go @@ -79,7 +79,7 @@ func NewConfigFromURL(kURL string) (*Config, error) { func NewWithRawConfig(log *logger.Logger, config *config.Config, wrapper wrapperFunc) (*Client, error) { l := log if l == nil { - log, err := logger.New("kibana_client") + log, err := logger.New("kibana_client", false) if err != nil { return nil, err } diff --git a/x-pack/elastic-agent/pkg/kibana/client_test.go b/x-pack/elastic-agent/pkg/kibana/client_test.go index 7fa0aea16e0..7dff58ffb6f 100644 --- a/x-pack/elastic-agent/pkg/kibana/client_test.go +++ b/x-pack/elastic-agent/pkg/kibana/client_test.go @@ -35,7 +35,7 @@ func addCatchAll(mux *http.ServeMux, t *testing.T) *http.ServeMux { } func TestPortDefaults(t *testing.T) { - l, err := logger.New("") + l, err := logger.New("", false) require.NoError(t, err) testCases := []struct { @@ -70,7 +70,7 @@ func TestPortDefaults(t *testing.T) { // - Prefix. func TestHTTPClient(t *testing.T) { ctx := context.Background() - l, err := logger.New("") + l, err := logger.New("", false) require.NoError(t, err) t.Run("Guard against double slashes on path", withServer( diff --git a/x-pack/elastic-agent/pkg/reporter/fleet/reporter_test.go b/x-pack/elastic-agent/pkg/reporter/fleet/reporter_test.go index 8d25852efe7..ce307e1fbab 100644 --- a/x-pack/elastic-agent/pkg/reporter/fleet/reporter_test.go +++ b/x-pack/elastic-agent/pkg/reporter/fleet/reporter_test.go @@ -209,7 +209,7 @@ func getEvents(count int) []reporter.Event { } func newTestReporter(frequency time.Duration, threshold int) *Reporter { - log, _ := logger.New("") + log, _ := logger.New("", false) r := &Reporter{ info: &testInfo{}, queue: make([]fleetapi.SerializableEvent, 0),