diff --git a/command/agent/agent.go b/command/agent/agent.go index c9be8c05274..54a695600dc 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -934,10 +934,14 @@ func (a *Agent) ShouldReload(newConfig *Config) (agent, http bool) { a.configLock.Lock() defer a.configLock.Unlock() + if newConfig.LogLevel != "" && newConfig.LogLevel != a.config.LogLevel { + agent = true + } + isEqual, err := a.config.TLSConfig.CertificateInfoIsEqual(newConfig.TLSConfig) if err != nil { a.logger.Error("parsing TLS certificate", "error", err) - return false, false + return agent, false } else if !isEqual { return true, true } @@ -962,13 +966,27 @@ func (a *Agent) Reload(newConfig *Config) error { a.configLock.Lock() defer a.configLock.Unlock() - if newConfig == nil || newConfig.TLSConfig == nil { + updatedLogging := newConfig != nil && (newConfig.LogLevel != a.config.LogLevel) + + if newConfig == nil || newConfig.TLSConfig == nil && !updatedLogging { return fmt.Errorf("cannot reload agent with nil configuration") } - // This is just a TLS configuration reload, we don't need to refresh - // existing network connections + if updatedLogging { + a.config.LogLevel = newConfig.LogLevel + a.logger.SetLevel(log.LevelFromString(newConfig.LogLevel)) + } + + fullUpdateTLSConfig := func() { + // Completely reload the agent's TLS configuration (moving from non-TLS to + // TLS, or vice versa) + // This does not handle errors in loading the new TLS configuration + a.config.TLSConfig = newConfig.TLSConfig.Copy() + } + if !a.config.TLSConfig.IsEmpty() && !newConfig.TLSConfig.IsEmpty() { + // This is just a TLS configuration reload, we don't need to refresh + // existing network connections // Reload the certificates on the keyloader and on success store the // updated TLS config. It is important to reuse the same keyloader @@ -983,17 +1001,12 @@ func (a *Agent) Reload(newConfig *Config) error { a.config.TLSConfig = newConfig.TLSConfig a.config.TLSConfig.KeyLoader = keyloader return nil - } - - // Completely reload the agent's TLS configuration (moving from non-TLS to - // TLS, or vice versa) - // This does not handle errors in loading the new TLS configuration - a.config.TLSConfig = newConfig.TLSConfig.Copy() - - if newConfig.TLSConfig.IsEmpty() { + } else if newConfig.TLSConfig.IsEmpty() && !a.config.TLSConfig.IsEmpty() { a.logger.Warn("downgrading agent's existing TLS configuration to plaintext") - } else { + fullUpdateTLSConfig() + } else if !newConfig.TLSConfig.IsEmpty() && a.config.TLSConfig.IsEmpty() { a.logger.Info("upgrading from plaintext configuration to TLS") + fullUpdateTLSConfig() } return nil diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index 07ebbdc4696..2fec663d4f1 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -441,6 +441,28 @@ func TestAgent_HTTPCheckPath(t *testing.T) { } } +// Here we validate that log levels get updated when the configuration is +// reloaded. I can't find a good way to fetch this from the logger itself, so +// we pull it only from the agents configuration struct, not the logger. +func TestAgent_Reload_LogLevel(t *testing.T) { + t.Parallel() + assert := assert.New(t) + + agent := NewTestAgent(t, t.Name(), func(c *Config) { + c.LogLevel = "INFO" + }) + defer agent.Shutdown() + + assert.Equal("INFO", agent.GetConfig().LogLevel) + + newConfig := &Config{ + LogLevel: "TRACE", + } + + assert.Nil(agent.Reload(newConfig)) + assert.Equal("TRACE", agent.GetConfig().LogLevel) +} + // This test asserts that the keyloader embedded in the TLS config is shared // across the Agent, Server, and Client. This is essential for certificate // reloading to work. diff --git a/command/agent/log_levels.go b/command/agent/log_levels.go index a0f29c6220b..f4455e47f86 100644 --- a/command/agent/log_levels.go +++ b/command/agent/log_levels.go @@ -10,7 +10,7 @@ import ( // levels that we use. func LevelFilter() *logutils.LevelFilter { return &logutils.LevelFilter{ - Levels: []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERR"}, + Levels: []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}, MinLevel: "INFO", Writer: ioutil.Discard, }