Skip to content

Commit db38eb4

Browse files
committed
Fixed reload of boolean flags
PR #874 caused an issue in case logtime was actually not configured and not specified in the command line. A reload would then remove logtime. Revisited the fix for that and included other boolean flags, such as debug, trace, etc.. Signed-off-by: Ivan Kozlovic <[email protected]>
1 parent 526c49d commit db38eb4

File tree

3 files changed

+457
-42
lines changed

3 files changed

+457
-42
lines changed

server/opts.go

+45-17
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ type Options struct {
143143
// CheckConfig configuration file syntax test was successful and exit.
144144
CheckConfig bool `json:"-"`
145145

146+
// private fields, used to know if bool options are explicitly
147+
// defined in config and/or command line params.
148+
inConfig map[string]bool
149+
inCmdLine map[string]bool
150+
146151
// private fields, used for testing
147152
gatewaysSolicitDelay time.Duration
148153
}
@@ -340,10 +345,13 @@ func (o *Options) ProcessConfigFile(configFile string) error {
340345
o.Host = v.(string)
341346
case "debug":
342347
o.Debug = v.(bool)
348+
trackExplicitVal(o, &o.inConfig, "Debug", o.Debug)
343349
case "trace":
344350
o.Trace = v.(bool)
351+
trackExplicitVal(o, &o.inConfig, "Trace", o.Trace)
345352
case "logtime":
346353
o.Logtime = v.(bool)
354+
trackExplicitVal(o, &o.inConfig, "Logtime", o.Logtime)
347355
case "accounts":
348356
err := parseAccounts(tk, o, &errors, &warnings)
349357
if err != nil {
@@ -424,6 +432,7 @@ func (o *Options) ProcessConfigFile(configFile string) error {
424432
o.LogFile = v.(string)
425433
case "syslog":
426434
o.Syslog = v.(bool)
435+
trackExplicitVal(o, &o.inConfig, "Syslog", o.Syslog)
427436
case "remote_syslog":
428437
o.RemoteSyslog = v.(string)
429438
case "pidfile", "pid_file":
@@ -630,6 +639,15 @@ func (o *Options) ProcessConfigFile(configFile string) error {
630639
return nil
631640
}
632641

642+
func trackExplicitVal(opts *Options, pm *map[string]bool, name string, val bool) {
643+
m := *pm
644+
if m == nil {
645+
m = make(map[string]bool)
646+
*pm = m
647+
}
648+
m[name] = val
649+
}
650+
633651
// hostPort is simple struct to hold parsed listen/addr strings.
634652
type hostPort struct {
635653
host string
@@ -732,6 +750,7 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err
732750
opts.Cluster.Advertise = mv.(string)
733751
case "no_advertise":
734752
opts.Cluster.NoAdvertise = mv.(bool)
753+
trackExplicitVal(opts, &opts.inConfig, "Cluster.NoAdvertise", opts.Cluster.NoAdvertise)
735754
case "connect_retries":
736755
opts.Cluster.ConnectRetries = int(mv.(int64))
737756
case "permissions":
@@ -2190,12 +2209,10 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp,
21902209
showTLSHelp bool
21912210
signal string
21922211
configFile string
2212+
dbgAndTrace bool
21932213
err error
21942214
)
21952215

2196-
// IMPORTANT: If you add boolean flags and use a 'true' as the default,
2197-
// check what needs to be done for FlagSnapshot down below.
2198-
// See logtimeIsExplicitlySet for reference.
21992216
fs.BoolVar(&showHelp, "h", false, "Show this message.")
22002217
fs.BoolVar(&showHelp, "help", false, "Show this message.")
22012218
fs.IntVar(&opts.Port, "port", 0, "Port to listen on.")
@@ -2208,7 +2225,7 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp,
22082225
fs.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.")
22092226
fs.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.")
22102227
fs.BoolVar(&opts.Trace, "trace", false, "Enable Trace logging.")
2211-
fs.Bool("DV", false, "Enable Debug and Trace logging.")
2228+
fs.BoolVar(&dbgAndTrace, "DV", false, "Enable Debug and Trace logging.")
22122229
fs.BoolVar(&opts.Logtime, "T", true, "Timestamp log entries.")
22132230
fs.BoolVar(&opts.Logtime, "logtime", true, "Timestamp log entries.")
22142231
fs.StringVar(&opts.Username, "user", "", "Username required for connection.")
@@ -2247,7 +2264,6 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp,
22472264
fs.StringVar(&opts.TLSCert, "tlscert", "", "Server certificate file.")
22482265
fs.StringVar(&opts.TLSKey, "tlskey", "", "Private key for server certificate.")
22492266
fs.StringVar(&opts.TLSCaCert, "tlscacert", "", "Client certificate CA for verification.")
2250-
// --- See comment on top of flags definition before adding a flag ---
22512267

22522268
// The flags definition above set "default" values to some of the options.
22532269
// Calling Parse() here will override the default options with any value
@@ -2292,19 +2308,32 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp,
22922308
// Snapshot flag options.
22932309
FlagSnapshot = opts.Clone()
22942310

2295-
// Before parsing the config file, we need to know if boolean
2296-
// flags are explicitly set or not, and for those which default
2297-
// to `true`, we need to reset them otherwise config reload would
2298-
// incorrectly override what is in the config file.
2299-
logtimeIsExplicitlySet := false
2311+
// Keep track of the boolean flags that were explicitly set with their value.
23002312
fs.Visit(func(f *flag.Flag) {
2301-
if f.Name == "logtime" {
2302-
logtimeIsExplicitlySet = true
2313+
switch f.Name {
2314+
case "DV":
2315+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", dbgAndTrace)
2316+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", dbgAndTrace)
2317+
case "D":
2318+
fallthrough
2319+
case "debug":
2320+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", FlagSnapshot.Debug)
2321+
case "V":
2322+
fallthrough
2323+
case "trace":
2324+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", FlagSnapshot.Trace)
2325+
case "T":
2326+
fallthrough
2327+
case "logtime":
2328+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Logtime", FlagSnapshot.Logtime)
2329+
case "s":
2330+
fallthrough
2331+
case "syslog":
2332+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Syslog", FlagSnapshot.Syslog)
2333+
case "no_advertise":
2334+
trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Cluster.NoAdvertise", FlagSnapshot.Cluster.NoAdvertise)
23032335
}
23042336
})
2305-
if !logtimeIsExplicitlySet {
2306-
FlagSnapshot.Logtime = false
2307-
}
23082337

23092338
// Process signal control.
23102339
if signal != "" {
@@ -2371,8 +2400,7 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp,
23712400
switch f.Name {
23722401
case "DV":
23732402
// Check value to support -DV=false
2374-
boolValue, _ := strconv.ParseBool(f.Value.String())
2375-
opts.Trace, opts.Debug = boolValue, boolValue
2403+
opts.Trace, opts.Debug = dbgAndTrace, dbgAndTrace
23762404
case "cluster", "cluster_listen":
23772405
// Override cluster config if explicitly set via flags.
23782406
flagErr = overrideCluster(opts)

server/reload.go

+29
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,10 @@ func (s *Server) Reload() error {
518518

519519
// Apply flags over config file settings.
520520
newOpts = MergeOptions(newOpts, FlagSnapshot)
521+
522+
// Need more processing for boolean flags...
523+
applyBoolFlags(newOpts, FlagSnapshot)
524+
521525
setBaselineOptions(newOpts)
522526

523527
// processOptions sets Port to 0 if set to -1 (RANDOM port)
@@ -543,6 +547,31 @@ func (s *Server) Reload() error {
543547
return nil
544548
}
545549

550+
func applyBoolFlags(newOpts, flagOpts *Options) {
551+
// Reset fields that may have been set to `true` in
552+
// MergeOptions() when some of the flags default to `true`
553+
// but have not been explicitly set and therefore value
554+
// from config file should take precedence.
555+
for name, val := range newOpts.inConfig {
556+
f := reflect.ValueOf(newOpts).Elem()
557+
names := strings.Split(name, ".")
558+
for _, name := range names {
559+
f = f.FieldByName(name)
560+
}
561+
f.SetBool(val)
562+
}
563+
// Now apply value (true or false) from flags that have
564+
// been explicitly set in command line
565+
for name, val := range flagOpts.inCmdLine {
566+
f := reflect.ValueOf(newOpts).Elem()
567+
names := strings.Split(name, ".")
568+
for _, name := range names {
569+
f = f.FieldByName(name)
570+
}
571+
f.SetBool(val)
572+
}
573+
}
574+
546575
// reloadOptions reloads the server config with the provided options. If an
547576
// option that doesn't support hot-swapping is changed, this returns an error.
548577
func (s *Server) reloadOptions(newOpts *Options) error {

0 commit comments

Comments
 (0)