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