github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/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 valuesSets := make(map[string]interface{}) 242 valuesSets["insecure-registries"] = insecureRegistries 243 244 newConfig := &config.Config{ 245 CommonConfig: config.CommonConfig{ 246 ServiceOptions: registry.ServiceOptions{ 247 InsecureRegistries: insecureRegistries, 248 }, 249 ValuesSet: valuesSets, 250 }, 251 } 252 253 if err := daemon.Reload(newConfig); err != nil { 254 t.Fatal(err) 255 } 256 257 // After Reload, daemon.RegistryService will be changed which is useful 258 // for registry communication in daemon. 259 registries := daemon.registryService.ServiceConfig() 260 261 // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon. 262 // Then collect registries.InsecureRegistryCIDRs in dataMap. 263 // When collecting, we need to convert CIDRS into string as a key, 264 // while the times of key appears as value. 265 dataMap := map[string]int{} 266 for _, value := range registries.InsecureRegistryCIDRs { 267 if _, ok := dataMap[value.String()]; !ok { 268 dataMap[value.String()] = 1 269 } else { 270 dataMap[value.String()]++ 271 } 272 } 273 274 for _, value := range registries.IndexConfigs { 275 if _, ok := dataMap[value.Name]; !ok { 276 dataMap[value.Name] = 1 277 } else { 278 dataMap[value.Name]++ 279 } 280 } 281 282 // Finally compare dataMap with the original insecureRegistries. 283 // Each value in insecureRegistries should appear in daemon's insecure registries, 284 // and each can only appear exactly ONCE. 285 for _, r := range insecureRegistries { 286 if value, ok := dataMap[r]; !ok { 287 t.Fatalf("Expected daemon insecure registry %s, got none", r) 288 } else if value != 1 { 289 t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value) 290 } 291 } 292 293 // assert if "10.10.1.22:5000" is removed when reloading 294 if value, ok := dataMap["10.10.1.22:5000"]; ok { 295 t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value) 296 } 297 298 // assert if "docker2.com" is removed when reloading 299 if value, ok := dataMap["docker2.example.com"]; ok { 300 t.Fatalf("Expected no insecure registry of docker2.com, got %d", value) 301 } 302 } 303 304 func TestDaemonReloadNotAffectOthers(t *testing.T) { 305 daemon := &Daemon{ 306 imageService: images.NewImageService(images.ImageServiceConfig{}), 307 } 308 muteLogs() 309 310 daemon.configStore = &config.Config{ 311 CommonConfig: config.CommonConfig{ 312 Labels: []string{"foo:bar"}, 313 Debug: true, 314 }, 315 } 316 317 valuesSets := make(map[string]interface{}) 318 valuesSets["labels"] = "foo:baz" 319 newConfig := &config.Config{ 320 CommonConfig: config.CommonConfig{ 321 Labels: []string{"foo:baz"}, 322 ValuesSet: valuesSets, 323 }, 324 } 325 326 if err := daemon.Reload(newConfig); err != nil { 327 t.Fatal(err) 328 } 329 330 label := daemon.configStore.Labels[0] 331 if label != "foo:baz" { 332 t.Fatalf("Expected daemon label `foo:baz`, got %s", label) 333 } 334 debug := daemon.configStore.Debug 335 if !debug { 336 t.Fatal("Expected debug 'enabled', got 'disabled'") 337 } 338 } 339 340 func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) { 341 if os.Getuid() != 0 { 342 t.Skip("root required") 343 } 344 daemon := &Daemon{ 345 imageService: images.NewImageService(images.ImageServiceConfig{}), 346 configStore: &config.Config{}, 347 } 348 349 enableConfig := &config.Config{ 350 CommonConfig: config.CommonConfig{ 351 NetworkDiagnosticPort: 2000, 352 ValuesSet: map[string]interface{}{ 353 "network-diagnostic-port": 2000, 354 }, 355 }, 356 } 357 358 netOptions, err := daemon.networkOptions(nil, nil) 359 if err != nil { 360 t.Fatal(err) 361 } 362 controller, err := libnetwork.New(netOptions...) 363 if err != nil { 364 t.Fatal(err) 365 } 366 daemon.netController = controller 367 368 // Enable/Disable the server for some iterations 369 for i := 0; i < 10; i++ { 370 enableConfig.CommonConfig.NetworkDiagnosticPort++ 371 if err := daemon.Reload(enableConfig); err != nil { 372 t.Fatal(err) 373 } 374 // Check that the diagnostic is enabled 375 if !daemon.netController.IsDiagnosticEnabled() { 376 t.Fatalf("diagnostic should be enabled") 377 } 378 379 // Reload 380 if err := daemon.Reload(&config.Config{}); err != nil { 381 t.Fatal(err) 382 } 383 // Check that the diagnostic is disabled 384 if daemon.netController.IsDiagnosticEnabled() { 385 t.Fatalf("diagnostic should be disabled") 386 } 387 } 388 389 enableConfig.CommonConfig.NetworkDiagnosticPort++ 390 // 2 times the enable should not create problems 391 if err := daemon.Reload(enableConfig); err != nil { 392 t.Fatal(err) 393 } 394 // Check that the diagnostic is enabled 395 if !daemon.netController.IsDiagnosticEnabled() { 396 t.Fatalf("diagnostic should be enable") 397 } 398 399 // Check that another reload does not cause issues 400 if err := daemon.Reload(enableConfig); err != nil { 401 t.Fatal(err) 402 } 403 // Check that the diagnostic is enable 404 if !daemon.netController.IsDiagnosticEnabled() { 405 t.Fatalf("diagnostic should be enable") 406 } 407 }