|
@@ -80,7 +80,7 @@ type CommonConfig struct {
|
|
Hosts []string `json:"hosts,omitempty"`
|
|
Hosts []string `json:"hosts,omitempty"`
|
|
LogLevel string `json:"log-level,omitempty"`
|
|
LogLevel string `json:"log-level,omitempty"`
|
|
TLS bool `json:"tls,omitempty"`
|
|
TLS bool `json:"tls,omitempty"`
|
|
- TLSVerify bool `json:"tls-verify,omitempty"`
|
|
|
|
|
|
+ TLSVerify bool `json:"tlsverify,omitempty"`
|
|
TLSOptions CommonTLSOptions `json:"tls-opts,omitempty"`
|
|
TLSOptions CommonTLSOptions `json:"tls-opts,omitempty"`
|
|
|
|
|
|
reloadLock sync.Mutex
|
|
reloadLock sync.Mutex
|
|
@@ -215,16 +215,43 @@ func configValuesSet(config map[string]interface{}) map[string]interface{} {
|
|
}
|
|
}
|
|
|
|
|
|
// findConfigurationConflicts iterates over the provided flags searching for
|
|
// findConfigurationConflicts iterates over the provided flags searching for
|
|
-// duplicated configurations. It returns an error with all the conflicts if
|
|
|
|
|
|
+// duplicated configurations and unknown keys. It returns an error with all the conflicts if
|
|
// it finds any.
|
|
// it finds any.
|
|
func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagSet) error {
|
|
func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagSet) error {
|
|
- var conflicts []string
|
|
|
|
|
|
+ // 1. Search keys from the file that we don't recognize as flags.
|
|
|
|
+ unknownKeys := make(map[string]interface{})
|
|
|
|
+ for key, value := range config {
|
|
|
|
+ flagName := "-" + key
|
|
|
|
+ if flag := flags.Lookup(flagName); flag == nil {
|
|
|
|
+ unknownKeys[key] = value
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 2. Discard keys that might have a given name, like `labels`.
|
|
|
|
+ unknownNamedConflicts := func(f *flag.Flag) {
|
|
|
|
+ if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
|
|
+ if _, valid := unknownKeys[namedOption.Name()]; valid {
|
|
|
|
+ delete(unknownKeys, namedOption.Name())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ flags.VisitAll(unknownNamedConflicts)
|
|
|
|
+
|
|
|
|
+ if len(unknownKeys) > 0 {
|
|
|
|
+ var unknown []string
|
|
|
|
+ for key := range unknownKeys {
|
|
|
|
+ unknown = append(unknown, key)
|
|
|
|
+ }
|
|
|
|
+ return fmt.Errorf("the following directives don't match any configuration option: %s", strings.Join(unknown, ", "))
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ var conflicts []string
|
|
printConflict := func(name string, flagValue, fileValue interface{}) string {
|
|
printConflict := func(name string, flagValue, fileValue interface{}) string {
|
|
return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue)
|
|
return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue)
|
|
}
|
|
}
|
|
|
|
|
|
- collectConflicts := func(f *flag.Flag) {
|
|
|
|
|
|
+ // 3. Search keys that are present as a flag and as a file option.
|
|
|
|
+ duplicatedConflicts := func(f *flag.Flag) {
|
|
// search option name in the json configuration payload if the value is a named option
|
|
// search option name in the json configuration payload if the value is a named option
|
|
if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
if optsValue, ok := config[namedOption.Name()]; ok {
|
|
if optsValue, ok := config[namedOption.Name()]; ok {
|
|
@@ -243,7 +270,7 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- flags.Visit(collectConflicts)
|
|
|
|
|
|
+ flags.Visit(duplicatedConflicts)
|
|
|
|
|
|
if len(conflicts) > 0 {
|
|
if len(conflicts) > 0 {
|
|
return fmt.Errorf("the following directives are specified both as a flag and in the configuration file: %s", strings.Join(conflicts, ", "))
|
|
return fmt.Errorf("the following directives are specified both as a flag and in the configuration file: %s", strings.Join(conflicts, ", "))
|