Browse code

Fix post config verification without flags.

- 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>

David Calavera authored on 2016/01/20 04:16:07
Showing 4 changed files
... ...
@@ -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
+}