- Set the daemon log level to what's set in the configuration.
- Enable TLS when TLSVerify is enabled.
Signed-off-by: David Calavera <david.calavera@gmail.com>
... | ... |
@@ -84,6 +84,7 @@ type CommonConfig struct { |
84 | 84 |
TLSOptions CommonTLSOptions `json:"tls-opts,omitempty"` |
85 | 85 |
|
86 | 86 |
reloadLock sync.Mutex |
87 |
+ valuesSet map[string]interface{} |
|
87 | 88 |
} |
88 | 89 |
|
89 | 90 |
// InstallCommonFlags adds command-line options to the top-level flag parser for |
... | ... |
@@ -112,6 +113,16 @@ func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string) |
112 | 112 |
cmd.Var(opts.NewNamedMapOpts("cluster-store-opts", config.ClusterOpts, nil), []string{"-cluster-store-opt"}, usageFn("Set cluster store options")) |
113 | 113 |
} |
114 | 114 |
|
115 |
+// IsValueSet returns true if a configuration value |
|
116 |
+// was explicitly set in the configuration file. |
|
117 |
+func (config *Config) IsValueSet(name string) bool { |
|
118 |
+ if config.valuesSet == nil { |
|
119 |
+ return false |
|
120 |
+ } |
|
121 |
+ _, ok := config.valuesSet[name] |
|
122 |
+ return ok |
|
123 |
+} |
|
124 |
+ |
|
115 | 125 |
func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) { |
116 | 126 |
if clusterAdvertise == "" { |
117 | 127 |
return "", errDiscoveryDisabled |
... | ... |
@@ -165,6 +176,7 @@ func getConflictFreeConfiguration(configFile string, flags *flag.FlagSet) (*Conf |
165 | 165 |
return nil, err |
166 | 166 |
} |
167 | 167 |
|
168 |
+ var config Config |
|
168 | 169 |
var reader io.Reader |
169 | 170 |
if flags != nil { |
170 | 171 |
var jsonConfig map[string]interface{} |
... | ... |
@@ -173,22 +185,22 @@ func getConflictFreeConfiguration(configFile string, flags *flag.FlagSet) (*Conf |
173 | 173 |
return nil, err |
174 | 174 |
} |
175 | 175 |
|
176 |
- if err := findConfigurationConflicts(jsonConfig, flags); err != nil { |
|
176 |
+ configSet := configValuesSet(jsonConfig) |
|
177 |
+ |
|
178 |
+ if err := findConfigurationConflicts(configSet, flags); err != nil { |
|
177 | 179 |
return nil, err |
178 | 180 |
} |
181 |
+ |
|
182 |
+ config.valuesSet = configSet |
|
179 | 183 |
} |
180 | 184 |
|
181 |
- var config Config |
|
182 | 185 |
reader = bytes.NewReader(b) |
183 | 186 |
err = json.NewDecoder(reader).Decode(&config) |
184 | 187 |
return &config, err |
185 | 188 |
} |
186 | 189 |
|
187 |
-// findConfigurationConflicts iterates over the provided flags searching for |
|
188 |
-// duplicated configurations. It returns an error with all the conflicts if |
|
189 |
-// it finds any. |
|
190 |
-func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagSet) error { |
|
191 |
- var conflicts []string |
|
190 |
+// configValuesSet returns the configuration values explicitly set in the file. |
|
191 |
+func configValuesSet(config map[string]interface{}) map[string]interface{} { |
|
192 | 192 |
flatten := make(map[string]interface{}) |
193 | 193 |
for k, v := range config { |
194 | 194 |
if m, ok := v.(map[string]interface{}); ok { |
... | ... |
@@ -199,6 +211,14 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS |
199 | 199 |
flatten[k] = v |
200 | 200 |
} |
201 | 201 |
} |
202 |
+ return flatten |
|
203 |
+} |
|
204 |
+ |
|
205 |
+// findConfigurationConflicts iterates over the provided flags searching for |
|
206 |
+// duplicated configurations. It returns an error with all the conflicts if |
|
207 |
+// it finds any. |
|
208 |
+func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagSet) error { |
|
209 |
+ var conflicts []string |
|
202 | 210 |
|
203 | 211 |
printConflict := func(name string, flagValue, fileValue interface{}) string { |
204 | 212 |
return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue) |
... | ... |
@@ -207,7 +227,7 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS |
207 | 207 |
collectConflicts := func(f *flag.Flag) { |
208 | 208 |
// search option name in the json configuration payload if the value is a named option |
209 | 209 |
if namedOption, ok := f.Value.(opts.NamedOption); ok { |
210 |
- if optsValue, ok := flatten[namedOption.Name()]; ok { |
|
210 |
+ if optsValue, ok := config[namedOption.Name()]; ok { |
|
211 | 211 |
conflicts = append(conflicts, printConflict(namedOption.Name(), f.Value.String(), optsValue)) |
212 | 212 |
} |
213 | 213 |
} else { |
... | ... |
@@ -215,7 +235,7 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS |
215 | 215 |
for _, name := range f.Names { |
216 | 216 |
name = strings.TrimLeft(name, "-") |
217 | 217 |
|
218 |
- if value, ok := flatten[name]; ok { |
|
218 |
+ if value, ok := config[name]; ok { |
|
219 | 219 |
conflicts = append(conflicts, printConflict(name, f.Value.String(), value)) |
220 | 220 |
break |
221 | 221 |
} |
... | ... |
@@ -55,16 +55,7 @@ func init() { |
55 | 55 |
func postParseCommon() { |
56 | 56 |
cmd := commonFlags.FlagSet |
57 | 57 |
|
58 |
- if commonFlags.LogLevel != "" { |
|
59 |
- lvl, err := logrus.ParseLevel(commonFlags.LogLevel) |
|
60 |
- if err != nil { |
|
61 |
- fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", commonFlags.LogLevel) |
|
62 |
- os.Exit(1) |
|
63 |
- } |
|
64 |
- logrus.SetLevel(lvl) |
|
65 |
- } else { |
|
66 |
- logrus.SetLevel(logrus.InfoLevel) |
|
67 |
- } |
|
58 |
+ setDaemonLogLevel(commonFlags.LogLevel) |
|
68 | 59 |
|
69 | 60 |
// Regardless of whether the user sets it to true or false, if they |
70 | 61 |
// specify --tlsverify at all then we need to turn on tls |
... | ... |
@@ -93,3 +84,16 @@ func postParseCommon() { |
93 | 93 |
} |
94 | 94 |
} |
95 | 95 |
} |
96 |
+ |
|
97 |
+func setDaemonLogLevel(logLevel string) { |
|
98 |
+ if logLevel != "" { |
|
99 |
+ lvl, err := logrus.ParseLevel(logLevel) |
|
100 |
+ if err != nil { |
|
101 |
+ fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", logLevel) |
|
102 |
+ os.Exit(1) |
|
103 |
+ } |
|
104 |
+ logrus.SetLevel(lvl) |
|
105 |
+ } else { |
|
106 |
+ logrus.SetLevel(logrus.InfoLevel) |
|
107 |
+ } |
|
108 |
+} |
... | ... |
@@ -360,5 +360,14 @@ func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commo |
360 | 360 |
} |
361 | 361 |
} |
362 | 362 |
|
363 |
+ // Regardless of whether the user sets it to true or false, if they |
|
364 |
+ // specify TLSVerify at all then we need to turn on TLS |
|
365 |
+ if config.IsValueSet("tls-verify") { |
|
366 |
+ config.TLS = true |
|
367 |
+ } |
|
368 |
+ |
|
369 |
+ // ensure that the log level is the one set after merging configurations |
|
370 |
+ setDaemonLogLevel(config.LogLevel) |
|
371 |
+ |
|
363 | 372 |
return config, nil |
364 | 373 |
} |
... | ... |
@@ -7,6 +7,7 @@ import ( |
7 | 7 |
"strings" |
8 | 8 |
"testing" |
9 | 9 |
|
10 |
+ "github.com/Sirupsen/logrus" |
|
10 | 11 |
"github.com/docker/docker/cli" |
11 | 12 |
"github.com/docker/docker/daemon" |
12 | 13 |
"github.com/docker/docker/opts" |
... | ... |
@@ -89,3 +90,126 @@ func TestLoadDaemonCliConfigWithConflicts(t *testing.T) { |
89 | 89 |
t.Fatalf("expected labels conflict, got %v", err) |
90 | 90 |
} |
91 | 91 |
} |
92 |
+ |
|
93 |
+func TestLoadDaemonCliConfigWithTLSVerify(t *testing.T) { |
|
94 |
+ c := &daemon.Config{} |
|
95 |
+ common := &cli.CommonFlags{ |
|
96 |
+ TLSOptions: &tlsconfig.Options{ |
|
97 |
+ CAFile: "/tmp/ca.pem", |
|
98 |
+ }, |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ f, err := ioutil.TempFile("", "docker-config-") |
|
102 |
+ if err != nil { |
|
103 |
+ t.Fatal(err) |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ configFile := f.Name() |
|
107 |
+ f.Write([]byte(`{"tls-verify": true}`)) |
|
108 |
+ f.Close() |
|
109 |
+ |
|
110 |
+ flags := mflag.NewFlagSet("test", mflag.ContinueOnError) |
|
111 |
+ loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) |
|
112 |
+ if err != nil { |
|
113 |
+ t.Fatal(err) |
|
114 |
+ } |
|
115 |
+ if loadedConfig == nil { |
|
116 |
+ t.Fatalf("expected configuration %v, got nil", c) |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ if !loadedConfig.TLS { |
|
120 |
+ t.Fatalf("expected TLS enabled, got %q", loadedConfig) |
|
121 |
+ } |
|
122 |
+} |
|
123 |
+ |
|
124 |
+func TestLoadDaemonCliConfigWithExplicitTLSVerifyFalse(t *testing.T) { |
|
125 |
+ c := &daemon.Config{} |
|
126 |
+ common := &cli.CommonFlags{ |
|
127 |
+ TLSOptions: &tlsconfig.Options{ |
|
128 |
+ CAFile: "/tmp/ca.pem", |
|
129 |
+ }, |
|
130 |
+ } |
|
131 |
+ |
|
132 |
+ f, err := ioutil.TempFile("", "docker-config-") |
|
133 |
+ if err != nil { |
|
134 |
+ t.Fatal(err) |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ configFile := f.Name() |
|
138 |
+ f.Write([]byte(`{"tls-verify": false}`)) |
|
139 |
+ f.Close() |
|
140 |
+ |
|
141 |
+ flags := mflag.NewFlagSet("test", mflag.ContinueOnError) |
|
142 |
+ loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) |
|
143 |
+ if err != nil { |
|
144 |
+ t.Fatal(err) |
|
145 |
+ } |
|
146 |
+ if loadedConfig == nil { |
|
147 |
+ t.Fatalf("expected configuration %v, got nil", c) |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ if !loadedConfig.TLS { |
|
151 |
+ t.Fatalf("expected TLS enabled, got %q", loadedConfig) |
|
152 |
+ } |
|
153 |
+} |
|
154 |
+ |
|
155 |
+func TestLoadDaemonCliConfigWithoutTLSVerify(t *testing.T) { |
|
156 |
+ c := &daemon.Config{} |
|
157 |
+ common := &cli.CommonFlags{ |
|
158 |
+ TLSOptions: &tlsconfig.Options{ |
|
159 |
+ CAFile: "/tmp/ca.pem", |
|
160 |
+ }, |
|
161 |
+ } |
|
162 |
+ |
|
163 |
+ f, err := ioutil.TempFile("", "docker-config-") |
|
164 |
+ if err != nil { |
|
165 |
+ t.Fatal(err) |
|
166 |
+ } |
|
167 |
+ |
|
168 |
+ configFile := f.Name() |
|
169 |
+ f.Write([]byte(`{}`)) |
|
170 |
+ f.Close() |
|
171 |
+ |
|
172 |
+ flags := mflag.NewFlagSet("test", mflag.ContinueOnError) |
|
173 |
+ loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) |
|
174 |
+ if err != nil { |
|
175 |
+ t.Fatal(err) |
|
176 |
+ } |
|
177 |
+ if loadedConfig == nil { |
|
178 |
+ t.Fatalf("expected configuration %v, got nil", c) |
|
179 |
+ } |
|
180 |
+ |
|
181 |
+ if loadedConfig.TLS { |
|
182 |
+ t.Fatalf("expected TLS disabled, got %q", loadedConfig) |
|
183 |
+ } |
|
184 |
+} |
|
185 |
+ |
|
186 |
+func TestLoadDaemonCliConfigWithLogLevel(t *testing.T) { |
|
187 |
+ c := &daemon.Config{} |
|
188 |
+ common := &cli.CommonFlags{} |
|
189 |
+ |
|
190 |
+ f, err := ioutil.TempFile("", "docker-config-") |
|
191 |
+ if err != nil { |
|
192 |
+ t.Fatal(err) |
|
193 |
+ } |
|
194 |
+ |
|
195 |
+ configFile := f.Name() |
|
196 |
+ f.Write([]byte(`{"log-level": "warn"}`)) |
|
197 |
+ f.Close() |
|
198 |
+ |
|
199 |
+ flags := mflag.NewFlagSet("test", mflag.ContinueOnError) |
|
200 |
+ loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) |
|
201 |
+ if err != nil { |
|
202 |
+ t.Fatal(err) |
|
203 |
+ } |
|
204 |
+ if loadedConfig == nil { |
|
205 |
+ t.Fatalf("expected configuration %v, got nil", c) |
|
206 |
+ } |
|
207 |
+ if loadedConfig.LogLevel != "warn" { |
|
208 |
+ t.Fatalf("expected warn log level, got %v", loadedConfig.LogLevel) |
|
209 |
+ } |
|
210 |
+ |
|
211 |
+ if logrus.GetLevel() != logrus.WarnLevel { |
|
212 |
+ t.Fatalf("expected warn log level, got %v", logrus.GetLevel()) |
|
213 |
+ } |
|
214 |
+} |