github.com/rawahars/moby@v24.0.4+incompatible/daemon/reload_test.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "os" 5 "sort" 6 "testing" 7 8 "github.com/docker/docker/daemon/config" 9 "github.com/docker/docker/daemon/images" 10 "github.com/docker/docker/libnetwork" 11 "github.com/docker/docker/registry" 12 "github.com/sirupsen/logrus" 13 "gotest.tools/v3/assert" 14 is "gotest.tools/v3/assert/cmp" 15 ) 16 17 // muteLogs suppresses logs that are generated during the test 18 func muteLogs() { 19 logrus.SetLevel(logrus.ErrorLevel) 20 } 21 22 func TestDaemonReloadLabels(t *testing.T) { 23 daemon := &Daemon{ 24 configStore: &config.Config{ 25 CommonConfig: config.CommonConfig{ 26 Labels: []string{"foo:bar"}, 27 }, 28 }, 29 imageService: images.NewImageService(images.ImageServiceConfig{}), 30 } 31 muteLogs() 32 33 valuesSets := make(map[string]interface{}) 34 valuesSets["labels"] = "foo:baz" 35 newConfig := &config.Config{ 36 CommonConfig: config.CommonConfig{ 37 Labels: []string{"foo:baz"}, 38 ValuesSet: valuesSets, 39 }, 40 } 41 42 if err := daemon.Reload(newConfig); err != nil { 43 t.Fatal(err) 44 } 45 46 label := daemon.configStore.Labels[0] 47 if label != "foo:baz" { 48 t.Fatalf("Expected daemon label `foo:baz`, got %s", label) 49 } 50 } 51 52 func TestDaemonReloadAllowNondistributableArtifacts(t *testing.T) { 53 daemon := &Daemon{ 54 configStore: &config.Config{}, 55 imageService: images.NewImageService(images.ImageServiceConfig{}), 56 } 57 muteLogs() 58 59 var err error 60 // Initialize daemon with some registries. 61 daemon.registryService, err = registry.NewService(registry.ServiceOptions{ 62 AllowNondistributableArtifacts: []string{ 63 "127.0.0.0/8", 64 "10.10.1.11:5000", 65 "10.10.1.22:5000", // This will be removed during reload. 66 "docker1.com", 67 "docker2.com", // This will be removed during reload. 68 }, 69 }) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 registries := []string{ 75 "127.0.0.0/8", 76 "10.10.1.11:5000", 77 "10.10.1.33:5000", // This will be added during reload. 78 "docker1.com", 79 "docker3.com", // This will be added during reload. 80 } 81 82 newConfig := &config.Config{ 83 CommonConfig: config.CommonConfig{ 84 ServiceOptions: registry.ServiceOptions{ 85 AllowNondistributableArtifacts: registries, 86 }, 87 ValuesSet: map[string]interface{}{ 88 "allow-nondistributable-artifacts": registries, 89 }, 90 }, 91 } 92 93 if err := daemon.Reload(newConfig); err != nil { 94 t.Fatal(err) 95 } 96 97 var actual []string 98 serviceConfig := daemon.registryService.ServiceConfig() 99 for _, value := range serviceConfig.AllowNondistributableArtifactsCIDRs { 100 actual = append(actual, value.String()) 101 } 102 actual = append(actual, serviceConfig.AllowNondistributableArtifactsHostnames...) 103 104 sort.Strings(registries) 105 sort.Strings(actual) 106 assert.Check(t, is.DeepEqual(registries, actual)) 107 } 108 109 func TestDaemonReloadMirrors(t *testing.T) { 110 daemon := &Daemon{ 111 imageService: images.NewImageService(images.ImageServiceConfig{}), 112 } 113 muteLogs() 114 115 var err error 116 daemon.registryService, err = registry.NewService(registry.ServiceOptions{ 117 InsecureRegistries: []string{}, 118 Mirrors: []string{ 119 "https://mirror.test1.example.com", 120 "https://mirror.test2.example.com", // this will be removed when reloading 121 "https://mirror.test3.example.com", // this will be removed when reloading 122 }, 123 }) 124 if err != nil { 125 t.Fatal(err) 126 } 127 128 daemon.configStore = &config.Config{} 129 130 type pair struct { 131 valid bool 132 mirrors []string 133 after []string 134 } 135 136 loadMirrors := []pair{ 137 { 138 valid: false, 139 mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid 140 after: []string{}, 141 }, 142 { 143 valid: false, 144 mirrors: []string{"mirror.test1.com"}, // this mirror is invalid 145 after: []string{}, 146 }, 147 { 148 valid: false, 149 mirrors: []string{"10.10.1.11:5000", "mirror.test1.example.com"}, // mirrors are invalid 150 after: []string{}, 151 }, 152 { 153 valid: true, 154 mirrors: []string{"https://mirror.test1.example.com", "https://mirror.test4.example.com"}, 155 after: []string{"https://mirror.test1.example.com/", "https://mirror.test4.example.com/"}, 156 }, 157 } 158 159 for _, value := range loadMirrors { 160 valuesSets := make(map[string]interface{}) 161 valuesSets["registry-mirrors"] = value.mirrors 162 163 newConfig := &config.Config{ 164 CommonConfig: config.CommonConfig{ 165 ServiceOptions: registry.ServiceOptions{ 166 Mirrors: value.mirrors, 167 }, 168 ValuesSet: valuesSets, 169 }, 170 } 171 172 err := daemon.Reload(newConfig) 173 if !value.valid && err == nil { 174 // mirrors should be invalid, should be a non-nil error 175 t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors) 176 } 177 178 if value.valid { 179 if err != nil { 180 // mirrors should be valid, should be no error 181 t.Fatal(err) 182 } 183 registryService := daemon.registryService.ServiceConfig() 184 185 if len(registryService.Mirrors) != len(value.after) { 186 t.Fatalf("Expected %d daemon mirrors %s while get %d with %s", 187 len(value.after), 188 value.after, 189 len(registryService.Mirrors), 190 registryService.Mirrors) 191 } 192 193 dataMap := map[string]struct{}{} 194 195 for _, mirror := range registryService.Mirrors { 196 if _, exist := dataMap[mirror]; !exist { 197 dataMap[mirror] = struct{}{} 198 } 199 } 200 201 for _, address := range value.after { 202 if _, exist := dataMap[address]; !exist { 203 t.Fatalf("Expected %s in daemon mirrors, while get none", address) 204 } 205 } 206 } 207 } 208 } 209 210 func TestDaemonReloadInsecureRegistries(t *testing.T) { 211 daemon := &Daemon{ 212 imageService: images.NewImageService(images.ImageServiceConfig{}), 213 } 214 muteLogs() 215 216 var err error 217 // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000" 218 daemon.registryService, err = registry.NewService(registry.ServiceOptions{ 219 InsecureRegistries: []string{ 220 "127.0.0.0/8", 221 "10.10.1.11:5000", 222 "10.10.1.22:5000", // this will be removed when reloading 223 "docker1.example.com", 224 "docker2.example.com", // this will be removed when reloading 225 }, 226 }) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 daemon.configStore = &config.Config{} 232 233 insecureRegistries := []string{ 234 "127.0.0.0/8", // this will be kept 235 "10.10.1.11:5000", // this will be kept 236 "10.10.1.33:5000", // this will be newly added 237 "docker1.example.com", // this will be kept 238 "docker3.example.com", // this will be newly added 239 } 240 241 mirrors := []string{ 242 "https://mirror.test.example.com", 243 } 244 245 valuesSets := make(map[string]interface{}) 246 valuesSets["insecure-registries"] = insecureRegistries 247 valuesSets["registry-mirrors"] = mirrors 248 249 newConfig := &config.Config{ 250 CommonConfig: config.CommonConfig{ 251 ServiceOptions: registry.ServiceOptions{ 252 InsecureRegistries: insecureRegistries, 253 Mirrors: mirrors, 254 }, 255 ValuesSet: valuesSets, 256 }, 257 } 258 259 if err := daemon.Reload(newConfig); err != nil { 260 t.Fatal(err) 261 } 262 263 // After Reload, daemon.RegistryService will be changed which is useful 264 // for registry communication in daemon. 265 registries := daemon.registryService.ServiceConfig() 266 267 // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon. 268 // Then collect registries.InsecureRegistryCIDRs in dataMap. 269 // When collecting, we need to convert CIDRS into string as a key, 270 // while the times of key appears as value. 271 dataMap := map[string]int{} 272 for _, value := range registries.InsecureRegistryCIDRs { 273 if _, ok := dataMap[value.String()]; !ok { 274 dataMap[value.String()] = 1 275 } else { 276 dataMap[value.String()]++ 277 } 278 } 279 280 for _, value := range registries.IndexConfigs { 281 if _, ok := dataMap[value.Name]; !ok { 282 dataMap[value.Name] = 1 283 } else { 284 dataMap[value.Name]++ 285 } 286 } 287 288 // Finally compare dataMap with the original insecureRegistries. 289 // Each value in insecureRegistries should appear in daemon's insecure registries, 290 // and each can only appear exactly ONCE. 291 for _, r := range insecureRegistries { 292 if value, ok := dataMap[r]; !ok { 293 t.Fatalf("Expected daemon insecure registry %s, got none", r) 294 } else if value != 1 { 295 t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value) 296 } 297 } 298 299 // assert if "10.10.1.22:5000" is removed when reloading 300 if value, ok := dataMap["10.10.1.22:5000"]; ok { 301 t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value) 302 } 303 304 // assert if "docker2.com" is removed when reloading 305 if value, ok := dataMap["docker2.example.com"]; ok { 306 t.Fatalf("Expected no insecure registry of docker2.com, got %d", value) 307 } 308 } 309 310 func TestDaemonReloadNotAffectOthers(t *testing.T) { 311 daemon := &Daemon{ 312 imageService: images.NewImageService(images.ImageServiceConfig{}), 313 } 314 muteLogs() 315 316 daemon.configStore = &config.Config{ 317 CommonConfig: config.CommonConfig{ 318 Labels: []string{"foo:bar"}, 319 Debug: true, 320 }, 321 } 322 323 valuesSets := make(map[string]interface{}) 324 valuesSets["labels"] = "foo:baz" 325 newConfig := &config.Config{ 326 CommonConfig: config.CommonConfig{ 327 Labels: []string{"foo:baz"}, 328 ValuesSet: valuesSets, 329 }, 330 } 331 332 if err := daemon.Reload(newConfig); err != nil { 333 t.Fatal(err) 334 } 335 336 label := daemon.configStore.Labels[0] 337 if label != "foo:baz" { 338 t.Fatalf("Expected daemon label `foo:baz`, got %s", label) 339 } 340 debug := daemon.configStore.Debug 341 if !debug { 342 t.Fatal("Expected debug 'enabled', got 'disabled'") 343 } 344 } 345 346 func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) { 347 if os.Getuid() != 0 { 348 t.Skip("root required") 349 } 350 daemon := &Daemon{ 351 imageService: images.NewImageService(images.ImageServiceConfig{}), 352 configStore: &config.Config{}, 353 } 354 355 enableConfig := &config.Config{ 356 CommonConfig: config.CommonConfig{ 357 NetworkDiagnosticPort: 2000, 358 ValuesSet: map[string]interface{}{ 359 "network-diagnostic-port": 2000, 360 }, 361 }, 362 } 363 364 netOptions, err := daemon.networkOptions(nil, nil) 365 if err != nil { 366 t.Fatal(err) 367 } 368 controller, err := libnetwork.New(netOptions...) 369 if err != nil { 370 t.Fatal(err) 371 } 372 daemon.netController = controller 373 374 // Enable/Disable the server for some iterations 375 for i := 0; i < 10; i++ { 376 enableConfig.CommonConfig.NetworkDiagnosticPort++ 377 if err := daemon.Reload(enableConfig); err != nil { 378 t.Fatal(err) 379 } 380 // Check that the diagnostic is enabled 381 if !daemon.netController.IsDiagnosticEnabled() { 382 t.Fatalf("diagnostic should be enabled") 383 } 384 385 // Reload 386 if err := daemon.Reload(&config.Config{}); err != nil { 387 t.Fatal(err) 388 } 389 // Check that the diagnostic is disabled 390 if daemon.netController.IsDiagnosticEnabled() { 391 t.Fatalf("diagnostic should be disabled") 392 } 393 } 394 395 enableConfig.CommonConfig.NetworkDiagnosticPort++ 396 // 2 times the enable should not create problems 397 if err := daemon.Reload(enableConfig); err != nil { 398 t.Fatal(err) 399 } 400 // Check that the diagnostic is enabled 401 if !daemon.netController.IsDiagnosticEnabled() { 402 t.Fatalf("diagnostic should be enable") 403 } 404 405 // Check that another reload does not cause issues 406 if err := daemon.Reload(enableConfig); err != nil { 407 t.Fatal(err) 408 } 409 // Check that the diagnostic is enable 410 if !daemon.netController.IsDiagnosticEnabled() { 411 t.Fatalf("diagnostic should be enable") 412 } 413 }