github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/daemon/reload_test.go (about)

     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  }