diff --git a/internalshared/configutil/config.go b/internalshared/configutil/config.go index f4c2ec11ad349..1e4d39315728c 100644 --- a/internalshared/configutil/config.go +++ b/internalshared/configutil/config.go @@ -38,12 +38,12 @@ type SharedConfig struct { // LogFormat specifies the log format. Valid values are "standard" and // "json". The values are case-insenstive. If no log format is specified, // then standard format will be used. + LogFile string `hcl:"log_file"` LogFormat string `hcl:"log_format"` LogLevel string `hcl:"log_level"` - LogFile string `hcl:"log_file"` - LogRotateDuration string `hcl:"log_rotate_duration"` LogRotateBytes int `hcl:"log_rotate_bytes"` LogRotateBytesRaw interface{} `hcl:"log_rotate_bytes"` + LogRotateDuration string `hcl:"log_rotate_duration"` LogRotateMaxFiles int `hcl:"log_rotate_max_files"` LogRotateMaxFilesRaw interface{} `hcl:"log_rotate_max_files"` @@ -164,16 +164,26 @@ func (c *SharedConfig) Sanitized() map[string]interface{} { } result := map[string]interface{}{ - "disable_mlock": c.DisableMlock, - + "cluster_name": c.ClusterName, "default_max_request_duration": c.DefaultMaxRequestDuration, + "disable_mlock": c.DisableMlock, + "log_format": c.LogFormat, + "log_level": c.LogLevel, + "pid_file": c.PidFile, + } - "log_level": c.LogLevel, - "log_format": c.LogFormat, - - "pid_file": c.PidFile, - - "cluster_name": c.ClusterName, + // Optional log related settings + if c.LogFile != "" { + result["log_file"] = c.LogFile + } + if c.LogRotateBytes != 0 { + result["log_rotate_bytes"] = c.LogRotateBytes + } + if c.LogRotateDuration != "" { + result["log_rotate_duration"] = c.LogRotateDuration + } + if c.LogRotateMaxFiles != 0 { + result["log_rotate_max_files"] = c.LogRotateMaxFiles } // Sanitize listeners diff --git a/internalshared/configutil/config_test.go b/internalshared/configutil/config_test.go new file mode 100644 index 0000000000000..e44bf7f991612 --- /dev/null +++ b/internalshared/configutil/config_test.go @@ -0,0 +1,157 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package configutil + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type mapValue[T any] struct { + Value T + IsFound bool +} + +type expectedLogFields struct { + File mapValue[string] + Format mapValue[string] + Level mapValue[string] + RotateBytes mapValue[int] + RotateDuration mapValue[string] + RotateMaxFiles mapValue[int] +} + +// TestSharedConfig_Sanitized_LogFields ensures that 'log related' shared config +// is sanitized as expected. +func TestSharedConfig_Sanitized_LogFields(t *testing.T) { + tests := map[string]struct { + Value *SharedConfig + IsNil bool + Expected expectedLogFields + }{ + "nil": { + Value: nil, + IsNil: true, + }, + "empty": { + Value: &SharedConfig{}, + IsNil: false, + Expected: expectedLogFields{ + Format: mapValue[string]{IsFound: true, Value: ""}, + Level: mapValue[string]{IsFound: true, Value: ""}, + }, + }, + "only-log-level-and-format": { + Value: &SharedConfig{ + LogFormat: "json", + LogLevel: "warn", + }, + IsNil: false, + Expected: expectedLogFields{ + Format: mapValue[string]{IsFound: true, Value: "json"}, + Level: mapValue[string]{IsFound: true, Value: "warn"}, + }, + }, + "valid-log-fields": { + Value: &SharedConfig{ + LogFile: "vault.log", + LogFormat: "json", + LogLevel: "warn", + LogRotateBytes: 1024, + LogRotateDuration: "30m", + LogRotateMaxFiles: -1, + }, + IsNil: false, + Expected: expectedLogFields{ + File: mapValue[string]{IsFound: true, Value: "vault.log"}, + Format: mapValue[string]{IsFound: true, Value: "json"}, + Level: mapValue[string]{IsFound: true, Value: "warn"}, + RotateBytes: mapValue[int]{IsFound: true, Value: 1024}, + RotateDuration: mapValue[string]{IsFound: true, Value: "30m"}, + RotateMaxFiles: mapValue[int]{IsFound: true, Value: -1}, + }, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + cfg := tc.Value.Sanitized() + switch { + case tc.IsNil: + require.Nil(t, cfg) + default: + require.NotNil(t, cfg) + + // Log file + val, found := cfg["log_file"] + switch { + case tc.Expected.File.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.File.Value, val) + default: + require.Nil(t, val) + } + + // Log format + val, found = cfg["log_format"] + switch { + case tc.Expected.Format.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.Format.Value, val) + default: + require.Nil(t, val) + } + + // Log level + val, found = cfg["log_level"] + switch { + case tc.Expected.Level.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.Level.Value, val) + default: + require.Nil(t, val) + } + + // Log rotate bytes + val, found = cfg["log_rotate_bytes"] + switch { + case tc.Expected.RotateBytes.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.RotateBytes.Value, val) + default: + require.Nil(t, val) + } + + // Log rotate duration + val, found = cfg["log_rotate_duration"] + switch { + case tc.Expected.RotateDuration.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.RotateDuration.Value, val) + default: + require.Nil(t, val) + } + + // Log rotate max files + val, found = cfg["log_rotate_max_files"] + switch { + case tc.Expected.RotateMaxFiles.IsFound: + require.True(t, found) + require.NotNil(t, val) + require.Equal(t, tc.Expected.RotateMaxFiles.Value, val) + default: + require.Nil(t, val) + } + } + }) + } +}