fix compile error
[platform/upstream/docker-engine.git] / daemon / reload_test.go
1 // +build !solaris
2
3 package daemon
4
5 import (
6         "reflect"
7         "sort"
8         "testing"
9         "time"
10
11         "github.com/docker/docker/daemon/config"
12         "github.com/docker/docker/pkg/discovery"
13         _ "github.com/docker/docker/pkg/discovery/memory"
14         "github.com/docker/docker/registry"
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         // Initialize daemon with some registries.
50         daemon.RegistryService = registry.NewService(registry.ServiceOptions{
51                 AllowNondistributableArtifacts: []string{
52                         "127.0.0.0/8",
53                         "10.10.1.11:5000",
54                         "10.10.1.22:5000", // This will be removed during reload.
55                         "docker1.com",
56                         "docker2.com", // This will be removed during reload.
57                 },
58         })
59
60         registries := []string{
61                 "127.0.0.0/8",
62                 "10.10.1.11:5000",
63                 "10.10.1.33:5000", // This will be added during reload.
64                 "docker1.com",
65                 "docker3.com", // This will be added during reload.
66         }
67
68         newConfig := &config.Config{
69                 CommonConfig: config.CommonConfig{
70                         ServiceOptions: registry.ServiceOptions{
71                                 AllowNondistributableArtifacts: registries,
72                         },
73                         ValuesSet: map[string]interface{}{
74                                 "allow-nondistributable-artifacts": registries,
75                         },
76                 },
77         }
78
79         if err := daemon.Reload(newConfig); err != nil {
80                 t.Fatal(err)
81         }
82
83         actual := []string{}
84         serviceConfig := daemon.RegistryService.ServiceConfig()
85         for _, value := range serviceConfig.AllowNondistributableArtifactsCIDRs {
86                 actual = append(actual, value.String())
87         }
88         for _, value := range serviceConfig.AllowNondistributableArtifactsHostnames {
89                 actual = append(actual, value)
90         }
91
92         sort.Strings(registries)
93         sort.Strings(actual)
94         if !reflect.DeepEqual(registries, actual) {
95                 t.Fatalf("expected %v, got %v\n", registries, actual)
96         }
97 }
98
99 func TestDaemonReloadMirrors(t *testing.T) {
100         daemon := &Daemon{}
101         daemon.RegistryService = registry.NewService(registry.ServiceOptions{
102                 InsecureRegistries: []string{},
103                 Mirrors: []string{
104                         "https://mirror.test1.com",
105                         "https://mirror.test2.com", // this will be removed when reloading
106                         "https://mirror.test3.com", // this will be removed when reloading
107                 },
108         })
109
110         daemon.configStore = &config.Config{}
111
112         type pair struct {
113                 valid   bool
114                 mirrors []string
115                 after   []string
116         }
117
118         loadMirrors := []pair{
119                 {
120                         valid:   false,
121                         mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid
122                         after:   []string{},
123                 },
124                 {
125                         valid:   false,
126                         mirrors: []string{"mirror.test1.com"}, // this mirror is invalid
127                         after:   []string{},
128                 },
129                 {
130                         valid:   false,
131                         mirrors: []string{"10.10.1.11:5000", "mirror.test1.com"}, // mirrors are invalid
132                         after:   []string{},
133                 },
134                 {
135                         valid:   true,
136                         mirrors: []string{"https://mirror.test1.com", "https://mirror.test4.com"},
137                         after:   []string{"https://mirror.test1.com/", "https://mirror.test4.com/"},
138                 },
139         }
140
141         for _, value := range loadMirrors {
142                 valuesSets := make(map[string]interface{})
143                 valuesSets["registry-mirrors"] = value.mirrors
144
145                 newConfig := &config.Config{
146                         CommonConfig: config.CommonConfig{
147                                 ServiceOptions: registry.ServiceOptions{
148                                         Mirrors: value.mirrors,
149                                 },
150                                 ValuesSet: valuesSets,
151                         },
152                 }
153
154                 err := daemon.Reload(newConfig)
155                 if !value.valid && err == nil {
156                         // mirrors should be invalid, should be a non-nil error
157                         t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors)
158                 }
159
160                 if value.valid {
161                         if err != nil {
162                                 // mirrors should be valid, should be no error
163                                 t.Fatal(err)
164                         }
165                         registryService := daemon.RegistryService.ServiceConfig()
166
167                         if len(registryService.Mirrors) != len(value.after) {
168                                 t.Fatalf("Expected %d daemon mirrors %s while get %d with %s",
169                                         len(value.after),
170                                         value.after,
171                                         len(registryService.Mirrors),
172                                         registryService.Mirrors)
173                         }
174
175                         dataMap := map[string]struct{}{}
176
177                         for _, mirror := range registryService.Mirrors {
178                                 if _, exist := dataMap[mirror]; !exist {
179                                         dataMap[mirror] = struct{}{}
180                                 }
181                         }
182
183                         for _, address := range value.after {
184                                 if _, exist := dataMap[address]; !exist {
185                                         t.Fatalf("Expected %s in daemon mirrors, while get none", address)
186                                 }
187                         }
188                 }
189         }
190 }
191
192 func TestDaemonReloadInsecureRegistries(t *testing.T) {
193         daemon := &Daemon{}
194         // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000"
195         daemon.RegistryService = registry.NewService(registry.ServiceOptions{
196                 InsecureRegistries: []string{
197                         "127.0.0.0/8",
198                         "10.10.1.11:5000",
199                         "10.10.1.22:5000", // this will be removed when reloading
200                         "docker1.com",
201                         "docker2.com", // this will be removed when reloading
202                 },
203         })
204
205         daemon.configStore = &config.Config{}
206
207         insecureRegistries := []string{
208                 "127.0.0.0/8",     // this will be kept
209                 "10.10.1.11:5000", // this will be kept
210                 "10.10.1.33:5000", // this will be newly added
211                 "docker1.com",     // this will be kept
212                 "docker3.com",     // this will be newly added
213         }
214
215         valuesSets := make(map[string]interface{})
216         valuesSets["insecure-registries"] = insecureRegistries
217
218         newConfig := &config.Config{
219                 CommonConfig: config.CommonConfig{
220                         ServiceOptions: registry.ServiceOptions{
221                                 InsecureRegistries: insecureRegistries,
222                         },
223                         ValuesSet: valuesSets,
224                 },
225         }
226
227         if err := daemon.Reload(newConfig); err != nil {
228                 t.Fatal(err)
229         }
230
231         // After Reload, daemon.RegistryService will be changed which is useful
232         // for registry communication in daemon.
233         registries := daemon.RegistryService.ServiceConfig()
234
235         // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon.
236         // Then collect registries.InsecureRegistryCIDRs in dataMap.
237         // When collecting, we need to convert CIDRS into string as a key,
238         // while the times of key appears as value.
239         dataMap := map[string]int{}
240         for _, value := range registries.InsecureRegistryCIDRs {
241                 if _, ok := dataMap[value.String()]; !ok {
242                         dataMap[value.String()] = 1
243                 } else {
244                         dataMap[value.String()]++
245                 }
246         }
247
248         for _, value := range registries.IndexConfigs {
249                 if _, ok := dataMap[value.Name]; !ok {
250                         dataMap[value.Name] = 1
251                 } else {
252                         dataMap[value.Name]++
253                 }
254         }
255
256         // Finally compare dataMap with the original insecureRegistries.
257         // Each value in insecureRegistries should appear in daemon's insecure registries,
258         // and each can only appear exactly ONCE.
259         for _, r := range insecureRegistries {
260                 if value, ok := dataMap[r]; !ok {
261                         t.Fatalf("Expected daemon insecure registry %s, got none", r)
262                 } else if value != 1 {
263                         t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value)
264                 }
265         }
266
267         // assert if "10.10.1.22:5000" is removed when reloading
268         if value, ok := dataMap["10.10.1.22:5000"]; ok {
269                 t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value)
270         }
271
272         // assert if "docker2.com" is removed when reloading
273         if value, ok := dataMap["docker2.com"]; ok {
274                 t.Fatalf("Expected no insecure registry of docker2.com, got %d", value)
275         }
276 }
277
278 func TestDaemonReloadNotAffectOthers(t *testing.T) {
279         daemon := &Daemon{}
280         daemon.configStore = &config.Config{
281                 CommonConfig: config.CommonConfig{
282                         Labels: []string{"foo:bar"},
283                         Debug:  true,
284                 },
285         }
286
287         valuesSets := make(map[string]interface{})
288         valuesSets["labels"] = "foo:baz"
289         newConfig := &config.Config{
290                 CommonConfig: config.CommonConfig{
291                         Labels:    []string{"foo:baz"},
292                         ValuesSet: valuesSets,
293                 },
294         }
295
296         if err := daemon.Reload(newConfig); err != nil {
297                 t.Fatal(err)
298         }
299
300         label := daemon.configStore.Labels[0]
301         if label != "foo:baz" {
302                 t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
303         }
304         debug := daemon.configStore.Debug
305         if !debug {
306                 t.Fatal("Expected debug 'enabled', got 'disabled'")
307         }
308 }
309
310 func TestDaemonDiscoveryReload(t *testing.T) {
311         daemon := &Daemon{}
312         daemon.configStore = &config.Config{
313                 CommonConfig: config.CommonConfig{
314                         ClusterStore:     "memory://127.0.0.1",
315                         ClusterAdvertise: "127.0.0.1:3333",
316                 },
317         }
318
319         if err := daemon.initDiscovery(daemon.configStore); err != nil {
320                 t.Fatal(err)
321         }
322
323         expected := discovery.Entries{
324                 &discovery.Entry{Host: "127.0.0.1", Port: "3333"},
325         }
326
327         select {
328         case <-time.After(10 * time.Second):
329                 t.Fatal("timeout waiting for discovery")
330         case <-daemon.discoveryWatcher.ReadyCh():
331         }
332
333         stopCh := make(chan struct{})
334         defer close(stopCh)
335         ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
336
337         select {
338         case <-time.After(1 * time.Second):
339                 t.Fatal("failed to get discovery advertisements in time")
340         case e := <-ch:
341                 if !reflect.DeepEqual(e, expected) {
342                         t.Fatalf("expected %v, got %v\n", expected, e)
343                 }
344         case e := <-errCh:
345                 t.Fatal(e)
346         }
347
348         valuesSets := make(map[string]interface{})
349         valuesSets["cluster-store"] = "memory://127.0.0.1:2222"
350         valuesSets["cluster-advertise"] = "127.0.0.1:5555"
351         newConfig := &config.Config{
352                 CommonConfig: config.CommonConfig{
353                         ClusterStore:     "memory://127.0.0.1:2222",
354                         ClusterAdvertise: "127.0.0.1:5555",
355                         ValuesSet:        valuesSets,
356                 },
357         }
358
359         expected = discovery.Entries{
360                 &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
361         }
362
363         if err := daemon.Reload(newConfig); err != nil {
364                 t.Fatal(err)
365         }
366
367         select {
368         case <-time.After(10 * time.Second):
369                 t.Fatal("timeout waiting for discovery")
370         case <-daemon.discoveryWatcher.ReadyCh():
371         }
372
373         ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
374
375         select {
376         case <-time.After(1 * time.Second):
377                 t.Fatal("failed to get discovery advertisements in time")
378         case e := <-ch:
379                 if !reflect.DeepEqual(e, expected) {
380                         t.Fatalf("expected %v, got %v\n", expected, e)
381                 }
382         case e := <-errCh:
383                 t.Fatal(e)
384         }
385 }
386
387 func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
388         daemon := &Daemon{}
389         daemon.configStore = &config.Config{}
390
391         valuesSet := make(map[string]interface{})
392         valuesSet["cluster-store"] = "memory://127.0.0.1:2222"
393         valuesSet["cluster-advertise"] = "127.0.0.1:5555"
394         newConfig := &config.Config{
395                 CommonConfig: config.CommonConfig{
396                         ClusterStore:     "memory://127.0.0.1:2222",
397                         ClusterAdvertise: "127.0.0.1:5555",
398                         ValuesSet:        valuesSet,
399                 },
400         }
401
402         expected := discovery.Entries{
403                 &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
404         }
405
406         if err := daemon.Reload(newConfig); err != nil {
407                 t.Fatal(err)
408         }
409
410         select {
411         case <-time.After(10 * time.Second):
412                 t.Fatal("timeout waiting for discovery")
413         case <-daemon.discoveryWatcher.ReadyCh():
414         }
415
416         stopCh := make(chan struct{})
417         defer close(stopCh)
418         ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
419
420         select {
421         case <-time.After(1 * time.Second):
422                 t.Fatal("failed to get discovery advertisements in time")
423         case e := <-ch:
424                 if !reflect.DeepEqual(e, expected) {
425                         t.Fatalf("expected %v, got %v\n", expected, e)
426                 }
427         case e := <-errCh:
428                 t.Fatal(e)
429         }
430 }
431
432 func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) {
433         daemon := &Daemon{}
434         daemon.configStore = &config.Config{
435                 CommonConfig: config.CommonConfig{
436                         ClusterStore: "memory://127.0.0.1",
437                 },
438         }
439         valuesSets := make(map[string]interface{})
440         valuesSets["cluster-advertise"] = "127.0.0.1:5555"
441         newConfig := &config.Config{
442                 CommonConfig: config.CommonConfig{
443                         ClusterAdvertise: "127.0.0.1:5555",
444                         ValuesSet:        valuesSets,
445                 },
446         }
447         expected := discovery.Entries{
448                 &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
449         }
450
451         if err := daemon.Reload(newConfig); err != nil {
452                 t.Fatal(err)
453         }
454
455         select {
456         case <-daemon.discoveryWatcher.ReadyCh():
457         case <-time.After(10 * time.Second):
458                 t.Fatal("Timeout waiting for discovery")
459         }
460         stopCh := make(chan struct{})
461         defer close(stopCh)
462         ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
463
464         select {
465         case <-time.After(1 * time.Second):
466                 t.Fatal("failed to get discovery advertisements in time")
467         case e := <-ch:
468                 if !reflect.DeepEqual(e, expected) {
469                         t.Fatalf("expected %v, got %v\n", expected, e)
470                 }
471         case e := <-errCh:
472                 t.Fatal(e)
473         }
474 }