github.com/sams1990/dockerrepo@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  }