github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/daemon/config/config_test.go (about) 1 package config // import "github.com/docker/docker/daemon/config" 2 3 import ( 4 "io/ioutil" 5 "os" 6 "strings" 7 "testing" 8 9 "github.com/docker/docker/daemon/discovery" 10 "github.com/docker/docker/internal/testutil" 11 "github.com/docker/docker/opts" 12 "github.com/gotestyourself/gotestyourself/assert" 13 is "github.com/gotestyourself/gotestyourself/assert/cmp" 14 "github.com/gotestyourself/gotestyourself/fs" 15 "github.com/spf13/pflag" 16 ) 17 18 func TestDaemonConfigurationNotFound(t *testing.T) { 19 _, err := MergeDaemonConfigurations(&Config{}, nil, "/tmp/foo-bar-baz-docker") 20 if err == nil || !os.IsNotExist(err) { 21 t.Fatalf("expected does not exist error, got %v", err) 22 } 23 } 24 25 func TestDaemonBrokenConfiguration(t *testing.T) { 26 f, err := ioutil.TempFile("", "docker-config-") 27 if err != nil { 28 t.Fatal(err) 29 } 30 31 configFile := f.Name() 32 f.Write([]byte(`{"Debug": tru`)) 33 f.Close() 34 35 _, err = MergeDaemonConfigurations(&Config{}, nil, configFile) 36 if err == nil { 37 t.Fatalf("expected error, got %v", err) 38 } 39 } 40 41 func TestParseClusterAdvertiseSettings(t *testing.T) { 42 _, err := ParseClusterAdvertiseSettings("something", "") 43 if err != discovery.ErrDiscoveryDisabled { 44 t.Fatalf("expected discovery disabled error, got %v\n", err) 45 } 46 47 _, err = ParseClusterAdvertiseSettings("", "something") 48 if err == nil { 49 t.Fatalf("expected discovery store error, got %v\n", err) 50 } 51 52 _, err = ParseClusterAdvertiseSettings("etcd", "127.0.0.1:8080") 53 if err != nil { 54 t.Fatal(err) 55 } 56 } 57 58 func TestFindConfigurationConflicts(t *testing.T) { 59 config := map[string]interface{}{"authorization-plugins": "foobar"} 60 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 61 62 flags.String("authorization-plugins", "", "") 63 assert.Check(t, flags.Set("authorization-plugins", "asdf")) 64 65 testutil.ErrorContains(t, 66 findConfigurationConflicts(config, flags), 67 "authorization-plugins: (from flag: asdf, from file: foobar)") 68 } 69 70 func TestFindConfigurationConflictsWithNamedOptions(t *testing.T) { 71 config := map[string]interface{}{"hosts": []string{"qwer"}} 72 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 73 74 var hosts []string 75 flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, opts.ValidateHost), "host", "H", "Daemon socket(s) to connect to") 76 assert.Check(t, flags.Set("host", "tcp://127.0.0.1:4444")) 77 assert.Check(t, flags.Set("host", "unix:///var/run/docker.sock")) 78 79 testutil.ErrorContains(t, findConfigurationConflicts(config, flags), "hosts") 80 } 81 82 func TestDaemonConfigurationMergeConflicts(t *testing.T) { 83 f, err := ioutil.TempFile("", "docker-config-") 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 configFile := f.Name() 89 f.Write([]byte(`{"debug": true}`)) 90 f.Close() 91 92 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 93 flags.Bool("debug", false, "") 94 flags.Set("debug", "false") 95 96 _, err = MergeDaemonConfigurations(&Config{}, flags, configFile) 97 if err == nil { 98 t.Fatal("expected error, got nil") 99 } 100 if !strings.Contains(err.Error(), "debug") { 101 t.Fatalf("expected debug conflict, got %v", err) 102 } 103 } 104 105 func TestDaemonConfigurationMergeConcurrent(t *testing.T) { 106 f, err := ioutil.TempFile("", "docker-config-") 107 if err != nil { 108 t.Fatal(err) 109 } 110 111 configFile := f.Name() 112 f.Write([]byte(`{"max-concurrent-downloads": 1}`)) 113 f.Close() 114 115 _, err = MergeDaemonConfigurations(&Config{}, nil, configFile) 116 if err != nil { 117 t.Fatal("expected error, got nil") 118 } 119 } 120 121 func TestDaemonConfigurationMergeConcurrentError(t *testing.T) { 122 f, err := ioutil.TempFile("", "docker-config-") 123 if err != nil { 124 t.Fatal(err) 125 } 126 127 configFile := f.Name() 128 f.Write([]byte(`{"max-concurrent-downloads": -1}`)) 129 f.Close() 130 131 _, err = MergeDaemonConfigurations(&Config{}, nil, configFile) 132 if err == nil { 133 t.Fatalf("expected no error, got error %v", err) 134 } 135 } 136 137 func TestDaemonConfigurationMergeConflictsWithInnerStructs(t *testing.T) { 138 f, err := ioutil.TempFile("", "docker-config-") 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 configFile := f.Name() 144 f.Write([]byte(`{"tlscacert": "/etc/certificates/ca.pem"}`)) 145 f.Close() 146 147 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 148 flags.String("tlscacert", "", "") 149 flags.Set("tlscacert", "~/.docker/ca.pem") 150 151 _, err = MergeDaemonConfigurations(&Config{}, flags, configFile) 152 if err == nil { 153 t.Fatal("expected error, got nil") 154 } 155 if !strings.Contains(err.Error(), "tlscacert") { 156 t.Fatalf("expected tlscacert conflict, got %v", err) 157 } 158 } 159 160 func TestFindConfigurationConflictsWithUnknownKeys(t *testing.T) { 161 config := map[string]interface{}{"tls-verify": "true"} 162 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 163 164 flags.Bool("tlsverify", false, "") 165 err := findConfigurationConflicts(config, flags) 166 if err == nil { 167 t.Fatal("expected error, got nil") 168 } 169 if !strings.Contains(err.Error(), "the following directives don't match any configuration option: tls-verify") { 170 t.Fatalf("expected tls-verify conflict, got %v", err) 171 } 172 } 173 174 func TestFindConfigurationConflictsWithMergedValues(t *testing.T) { 175 var hosts []string 176 config := map[string]interface{}{"hosts": "tcp://127.0.0.1:2345"} 177 flags := pflag.NewFlagSet("base", pflag.ContinueOnError) 178 flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, nil), "host", "H", "") 179 180 err := findConfigurationConflicts(config, flags) 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 flags.Set("host", "unix:///var/run/docker.sock") 186 err = findConfigurationConflicts(config, flags) 187 if err == nil { 188 t.Fatal("expected error, got nil") 189 } 190 if !strings.Contains(err.Error(), "hosts: (from flag: [unix:///var/run/docker.sock], from file: tcp://127.0.0.1:2345)") { 191 t.Fatalf("expected hosts conflict, got %v", err) 192 } 193 } 194 195 func TestValidateConfigurationErrors(t *testing.T) { 196 minusNumber := -10 197 testCases := []struct { 198 config *Config 199 }{ 200 { 201 config: &Config{ 202 CommonConfig: CommonConfig{ 203 Labels: []string{"one"}, 204 }, 205 }, 206 }, 207 { 208 config: &Config{ 209 CommonConfig: CommonConfig{ 210 Labels: []string{"foo=bar", "one"}, 211 }, 212 }, 213 }, 214 { 215 config: &Config{ 216 CommonConfig: CommonConfig{ 217 DNS: []string{"1.1.1.1o"}, 218 }, 219 }, 220 }, 221 { 222 config: &Config{ 223 CommonConfig: CommonConfig{ 224 DNS: []string{"2.2.2.2", "1.1.1.1o"}, 225 }, 226 }, 227 }, 228 { 229 config: &Config{ 230 CommonConfig: CommonConfig{ 231 DNSSearch: []string{"123456"}, 232 }, 233 }, 234 }, 235 { 236 config: &Config{ 237 CommonConfig: CommonConfig{ 238 DNSSearch: []string{"a.b.c", "123456"}, 239 }, 240 }, 241 }, 242 { 243 config: &Config{ 244 CommonConfig: CommonConfig{ 245 MaxConcurrentDownloads: &minusNumber, 246 // This is weird... 247 ValuesSet: map[string]interface{}{ 248 "max-concurrent-downloads": -1, 249 }, 250 }, 251 }, 252 }, 253 { 254 config: &Config{ 255 CommonConfig: CommonConfig{ 256 MaxConcurrentUploads: &minusNumber, 257 // This is weird... 258 ValuesSet: map[string]interface{}{ 259 "max-concurrent-uploads": -1, 260 }, 261 }, 262 }, 263 }, 264 { 265 config: &Config{ 266 CommonConfig: CommonConfig{ 267 NodeGenericResources: []string{"foo"}, 268 }, 269 }, 270 }, 271 { 272 config: &Config{ 273 CommonConfig: CommonConfig{ 274 NodeGenericResources: []string{"foo=bar", "foo=1"}, 275 }, 276 }, 277 }, 278 } 279 for _, tc := range testCases { 280 err := Validate(tc.config) 281 if err == nil { 282 t.Fatalf("expected error, got nil for config %v", tc.config) 283 } 284 } 285 } 286 287 func TestValidateConfiguration(t *testing.T) { 288 minusNumber := 4 289 testCases := []struct { 290 config *Config 291 }{ 292 { 293 config: &Config{ 294 CommonConfig: CommonConfig{ 295 Labels: []string{"one=two"}, 296 }, 297 }, 298 }, 299 { 300 config: &Config{ 301 CommonConfig: CommonConfig{ 302 DNS: []string{"1.1.1.1"}, 303 }, 304 }, 305 }, 306 { 307 config: &Config{ 308 CommonConfig: CommonConfig{ 309 DNSSearch: []string{"a.b.c"}, 310 }, 311 }, 312 }, 313 { 314 config: &Config{ 315 CommonConfig: CommonConfig{ 316 MaxConcurrentDownloads: &minusNumber, 317 // This is weird... 318 ValuesSet: map[string]interface{}{ 319 "max-concurrent-downloads": -1, 320 }, 321 }, 322 }, 323 }, 324 { 325 config: &Config{ 326 CommonConfig: CommonConfig{ 327 MaxConcurrentUploads: &minusNumber, 328 // This is weird... 329 ValuesSet: map[string]interface{}{ 330 "max-concurrent-uploads": -1, 331 }, 332 }, 333 }, 334 }, 335 { 336 config: &Config{ 337 CommonConfig: CommonConfig{ 338 NodeGenericResources: []string{"foo=bar", "foo=baz"}, 339 }, 340 }, 341 }, 342 { 343 config: &Config{ 344 CommonConfig: CommonConfig{ 345 NodeGenericResources: []string{"foo=1"}, 346 }, 347 }, 348 }, 349 } 350 for _, tc := range testCases { 351 err := Validate(tc.config) 352 if err != nil { 353 t.Fatalf("expected no error, got error %v", err) 354 } 355 } 356 } 357 358 func TestModifiedDiscoverySettings(t *testing.T) { 359 cases := []struct { 360 current *Config 361 modified *Config 362 expected bool 363 }{ 364 { 365 current: discoveryConfig("foo", "bar", map[string]string{}), 366 modified: discoveryConfig("foo", "bar", map[string]string{}), 367 expected: false, 368 }, 369 { 370 current: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}), 371 modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}), 372 expected: false, 373 }, 374 { 375 current: discoveryConfig("foo", "bar", map[string]string{}), 376 modified: discoveryConfig("foo", "bar", nil), 377 expected: false, 378 }, 379 { 380 current: discoveryConfig("foo", "bar", nil), 381 modified: discoveryConfig("foo", "bar", map[string]string{}), 382 expected: false, 383 }, 384 { 385 current: discoveryConfig("foo", "bar", nil), 386 modified: discoveryConfig("baz", "bar", nil), 387 expected: true, 388 }, 389 { 390 current: discoveryConfig("foo", "bar", nil), 391 modified: discoveryConfig("foo", "baz", nil), 392 expected: true, 393 }, 394 { 395 current: discoveryConfig("foo", "bar", nil), 396 modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}), 397 expected: true, 398 }, 399 } 400 401 for _, c := range cases { 402 got := ModifiedDiscoverySettings(c.current, c.modified.ClusterStore, c.modified.ClusterAdvertise, c.modified.ClusterOpts) 403 if c.expected != got { 404 t.Fatalf("expected %v, got %v: current config %v, new config %v", c.expected, got, c.current, c.modified) 405 } 406 } 407 } 408 409 func discoveryConfig(backendAddr, advertiseAddr string, opts map[string]string) *Config { 410 return &Config{ 411 CommonConfig: CommonConfig{ 412 ClusterStore: backendAddr, 413 ClusterAdvertise: advertiseAddr, 414 ClusterOpts: opts, 415 }, 416 } 417 } 418 419 // TestReloadSetConfigFileNotExist tests that when `--config-file` is set 420 // and it doesn't exist the `Reload` function returns an error. 421 func TestReloadSetConfigFileNotExist(t *testing.T) { 422 configFile := "/tmp/blabla/not/exists/config.json" 423 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 424 flags.String("config-file", "", "") 425 flags.Set("config-file", configFile) 426 427 err := Reload(configFile, flags, func(c *Config) {}) 428 assert.Check(t, is.ErrorContains(err, "")) 429 testutil.ErrorContains(t, err, "unable to configure the Docker daemon with file") 430 } 431 432 // TestReloadDefaultConfigNotExist tests that if the default configuration file 433 // doesn't exist the daemon still will be reloaded. 434 func TestReloadDefaultConfigNotExist(t *testing.T) { 435 reloaded := false 436 configFile := "/etc/docker/daemon.json" 437 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 438 flags.String("config-file", configFile, "") 439 err := Reload(configFile, flags, func(c *Config) { 440 reloaded = true 441 }) 442 assert.Check(t, err) 443 assert.Check(t, reloaded) 444 } 445 446 // TestReloadBadDefaultConfig tests that when `--config-file` is not set 447 // and the default configuration file exists and is bad return an error 448 func TestReloadBadDefaultConfig(t *testing.T) { 449 f, err := ioutil.TempFile("", "docker-config-") 450 if err != nil { 451 t.Fatal(err) 452 } 453 454 configFile := f.Name() 455 f.Write([]byte(`{wrong: "configuration"}`)) 456 f.Close() 457 458 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 459 flags.String("config-file", configFile, "") 460 err = Reload(configFile, flags, func(c *Config) {}) 461 assert.Check(t, is.ErrorContains(err, "")) 462 testutil.ErrorContains(t, err, "unable to configure the Docker daemon with file") 463 } 464 465 func TestReloadWithConflictingLabels(t *testing.T) { 466 tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=bar","foo=baz"]}`)) 467 defer tempFile.Remove() 468 configFile := tempFile.Path() 469 470 var lbls []string 471 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 472 flags.String("config-file", configFile, "") 473 flags.StringSlice("labels", lbls, "") 474 err := Reload(configFile, flags, func(c *Config) {}) 475 testutil.ErrorContains(t, err, "conflict labels for foo=baz and foo=bar") 476 } 477 478 func TestReloadWithDuplicateLabels(t *testing.T) { 479 tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=the-same","foo=the-same"]}`)) 480 defer tempFile.Remove() 481 configFile := tempFile.Path() 482 483 var lbls []string 484 flags := pflag.NewFlagSet("test", pflag.ContinueOnError) 485 flags.String("config-file", configFile, "") 486 flags.StringSlice("labels", lbls, "") 487 err := Reload(configFile, flags, func(c *Config) {}) 488 assert.Check(t, err) 489 }