179 lines
5.1 KiB
Go
179 lines
5.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package command
|
|
|
|
import (
|
|
"flag"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/hashicorp/vault/internalshared/configutil"
|
|
"github.com/posener/complete"
|
|
)
|
|
|
|
// logFlags are the 'log' related flags that can be shared across commands.
|
|
type logFlags struct {
|
|
flagCombineLogs bool
|
|
flagLogLevel string
|
|
flagLogFormat string
|
|
flagLogFile string
|
|
flagLogRotateBytes int
|
|
flagLogRotateDuration string
|
|
flagLogRotateMaxFiles int
|
|
}
|
|
|
|
// valuesProvider has the intention of providing a way to supply a func with a
|
|
// way to retrieve values for flags and environment variables without having to
|
|
// directly call a specific implementation.
|
|
// The reasoning for its existence is to facilitate testing.
|
|
type valuesProvider struct {
|
|
flagProvider func(string) (flag.Value, bool)
|
|
envVarProvider func(string) (string, bool)
|
|
}
|
|
|
|
// addLogFlags will add the set of 'log' related flags to a flag set.
|
|
func (f *FlagSet) addLogFlags(l *logFlags) {
|
|
f.BoolVar(&BoolVar{
|
|
Name: flagNameCombineLogs,
|
|
Target: &l.flagCombineLogs,
|
|
Default: false,
|
|
Hidden: true,
|
|
})
|
|
|
|
f.StringVar(&StringVar{
|
|
Name: flagNameLogLevel,
|
|
Target: &l.flagLogLevel,
|
|
Default: notSetValue,
|
|
EnvVar: EnvVaultLogLevel,
|
|
Completion: complete.PredictSet("trace", "debug", "info", "warn", "error"),
|
|
Usage: "Log verbosity level. Supported values (in order of detail) are " +
|
|
"\"trace\", \"debug\", \"info\", \"warn\", and \"error\".",
|
|
})
|
|
|
|
f.StringVar(&StringVar{
|
|
Name: flagNameLogFormat,
|
|
Target: &l.flagLogFormat,
|
|
Default: notSetValue,
|
|
EnvVar: EnvVaultLogFormat,
|
|
Completion: complete.PredictSet("standard", "json"),
|
|
Usage: `Log format. Supported values are "standard" and "json".`,
|
|
})
|
|
|
|
f.StringVar(&StringVar{
|
|
Name: flagNameLogFile,
|
|
Target: &l.flagLogFile,
|
|
Usage: "Path to the log file that Vault should use for logging",
|
|
})
|
|
|
|
f.IntVar(&IntVar{
|
|
Name: flagNameLogRotateBytes,
|
|
Target: &l.flagLogRotateBytes,
|
|
Usage: "Number of bytes that should be written to a log before it needs to be rotated. " +
|
|
"Unless specified, there is no limit to the number of bytes that can be written to a log file",
|
|
})
|
|
|
|
f.StringVar(&StringVar{
|
|
Name: flagNameLogRotateDuration,
|
|
Target: &l.flagLogRotateDuration,
|
|
Usage: "The maximum duration a log should be written to before it needs to be rotated. " +
|
|
"Must be a duration value such as 30s",
|
|
})
|
|
|
|
f.IntVar(&IntVar{
|
|
Name: flagNameLogRotateMaxFiles,
|
|
Target: &l.flagLogRotateMaxFiles,
|
|
Usage: "The maximum number of older log file archives to keep",
|
|
})
|
|
}
|
|
|
|
// envVarValue attempts to get a named value from the environment variables.
|
|
// The value will be returned as a string along with a boolean value indiciating
|
|
// to the caller whether the named env var existed.
|
|
func envVarValue(key string) (string, bool) {
|
|
if key == "" {
|
|
return "", false
|
|
}
|
|
return os.LookupEnv(key)
|
|
}
|
|
|
|
// flagValue attempts to find the named flag in a set of FlagSets.
|
|
// The flag.Value is returned if it was specified, and the boolean value indicates
|
|
// to the caller if the flag was specified by the end user.
|
|
func (f *FlagSets) flagValue(flagName string) (flag.Value, bool) {
|
|
var result flag.Value
|
|
var isFlagSpecified bool
|
|
|
|
if f != nil {
|
|
f.Visit(func(fl *flag.Flag) {
|
|
if fl.Name == flagName {
|
|
result = fl.Value
|
|
isFlagSpecified = true
|
|
}
|
|
})
|
|
}
|
|
|
|
return result, isFlagSpecified
|
|
}
|
|
|
|
// overrideValue uses the provided keys to check CLI flags and environment
|
|
// variables for values that may be used to override any specified configuration.
|
|
func (p *valuesProvider) overrideValue(flagKey, envVarKey string) (string, bool) {
|
|
var result string
|
|
found := true
|
|
|
|
flg, flgFound := p.flagProvider(flagKey)
|
|
env, envFound := p.envVarProvider(envVarKey)
|
|
|
|
switch {
|
|
case flgFound:
|
|
result = flg.String()
|
|
case envFound:
|
|
result = env
|
|
default:
|
|
found = false
|
|
}
|
|
|
|
return result, found
|
|
}
|
|
|
|
// applyLogConfigOverrides will accept a shared config and specifically attempt to update the 'log' related config keys.
|
|
// For each 'log' key, we aggregate file config, env vars and CLI flags to select the one with the highest precedence.
|
|
// This method mutates the config object passed into it.
|
|
func (f *FlagSets) applyLogConfigOverrides(config *configutil.SharedConfig) {
|
|
p := &valuesProvider{
|
|
flagProvider: f.flagValue,
|
|
envVarProvider: envVarValue,
|
|
}
|
|
|
|
// Update log level
|
|
if val, found := p.overrideValue(flagNameLogLevel, EnvVaultLogLevel); found {
|
|
config.LogLevel = val
|
|
}
|
|
|
|
// Update log format
|
|
if val, found := p.overrideValue(flagNameLogFormat, EnvVaultLogFormat); found {
|
|
config.LogFormat = val
|
|
}
|
|
|
|
// Update log file name
|
|
if val, found := p.overrideValue(flagNameLogFile, ""); found {
|
|
config.LogFile = val
|
|
}
|
|
|
|
// Update log rotation duration
|
|
if val, found := p.overrideValue(flagNameLogRotateDuration, ""); found {
|
|
config.LogRotateDuration = val
|
|
}
|
|
|
|
// Update log max files
|
|
if val, found := p.overrideValue(flagNameLogRotateMaxFiles, ""); found {
|
|
config.LogRotateMaxFiles, _ = strconv.Atoi(val)
|
|
}
|
|
|
|
// Update log rotation max bytes
|
|
if val, found := p.overrideValue(flagNameLogRotateBytes, ""); found {
|
|
config.LogRotateBytes, _ = strconv.Atoi(val)
|
|
}
|
|
}
|