From b4b85bd83add340655779d1c3e58afde6e0011cf Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Wed, 2 Jun 2021 17:12:44 -0400 Subject: [PATCH] agent: fix agent logging Remove the leading whitespace on every log line. This was causing problems for a customer because their logging system was interpretting the logs as a single multi-line log. --- command/agent/agent.go | 47 ++++++++++++++++++++----------------- command/agent/agent_test.go | 25 ++++++++++++++++---- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 4a1f8314f8..cbf3d78583 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -13,10 +13,11 @@ import ( "github.com/hashicorp/go-checkpoint" "github.com/hashicorp/go-hclog" - "github.com/mitchellh/cli" + mcli "github.com/mitchellh/cli" "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent/config" + "github.com/hashicorp/consul/command/cli" "github.com/hashicorp/consul/command/flags" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" @@ -25,15 +26,8 @@ import ( ) func New(ui cli.Ui) *cmd { - ui = &cli.PrefixedUi{ - OutputPrefix: "==> ", - InfoPrefix: " ", - ErrorPrefix: "==> ", - Ui: ui, - } - c := &cmd{ - UI: ui, + ui: ui, revision: consulversion.GitCommit, version: consulversion.Version, versionPrerelease: consulversion.VersionPrerelease, @@ -50,7 +44,7 @@ func New(ui cli.Ui) *cmd { // ShutdownCh. If two messages are sent on the ShutdownCh it will forcibly // exit. type cmd struct { - UI cli.Ui + ui cli.Ui flags *flag.FlagSet http *flags.HTTPFlags help string @@ -118,7 +112,7 @@ func (c *cmd) startupJoin(agent *agent.Agent, cfg *config.RuntimeConfig) error { return nil } - c.UI.Output("Joining cluster...") + c.logger.Info("Joining cluster") n, err := agent.JoinLAN(cfg.StartJoinAddrsLAN) if err != nil { return err @@ -134,43 +128,52 @@ func (c *cmd) startupJoinWan(agent *agent.Agent, cfg *config.RuntimeConfig) erro return nil } - c.UI.Output("Joining -wan cluster...") + c.logger.Info("Joining wan cluster") n, err := agent.JoinWAN(cfg.StartJoinAddrsWAN) if err != nil { return err } - c.logger.Info("Join -wan completed. Initial agents synced with", "agent_count", n) + c.logger.Info("Join wan completed. Initial agents synced with", "agent_count", n) return nil } func (c *cmd) run(args []string) int { + ui := &mcli.PrefixedUi{ + OutputPrefix: "==> ", + InfoPrefix: " ", + ErrorPrefix: "==> ", + Ui: c.ui, + } + if err := c.flags.Parse(args); err != nil { if !strings.Contains(err.Error(), "help requested") { - c.UI.Error(fmt.Sprintf("error parsing flags: %v", err)) + ui.Error(fmt.Sprintf("error parsing flags: %v", err)) } return 1 } if len(c.flags.Args()) > 0 { - c.UI.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args())) + ui.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args())) return 1 } - logGate := &logging.GatedWriter{Writer: &cli.UiWriter{Ui: c.UI}} + // FIXME: logs should always go to stderr, but previously they were sent to + // stdout, so continue to use Stdout for now, and fix this in a future release. + logGate := &logging.GatedWriter{Writer: c.ui.Stdout()} loader := func(source config.Source) (config.LoadResult, error) { c.configLoadOpts.DefaultConfig = source return config.Load(c.configLoadOpts) } bd, err := agent.NewBaseDeps(loader, logGate) if err != nil { - c.UI.Error(err.Error()) + ui.Error(err.Error()) return 1 } c.logger = bd.Logger agent, err := agent.New(bd) if err != nil { - c.UI.Error(err.Error()) + ui.Error(err.Error()) return 1 } @@ -179,7 +182,7 @@ func (c *cmd) run(args []string) int { // Setup gate to check if we should output CLI information cli := GatedUi{ JSONoutput: config.Logging.LogJSON, - ui: c.UI, + ui: ui, } // Create the agent @@ -255,12 +258,12 @@ func (c *cmd) run(args []string) int { } if err := c.startupJoin(agent, config); err != nil { - c.logger.Error((err.Error())) + c.logger.Error(err.Error()) return 1 } if err := c.startupJoinWan(agent, config); err != nil { - c.logger.Error((err.Error())) + c.logger.Error(err.Error()) return 1 } @@ -340,7 +343,7 @@ func (c *cmd) run(args []string) int { type GatedUi struct { JSONoutput bool - ui cli.Ui + ui mcli.Ui } func (g *GatedUi) output(s string) { diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index d6b9f0a646..074702130a 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -2,6 +2,7 @@ package agent import ( "fmt" + "io" "os" "os/exec" "path/filepath" @@ -120,7 +121,7 @@ func TestRetryJoinFail(t *testing.T) { t.Parallel() tmpDir := testutil.TempDir(t, "consul") - ui := cli.NewMockUi() + ui := newCaptureUI() cmd := New(ui) args := []string{ @@ -144,7 +145,7 @@ func TestRetryJoinWanFail(t *testing.T) { t.Parallel() tmpDir := testutil.TempDir(t, "consul") - ui := cli.NewMockUi() + ui := newCaptureUI() cmd := New(ui) args := []string{ @@ -183,7 +184,7 @@ func TestProtectDataDir(t *testing.T) { t.Fatalf("err: %v", err) } - ui := cli.NewMockUi() + ui := newCaptureUI() cmd := New(ui) args := []string{"-config-file=" + cfgFile.Name()} if code := cmd.Run(args); code == 0 { @@ -202,7 +203,7 @@ func TestBadDataDirPermissions(t *testing.T) { t.Fatalf("err: %v", err) } - ui := cli.NewMockUi() + ui := newCaptureUI() cmd := New(ui) args := []string{"-data-dir=" + dataDir, "-server=true", "-bind=10.0.0.1"} if code := cmd.Run(args); code == 0 { @@ -212,3 +213,19 @@ func TestBadDataDirPermissions(t *testing.T) { t.Fatalf("expected permission denied error, got: %s", out) } } + +type captureUI struct { + *cli.MockUi +} + +func (c *captureUI) Stdout() io.Writer { + return c.MockUi.OutputWriter +} + +func (c *captureUI) Stderr() io.Writer { + return c.MockUi.ErrorWriter +} + +func newCaptureUI() *captureUI { + return &captureUI{MockUi: cli.NewMockUi()} +}