github.com/wozhu6104/docker@v20.10.10+incompatible/daemon/reload_test.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "os" 5 "reflect" 6 "sort" 7 "testing" 8 "time" 9 10 "github.com/docker/docker/daemon/config" 11 "github.com/docker/docker/daemon/images" 12 "github.com/docker/docker/pkg/discovery" 13 _ "github.com/docker/docker/pkg/discovery/memory" 14 "github.com/docker/docker/registry" 15 "github.com/docker/libnetwork" 16 "github.com/sirupsen/logrus" 17 "gotest.tools/v3/assert" 18 is "gotest.tools/v3/assert/cmp" 19 ) 20 21 // muteLogs suppresses logs that are generated during the test 22 func muteLogs() { 23 logrus.SetLevel(logrus.ErrorLevel) 24 } 25 26 func TestDaemonReloadLabels(t *testing.T) { 27 daemon := &Daemon{ 28 configStore: &config.Config{ 29 CommonConfig: config.CommonConfig{ 30 Labels: []string{"foo:bar"}, 31 }, 32 }, 33 imageService: images.NewImageService(images.ImageServiceConfig{}), 34 } 35 muteLogs() 36 37 valuesSets := make(map[string]interface{}) 38 valuesSets["labels"] = "foo:baz" 39 newConfig := &config.Config{ 40 CommonConfig: config.CommonConfig{ 41 Labels: []string{"foo:baz"}, 42 ValuesSet: valuesSets, 43 }, 44 } 45 46 if err := daemon.Reload(newConfig); err != nil { 47 t.Fatal(err) 48 } 49 50 label := daemon.configStore.Labels[0] 51 if label != "foo:baz" { 52 t.Fatalf("Expected daemon label `foo:baz`, got %s", label) 53 } 54 } 55 56 func TestDaemonReloadAllowNondistributableArtifacts(t *testing.T) { 57 daemon := &Daemon{ 58 configStore: &config.Config{}, 59 imageService: images.NewImageService(images.ImageServiceConfig{}), 60 } 61 muteLogs() 62 63 var err error 64 // Initialize daemon with some registries. 65 daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{ 66 AllowNondistributableArtifacts: []string{ 67 "127.0.0.0/8", 68 "10.10.1.11:5000", 69 "10.10.1.22:5000", // This will be removed during reload. 70 "docker1.com", 71 "docker2.com", // This will be removed during reload. 72 }, 73 }) 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 registries := []string{ 79 "127.0.0.0/8", 80 "10.10.1.11:5000", 81 "10.10.1.33:5000", // This will be added during reload. 82 "docker1.com", 83 "docker3.com", // This will be added during reload. 84 } 85 86 newConfig := &config.Config{ 87 CommonConfig: config.CommonConfig{ 88 ServiceOptions: registry.ServiceOptions{ 89 AllowNondistributableArtifacts: registries, 90 }, 91 ValuesSet: map[string]interface{}{ 92 "allow-nondistributable-artifacts": registries, 93 }, 94 }, 95 } 96 97 if err := daemon.Reload(newConfig); err != nil { 98 t.Fatal(err) 99 } 100 101 var actual []string 102 serviceConfig := daemon.RegistryService.ServiceConfig() 103 for _, value := range serviceConfig.AllowNondistributableArtifactsCIDRs { 104 actual = append(actual, value.String()) 105 } 106 actual = append(actual, serviceConfig.AllowNondistributableArtifactsHostnames...) 107 108 sort.Strings(registries) 109 sort.Strings(actual) 110 assert.Check(t, is.DeepEqual(registries, actual)) 111 } 112 113 func TestDaemonReloadMirrors(t *testing.T) { 114 daemon := &Daemon{ 115 imageService: images.NewImageService(images.ImageServiceConfig{}), 116 } 117 muteLogs() 118 119 var err error 120 daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{ 121 InsecureRegistries: []string{}, 122 Mirrors: []string{ 123 "https://mirror.test1.com", 124 "https://mirror.test2.com", // this will be removed when reloading 125 "https://mirror.test3.com", // this will be removed when reloading 126 }, 127 }) 128 if err != nil { 129 t.Fatal(err) 130 } 131 132 daemon.configStore = &config.Config{} 133 134 type pair struct { 135 valid bool 136 mirrors []string 137 after []string 138 } 139 140 loadMirrors := []pair{ 141 { 142 valid: false, 143 mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid 144 after: []string{}, 145 }, 146 { 147 valid: false, 148 mirrors: []string{"mirror.test1.com"}, // this mirror is invalid 149 after: []string{}, 150 }, 151 { 152 valid: false, 153 mirrors: []string{"10.10.1.11:5000", "mirror.test1.com"}, // mirrors are invalid 154 after: []string{}, 155 }, 156 { 157 valid: true, 158 mirrors: []string{"https://mirror.test1.com", "https://mirror.test4.com"}, 159 after: []string{"https://mirror.test1.com/", "https://mirror.test4.com/"}, 160 }, 161 } 162 163 for _, value := range loadMirrors { 164 valuesSets := make(map[string]interface{}) 165 valuesSets["registry-mirrors"] = value.mirrors 166 167 newConfig := &config.Config{ 168 CommonConfig: config.CommonConfig{ 169 ServiceOptions: registry.ServiceOptions{ 170 Mirrors: value.mirrors, 171 }, 172 ValuesSet: valuesSets, 173 }, 174 } 175 176 err := daemon.Reload(newConfig) 177 if !value.valid && err == nil { 178 // mirrors should be invalid, should be a non-nil error 179 t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors) 180 } 181 182 if value.valid { 183 if err != nil { 184 // mirrors should be valid, should be no error 185 t.Fatal(err) 186 } 187 registryService := daemon.RegistryService.ServiceConfig() 188 189 if len(registryService.Mirrors) != len(value.after) { 190 t.Fatalf("Expected %d daemon mirrors %s while get %d with %s", 191 len(value.after), 192 value.after, 193 len(registryService.Mirrors), 194 registryService.Mirrors) 195 } 196 197 dataMap := map[string]struct{}{} 198 199 for _, mirror := range registryService.Mirrors { 200 if _, exist := dataMap[mirror]; !exist { 201 dataMap[mirror] = struct{}{} 202 } 203 } 204 205 for _, address := range value.after { 206 if _, exist := dataMap[address]; !exist { 207 t.Fatalf("Expected %s in daemon mirrors, while get none", address) 208 } 209 } 210 } 211 } 212 } 213 214 func TestDaemonReloadInsecureRegistries(t *testing.T) { 215 daemon := &Daemon{ 216 imageService: images.NewImageService(images.ImageServiceConfig{}), 217 } 218 muteLogs() 219 220 var err error 221 // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000" 222 daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{ 223 InsecureRegistries: []string{ 224 "127.0.0.0/8", 225 "10.10.1.11:5000", 226 "10.10.1.22:5000", // this will be removed when reloading 227 "docker1.com", 228 "docker2.com", // this will be removed when reloading 229 }, 230 }) 231 if err != nil { 232 t.Fatal(err) 233 } 234 235 daemon.configStore = &config.Config{} 236 237 insecureRegistries := []string{ 238 "127.0.0.0/8", // this will be kept 239 "10.10.1.11:5000", // this will be kept 240 "10.10.1.33:5000", // this will be newly added 241 "docker1.com", // this will be kept 242 "docker3.com", // this will be newly added 243 } 244 245 valuesSets := make(map[string]interface{}) 246 valuesSets["insecure-registries"] = insecureRegistries 247 248 newConfig := &config.Config{ 249 CommonConfig: config.CommonConfig{ 250 ServiceOptions: registry.ServiceOptions{ 251 InsecureRegistries: insecureRegistries, 252 }, 253 ValuesSet: valuesSets, 254 }, 255 } 256 257 if err := daemon.Reload(newConfig); err != nil { 258 t.Fatal(err) 259 } 260 261 // After Reload, daemon.RegistryService will be changed which is useful 262 // for registry communication in daemon. 263 registries := daemon.RegistryService.ServiceConfig() 264 265 // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon. 266 // Then collect registries.InsecureRegistryCIDRs in dataMap. 267 // When collecting, we need to convert CIDRS into string as a key, 268 // while the times of key appears as value. 269 dataMap := map[string]int{} 270 for _, value := range registries.InsecureRegistryCIDRs { 271 if _, ok := dataMap[value.String()]; !ok { 272 dataMap[value.String()] = 1 273 } else { 274 dataMap[value.String()]++ 275 } 276 } 277 278 for _, value := range registries.IndexConfigs { 279 if _, ok := dataMap[value.Name]; !ok { 280 dataMap[value.Name] = 1 281 } else { 282 dataMap[value.Name]++ 283 } 284 } 285 286 // Finally compare dataMap with the original insecureRegistries. 287 // Each value in insecureRegistries should appear in daemon's insecure registries, 288 // and each can only appear exactly ONCE. 289 for _, r := range insecureRegistries { 290 if value, ok := dataMap[r]; !ok { 291 t.Fatalf("Expected daemon insecure registry %s, got none", r) 292 } else if value != 1 { 293 t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value) 294 } 295 } 296 297 // assert if "10.10.1.22:5000" is removed when reloading 298 if value, ok := dataMap["10.10.1.22:5000"]; ok { 299 t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value) 300 } 301 302 // assert if "docker2.com" is removed when reloading 303 if value, ok := dataMap["docker2.com"]; ok { 304 t.Fatalf("Expected no insecure registry of docker2.com, got %d", value) 305 } 306 } 307 308 func TestDaemonReloadNotAffectOthers(t *testing.T) { 309 daemon := &Daemon{ 310 imageService: images.NewImageService(images.ImageServiceConfig{}), 311 } 312 muteLogs() 313 314 daemon.configStore = &config.Config{ 315 CommonConfig: config.CommonConfig{ 316 Labels: []string{"foo:bar"}, 317 Debug: true, 318 }, 319 } 320 321 valuesSets := make(map[string]interface{}) 322 valuesSets["labels"] = "foo:baz" 323 newConfig := &config.Config{ 324 CommonConfig: config.CommonConfig{ 325 Labels: []string{"foo:baz"}, 326 ValuesSet: valuesSets, 327 }, 328 } 329 330 if err := daemon.Reload(newConfig); err != nil { 331 t.Fatal(err) 332 } 333 334 label := daemon.configStore.Labels[0] 335 if label != "foo:baz" { 336 t.Fatalf("Expected daemon label `foo:baz`, got %s", label) 337 } 338 debug := daemon.configStore.Debug 339 if !debug { 340 t.Fatal("Expected debug 'enabled', got 'disabled'") 341 } 342 } 343 344 func TestDaemonDiscoveryReload(t *testing.T) { 345 daemon := &Daemon{ 346 imageService: images.NewImageService(images.ImageServiceConfig{}), 347 } 348 muteLogs() 349 daemon.configStore = &config.Config{ 350 CommonConfig: config.CommonConfig{ 351 ClusterStore: "memory://127.0.0.1", 352 ClusterAdvertise: "127.0.0.1:3333", 353 }, 354 } 355 356 if err := daemon.initDiscovery(daemon.configStore); err != nil { 357 t.Fatal(err) 358 } 359 360 expected := discovery.Entries{ 361 &discovery.Entry{Host: "127.0.0.1", Port: "3333"}, 362 } 363 364 select { 365 case <-time.After(10 * time.Second): 366 t.Fatal("timeout waiting for discovery") 367 case <-daemon.discoveryWatcher.ReadyCh(): 368 } 369 370 stopCh := make(chan struct{}) 371 defer close(stopCh) 372 ch, errCh := daemon.discoveryWatcher.Watch(stopCh) 373 374 select { 375 case <-time.After(1 * time.Second): 376 t.Fatal("failed to get discovery advertisements in time") 377 case e := <-ch: 378 if !reflect.DeepEqual(e, expected) { 379 t.Fatalf("expected %v, got %v\n", expected, e) 380 } 381 case e := <-errCh: 382 t.Fatal(e) 383 } 384 385 valuesSets := make(map[string]interface{}) 386 valuesSets["cluster-store"] = "memory://127.0.0.1:2222" 387 valuesSets["cluster-advertise"] = "127.0.0.1:5555" 388 newConfig := &config.Config{ 389 CommonConfig: config.CommonConfig{ 390 ClusterStore: "memory://127.0.0.1:2222", 391 ClusterAdvertise: "127.0.0.1:5555", 392 ValuesSet: valuesSets, 393 }, 394 } 395 396 expected = discovery.Entries{ 397 &discovery.Entry{Host: "127.0.0.1", Port: "5555"}, 398 } 399 400 if err := daemon.Reload(newConfig); err != nil { 401 t.Fatal(err) 402 } 403 404 select { 405 case <-time.After(10 * time.Second): 406 t.Fatal("timeout waiting for discovery") 407 case <-daemon.discoveryWatcher.ReadyCh(): 408 } 409 410 ch, errCh = daemon.discoveryWatcher.Watch(stopCh) 411 412 select { 413 case <-time.After(1 * time.Second): 414 t.Fatal("failed to get discovery advertisements in time") 415 case e := <-ch: 416 if !reflect.DeepEqual(e, expected) { 417 t.Fatalf("expected %v, got %v\n", expected, e) 418 } 419 case e := <-errCh: 420 t.Fatal(e) 421 } 422 } 423 424 func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) { 425 daemon := &Daemon{ 426 imageService: images.NewImageService(images.ImageServiceConfig{}), 427 } 428 daemon.configStore = &config.Config{} 429 muteLogs() 430 431 valuesSet := make(map[string]interface{}) 432 valuesSet["cluster-store"] = "memory://127.0.0.1:2222" 433 valuesSet["cluster-advertise"] = "127.0.0.1:5555" 434 newConfig := &config.Config{ 435 CommonConfig: config.CommonConfig{ 436 ClusterStore: "memory://127.0.0.1:2222", 437 ClusterAdvertise: "127.0.0.1:5555", 438 ValuesSet: valuesSet, 439 }, 440 } 441 442 expected := discovery.Entries{ 443 &discovery.Entry{Host: "127.0.0.1", Port: "5555"}, 444 } 445 446 if err := daemon.Reload(newConfig); err != nil { 447 t.Fatal(err) 448 } 449 450 select { 451 case <-time.After(10 * time.Second): 452 t.Fatal("timeout waiting for discovery") 453 case <-daemon.discoveryWatcher.ReadyCh(): 454 } 455 456 stopCh := make(chan struct{}) 457 defer close(stopCh) 458 ch, errCh := daemon.discoveryWatcher.Watch(stopCh) 459 460 select { 461 case <-time.After(1 * time.Second): 462 t.Fatal("failed to get discovery advertisements in time") 463 case e := <-ch: 464 if !reflect.DeepEqual(e, expected) { 465 t.Fatalf("expected %v, got %v\n", expected, e) 466 } 467 case e := <-errCh: 468 t.Fatal(e) 469 } 470 } 471 472 func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) { 473 daemon := &Daemon{ 474 imageService: images.NewImageService(images.ImageServiceConfig{}), 475 } 476 daemon.configStore = &config.Config{ 477 CommonConfig: config.CommonConfig{ 478 ClusterStore: "memory://127.0.0.1", 479 }, 480 } 481 valuesSets := make(map[string]interface{}) 482 valuesSets["cluster-advertise"] = "127.0.0.1:5555" 483 newConfig := &config.Config{ 484 CommonConfig: config.CommonConfig{ 485 ClusterAdvertise: "127.0.0.1:5555", 486 ValuesSet: valuesSets, 487 }, 488 } 489 expected := discovery.Entries{ 490 &discovery.Entry{Host: "127.0.0.1", Port: "5555"}, 491 } 492 493 if err := daemon.Reload(newConfig); err != nil { 494 t.Fatal(err) 495 } 496 497 select { 498 case <-daemon.discoveryWatcher.ReadyCh(): 499 case <-time.After(10 * time.Second): 500 t.Fatal("Timeout waiting for discovery") 501 } 502 stopCh := make(chan struct{}) 503 defer close(stopCh) 504 ch, errCh := daemon.discoveryWatcher.Watch(stopCh) 505 506 select { 507 case <-time.After(1 * time.Second): 508 t.Fatal("failed to get discovery advertisements in time") 509 case e := <-ch: 510 if !reflect.DeepEqual(e, expected) { 511 t.Fatalf("expected %v, got %v\n", expected, e) 512 } 513 case e := <-errCh: 514 t.Fatal(e) 515 } 516 } 517 518 func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) { 519 if os.Getuid() != 0 { 520 t.Skip("root required") 521 } 522 daemon := &Daemon{ 523 imageService: images.NewImageService(images.ImageServiceConfig{}), 524 } 525 daemon.configStore = &config.Config{} 526 527 valuesSet := make(map[string]interface{}) 528 valuesSet["network-diagnostic-port"] = 2000 529 enableConfig := &config.Config{ 530 CommonConfig: config.CommonConfig{ 531 NetworkDiagnosticPort: 2000, 532 ValuesSet: valuesSet, 533 }, 534 } 535 disableConfig := &config.Config{ 536 CommonConfig: config.CommonConfig{}, 537 } 538 539 netOptions, err := daemon.networkOptions(enableConfig, nil, nil) 540 if err != nil { 541 t.Fatal(err) 542 } 543 controller, err := libnetwork.New(netOptions...) 544 if err != nil { 545 t.Fatal(err) 546 } 547 daemon.netController = controller 548 549 // Enable/Disable the server for some iterations 550 for i := 0; i < 10; i++ { 551 enableConfig.CommonConfig.NetworkDiagnosticPort++ 552 if err := daemon.Reload(enableConfig); err != nil { 553 t.Fatal(err) 554 } 555 // Check that the diagnostic is enabled 556 if !daemon.netController.IsDiagnosticEnabled() { 557 t.Fatalf("diagnostic should be enable") 558 } 559 560 // Reload 561 if err := daemon.Reload(disableConfig); err != nil { 562 t.Fatal(err) 563 } 564 // Check that the diagnostic is disabled 565 if daemon.netController.IsDiagnosticEnabled() { 566 t.Fatalf("diagnostic should be disable") 567 } 568 } 569 570 enableConfig.CommonConfig.NetworkDiagnosticPort++ 571 // 2 times the enable should not create problems 572 if err := daemon.Reload(enableConfig); err != nil { 573 t.Fatal(err) 574 } 575 // Check that the diagnostic is enabled 576 if !daemon.netController.IsDiagnosticEnabled() { 577 t.Fatalf("diagnostic should be enable") 578 } 579 580 // Check that another reload does not cause issues 581 if err := daemon.Reload(enableConfig); err != nil { 582 t.Fatal(err) 583 } 584 // Check that the diagnostic is enable 585 if !daemon.netController.IsDiagnosticEnabled() { 586 t.Fatalf("diagnostic should be enable") 587 } 588 589 }