github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/daemon/config/config_test.go (about)

     1  package config // import "github.com/docker/docker/daemon/config"
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/docker/docker/daemon/discovery"
    10  	"github.com/docker/docker/internal/testutil"
    11  	"github.com/docker/docker/opts"
    12  	"github.com/gotestyourself/gotestyourself/assert"
    13  	is "github.com/gotestyourself/gotestyourself/assert/cmp"
    14  	"github.com/gotestyourself/gotestyourself/fs"
    15  	"github.com/spf13/pflag"
    16  )
    17  
    18  func TestDaemonConfigurationNotFound(t *testing.T) {
    19  	_, err := MergeDaemonConfigurations(&Config{}, nil, "/tmp/foo-bar-baz-docker")
    20  	if err == nil || !os.IsNotExist(err) {
    21  		t.Fatalf("expected does not exist error, got %v", err)
    22  	}
    23  }
    24  
    25  func TestDaemonBrokenConfiguration(t *testing.T) {
    26  	f, err := ioutil.TempFile("", "docker-config-")
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	configFile := f.Name()
    32  	f.Write([]byte(`{"Debug": tru`))
    33  	f.Close()
    34  
    35  	_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
    36  	if err == nil {
    37  		t.Fatalf("expected error, got %v", err)
    38  	}
    39  }
    40  
    41  func TestParseClusterAdvertiseSettings(t *testing.T) {
    42  	_, err := ParseClusterAdvertiseSettings("something", "")
    43  	if err != discovery.ErrDiscoveryDisabled {
    44  		t.Fatalf("expected discovery disabled error, got %v\n", err)
    45  	}
    46  
    47  	_, err = ParseClusterAdvertiseSettings("", "something")
    48  	if err == nil {
    49  		t.Fatalf("expected discovery store error, got %v\n", err)
    50  	}
    51  
    52  	_, err = ParseClusterAdvertiseSettings("etcd", "127.0.0.1:8080")
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  }
    57  
    58  func TestFindConfigurationConflicts(t *testing.T) {
    59  	config := map[string]interface{}{"authorization-plugins": "foobar"}
    60  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
    61  
    62  	flags.String("authorization-plugins", "", "")
    63  	assert.Check(t, flags.Set("authorization-plugins", "asdf"))
    64  
    65  	testutil.ErrorContains(t,
    66  		findConfigurationConflicts(config, flags),
    67  		"authorization-plugins: (from flag: asdf, from file: foobar)")
    68  }
    69  
    70  func TestFindConfigurationConflictsWithNamedOptions(t *testing.T) {
    71  	config := map[string]interface{}{"hosts": []string{"qwer"}}
    72  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
    73  
    74  	var hosts []string
    75  	flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, opts.ValidateHost), "host", "H", "Daemon socket(s) to connect to")
    76  	assert.Check(t, flags.Set("host", "tcp://127.0.0.1:4444"))
    77  	assert.Check(t, flags.Set("host", "unix:///var/run/docker.sock"))
    78  
    79  	testutil.ErrorContains(t, findConfigurationConflicts(config, flags), "hosts")
    80  }
    81  
    82  func TestDaemonConfigurationMergeConflicts(t *testing.T) {
    83  	f, err := ioutil.TempFile("", "docker-config-")
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	configFile := f.Name()
    89  	f.Write([]byte(`{"debug": true}`))
    90  	f.Close()
    91  
    92  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
    93  	flags.Bool("debug", false, "")
    94  	flags.Set("debug", "false")
    95  
    96  	_, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
    97  	if err == nil {
    98  		t.Fatal("expected error, got nil")
    99  	}
   100  	if !strings.Contains(err.Error(), "debug") {
   101  		t.Fatalf("expected debug conflict, got %v", err)
   102  	}
   103  }
   104  
   105  func TestDaemonConfigurationMergeConcurrent(t *testing.T) {
   106  	f, err := ioutil.TempFile("", "docker-config-")
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	configFile := f.Name()
   112  	f.Write([]byte(`{"max-concurrent-downloads": 1}`))
   113  	f.Close()
   114  
   115  	_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
   116  	if err != nil {
   117  		t.Fatal("expected error, got nil")
   118  	}
   119  }
   120  
   121  func TestDaemonConfigurationMergeConcurrentError(t *testing.T) {
   122  	f, err := ioutil.TempFile("", "docker-config-")
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	configFile := f.Name()
   128  	f.Write([]byte(`{"max-concurrent-downloads": -1}`))
   129  	f.Close()
   130  
   131  	_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
   132  	if err == nil {
   133  		t.Fatalf("expected no error, got error %v", err)
   134  	}
   135  }
   136  
   137  func TestDaemonConfigurationMergeConflictsWithInnerStructs(t *testing.T) {
   138  	f, err := ioutil.TempFile("", "docker-config-")
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	configFile := f.Name()
   144  	f.Write([]byte(`{"tlscacert": "/etc/certificates/ca.pem"}`))
   145  	f.Close()
   146  
   147  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   148  	flags.String("tlscacert", "", "")
   149  	flags.Set("tlscacert", "~/.docker/ca.pem")
   150  
   151  	_, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
   152  	if err == nil {
   153  		t.Fatal("expected error, got nil")
   154  	}
   155  	if !strings.Contains(err.Error(), "tlscacert") {
   156  		t.Fatalf("expected tlscacert conflict, got %v", err)
   157  	}
   158  }
   159  
   160  func TestFindConfigurationConflictsWithUnknownKeys(t *testing.T) {
   161  	config := map[string]interface{}{"tls-verify": "true"}
   162  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   163  
   164  	flags.Bool("tlsverify", false, "")
   165  	err := findConfigurationConflicts(config, flags)
   166  	if err == nil {
   167  		t.Fatal("expected error, got nil")
   168  	}
   169  	if !strings.Contains(err.Error(), "the following directives don't match any configuration option: tls-verify") {
   170  		t.Fatalf("expected tls-verify conflict, got %v", err)
   171  	}
   172  }
   173  
   174  func TestFindConfigurationConflictsWithMergedValues(t *testing.T) {
   175  	var hosts []string
   176  	config := map[string]interface{}{"hosts": "tcp://127.0.0.1:2345"}
   177  	flags := pflag.NewFlagSet("base", pflag.ContinueOnError)
   178  	flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, nil), "host", "H", "")
   179  
   180  	err := findConfigurationConflicts(config, flags)
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	flags.Set("host", "unix:///var/run/docker.sock")
   186  	err = findConfigurationConflicts(config, flags)
   187  	if err == nil {
   188  		t.Fatal("expected error, got nil")
   189  	}
   190  	if !strings.Contains(err.Error(), "hosts: (from flag: [unix:///var/run/docker.sock], from file: tcp://127.0.0.1:2345)") {
   191  		t.Fatalf("expected hosts conflict, got %v", err)
   192  	}
   193  }
   194  
   195  func TestValidateConfigurationErrors(t *testing.T) {
   196  	minusNumber := -10
   197  	testCases := []struct {
   198  		config *Config
   199  	}{
   200  		{
   201  			config: &Config{
   202  				CommonConfig: CommonConfig{
   203  					Labels: []string{"one"},
   204  				},
   205  			},
   206  		},
   207  		{
   208  			config: &Config{
   209  				CommonConfig: CommonConfig{
   210  					Labels: []string{"foo=bar", "one"},
   211  				},
   212  			},
   213  		},
   214  		{
   215  			config: &Config{
   216  				CommonConfig: CommonConfig{
   217  					DNS: []string{"1.1.1.1o"},
   218  				},
   219  			},
   220  		},
   221  		{
   222  			config: &Config{
   223  				CommonConfig: CommonConfig{
   224  					DNS: []string{"2.2.2.2", "1.1.1.1o"},
   225  				},
   226  			},
   227  		},
   228  		{
   229  			config: &Config{
   230  				CommonConfig: CommonConfig{
   231  					DNSSearch: []string{"123456"},
   232  				},
   233  			},
   234  		},
   235  		{
   236  			config: &Config{
   237  				CommonConfig: CommonConfig{
   238  					DNSSearch: []string{"a.b.c", "123456"},
   239  				},
   240  			},
   241  		},
   242  		{
   243  			config: &Config{
   244  				CommonConfig: CommonConfig{
   245  					MaxConcurrentDownloads: &minusNumber,
   246  					// This is weird...
   247  					ValuesSet: map[string]interface{}{
   248  						"max-concurrent-downloads": -1,
   249  					},
   250  				},
   251  			},
   252  		},
   253  		{
   254  			config: &Config{
   255  				CommonConfig: CommonConfig{
   256  					MaxConcurrentUploads: &minusNumber,
   257  					// This is weird...
   258  					ValuesSet: map[string]interface{}{
   259  						"max-concurrent-uploads": -1,
   260  					},
   261  				},
   262  			},
   263  		},
   264  		{
   265  			config: &Config{
   266  				CommonConfig: CommonConfig{
   267  					NodeGenericResources: []string{"foo"},
   268  				},
   269  			},
   270  		},
   271  		{
   272  			config: &Config{
   273  				CommonConfig: CommonConfig{
   274  					NodeGenericResources: []string{"foo=bar", "foo=1"},
   275  				},
   276  			},
   277  		},
   278  	}
   279  	for _, tc := range testCases {
   280  		err := Validate(tc.config)
   281  		if err == nil {
   282  			t.Fatalf("expected error, got nil for config %v", tc.config)
   283  		}
   284  	}
   285  }
   286  
   287  func TestValidateConfiguration(t *testing.T) {
   288  	minusNumber := 4
   289  	testCases := []struct {
   290  		config *Config
   291  	}{
   292  		{
   293  			config: &Config{
   294  				CommonConfig: CommonConfig{
   295  					Labels: []string{"one=two"},
   296  				},
   297  			},
   298  		},
   299  		{
   300  			config: &Config{
   301  				CommonConfig: CommonConfig{
   302  					DNS: []string{"1.1.1.1"},
   303  				},
   304  			},
   305  		},
   306  		{
   307  			config: &Config{
   308  				CommonConfig: CommonConfig{
   309  					DNSSearch: []string{"a.b.c"},
   310  				},
   311  			},
   312  		},
   313  		{
   314  			config: &Config{
   315  				CommonConfig: CommonConfig{
   316  					MaxConcurrentDownloads: &minusNumber,
   317  					// This is weird...
   318  					ValuesSet: map[string]interface{}{
   319  						"max-concurrent-downloads": -1,
   320  					},
   321  				},
   322  			},
   323  		},
   324  		{
   325  			config: &Config{
   326  				CommonConfig: CommonConfig{
   327  					MaxConcurrentUploads: &minusNumber,
   328  					// This is weird...
   329  					ValuesSet: map[string]interface{}{
   330  						"max-concurrent-uploads": -1,
   331  					},
   332  				},
   333  			},
   334  		},
   335  		{
   336  			config: &Config{
   337  				CommonConfig: CommonConfig{
   338  					NodeGenericResources: []string{"foo=bar", "foo=baz"},
   339  				},
   340  			},
   341  		},
   342  		{
   343  			config: &Config{
   344  				CommonConfig: CommonConfig{
   345  					NodeGenericResources: []string{"foo=1"},
   346  				},
   347  			},
   348  		},
   349  	}
   350  	for _, tc := range testCases {
   351  		err := Validate(tc.config)
   352  		if err != nil {
   353  			t.Fatalf("expected no error, got error %v", err)
   354  		}
   355  	}
   356  }
   357  
   358  func TestModifiedDiscoverySettings(t *testing.T) {
   359  	cases := []struct {
   360  		current  *Config
   361  		modified *Config
   362  		expected bool
   363  	}{
   364  		{
   365  			current:  discoveryConfig("foo", "bar", map[string]string{}),
   366  			modified: discoveryConfig("foo", "bar", map[string]string{}),
   367  			expected: false,
   368  		},
   369  		{
   370  			current:  discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
   371  			modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
   372  			expected: false,
   373  		},
   374  		{
   375  			current:  discoveryConfig("foo", "bar", map[string]string{}),
   376  			modified: discoveryConfig("foo", "bar", nil),
   377  			expected: false,
   378  		},
   379  		{
   380  			current:  discoveryConfig("foo", "bar", nil),
   381  			modified: discoveryConfig("foo", "bar", map[string]string{}),
   382  			expected: false,
   383  		},
   384  		{
   385  			current:  discoveryConfig("foo", "bar", nil),
   386  			modified: discoveryConfig("baz", "bar", nil),
   387  			expected: true,
   388  		},
   389  		{
   390  			current:  discoveryConfig("foo", "bar", nil),
   391  			modified: discoveryConfig("foo", "baz", nil),
   392  			expected: true,
   393  		},
   394  		{
   395  			current:  discoveryConfig("foo", "bar", nil),
   396  			modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
   397  			expected: true,
   398  		},
   399  	}
   400  
   401  	for _, c := range cases {
   402  		got := ModifiedDiscoverySettings(c.current, c.modified.ClusterStore, c.modified.ClusterAdvertise, c.modified.ClusterOpts)
   403  		if c.expected != got {
   404  			t.Fatalf("expected %v, got %v: current config %v, new config %v", c.expected, got, c.current, c.modified)
   405  		}
   406  	}
   407  }
   408  
   409  func discoveryConfig(backendAddr, advertiseAddr string, opts map[string]string) *Config {
   410  	return &Config{
   411  		CommonConfig: CommonConfig{
   412  			ClusterStore:     backendAddr,
   413  			ClusterAdvertise: advertiseAddr,
   414  			ClusterOpts:      opts,
   415  		},
   416  	}
   417  }
   418  
   419  // TestReloadSetConfigFileNotExist tests that when `--config-file` is set
   420  // and it doesn't exist the `Reload` function returns an error.
   421  func TestReloadSetConfigFileNotExist(t *testing.T) {
   422  	configFile := "/tmp/blabla/not/exists/config.json"
   423  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   424  	flags.String("config-file", "", "")
   425  	flags.Set("config-file", configFile)
   426  
   427  	err := Reload(configFile, flags, func(c *Config) {})
   428  	assert.Check(t, is.ErrorContains(err, ""))
   429  	testutil.ErrorContains(t, err, "unable to configure the Docker daemon with file")
   430  }
   431  
   432  // TestReloadDefaultConfigNotExist tests that if the default configuration file
   433  // doesn't exist the daemon still will be reloaded.
   434  func TestReloadDefaultConfigNotExist(t *testing.T) {
   435  	reloaded := false
   436  	configFile := "/etc/docker/daemon.json"
   437  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   438  	flags.String("config-file", configFile, "")
   439  	err := Reload(configFile, flags, func(c *Config) {
   440  		reloaded = true
   441  	})
   442  	assert.Check(t, err)
   443  	assert.Check(t, reloaded)
   444  }
   445  
   446  // TestReloadBadDefaultConfig tests that when `--config-file` is not set
   447  // and the default configuration file exists and is bad return an error
   448  func TestReloadBadDefaultConfig(t *testing.T) {
   449  	f, err := ioutil.TempFile("", "docker-config-")
   450  	if err != nil {
   451  		t.Fatal(err)
   452  	}
   453  
   454  	configFile := f.Name()
   455  	f.Write([]byte(`{wrong: "configuration"}`))
   456  	f.Close()
   457  
   458  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   459  	flags.String("config-file", configFile, "")
   460  	err = Reload(configFile, flags, func(c *Config) {})
   461  	assert.Check(t, is.ErrorContains(err, ""))
   462  	testutil.ErrorContains(t, err, "unable to configure the Docker daemon with file")
   463  }
   464  
   465  func TestReloadWithConflictingLabels(t *testing.T) {
   466  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=bar","foo=baz"]}`))
   467  	defer tempFile.Remove()
   468  	configFile := tempFile.Path()
   469  
   470  	var lbls []string
   471  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   472  	flags.String("config-file", configFile, "")
   473  	flags.StringSlice("labels", lbls, "")
   474  	err := Reload(configFile, flags, func(c *Config) {})
   475  	testutil.ErrorContains(t, err, "conflict labels for foo=baz and foo=bar")
   476  }
   477  
   478  func TestReloadWithDuplicateLabels(t *testing.T) {
   479  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=the-same","foo=the-same"]}`))
   480  	defer tempFile.Remove()
   481  	configFile := tempFile.Path()
   482  
   483  	var lbls []string
   484  	flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
   485  	flags.String("config-file", configFile, "")
   486  	flags.StringSlice("labels", lbls, "")
   487  	err := Reload(configFile, flags, func(c *Config) {})
   488  	assert.Check(t, err)
   489  }