forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog_flags.go
175 lines (149 loc) · 5.06 KB
/
log_flags.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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)
}
}