github.com/rish1988/moby@v25.0.2+incompatible/cmd/dockerd/daemon_test.go (about)

     1  package main
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/containerd/log"
     7  	"github.com/docker/docker/daemon/config"
     8  	"github.com/google/go-cmp/cmp/cmpopts"
     9  	"github.com/spf13/pflag"
    10  	"gotest.tools/v3/assert"
    11  	is "gotest.tools/v3/assert/cmp"
    12  	"gotest.tools/v3/fs"
    13  )
    14  
    15  func defaultOptions(t *testing.T, configFile string) *daemonOptions {
    16  	cfg, err := config.New()
    17  	assert.NilError(t, err)
    18  	opts := newDaemonOptions(cfg)
    19  	opts.flags = &pflag.FlagSet{}
    20  	opts.installFlags(opts.flags)
    21  	err = installConfigFlags(opts.daemonConfig, opts.flags)
    22  	assert.NilError(t, err)
    23  	defaultDaemonConfigFile, err := getDefaultDaemonConfigFile()
    24  	assert.NilError(t, err)
    25  	opts.flags.StringVar(&opts.configFile, "config-file", defaultDaemonConfigFile, "")
    26  	opts.configFile = configFile
    27  	err = opts.flags.Parse([]string{})
    28  	assert.NilError(t, err)
    29  	return opts
    30  }
    31  
    32  func TestLoadDaemonCliConfigWithoutOverriding(t *testing.T) {
    33  	opts := defaultOptions(t, "")
    34  	opts.Debug = true
    35  
    36  	loadedConfig, err := loadDaemonCliConfig(opts)
    37  	assert.NilError(t, err)
    38  	assert.Assert(t, loadedConfig != nil)
    39  	if !loadedConfig.Debug {
    40  		t.Fatalf("expected debug to be copied from the common flags, got false")
    41  	}
    42  }
    43  
    44  func TestLoadDaemonCliConfigWithTLS(t *testing.T) {
    45  	opts := defaultOptions(t, "")
    46  	opts.TLSOptions.CAFile = "/tmp/ca.pem"
    47  	opts.TLS = true
    48  
    49  	loadedConfig, err := loadDaemonCliConfig(opts)
    50  	assert.NilError(t, err)
    51  	assert.Assert(t, loadedConfig != nil)
    52  	assert.Check(t, is.Equal("/tmp/ca.pem", loadedConfig.TLSOptions.CAFile))
    53  }
    54  
    55  func TestLoadDaemonCliConfigWithConflicts(t *testing.T) {
    56  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels": ["l3=foo"]}`))
    57  	defer tempFile.Remove()
    58  	configFile := tempFile.Path()
    59  
    60  	opts := defaultOptions(t, configFile)
    61  	flags := opts.flags
    62  
    63  	assert.Check(t, flags.Set("config-file", configFile))
    64  	assert.Check(t, flags.Set("label", "l1=bar"))
    65  	assert.Check(t, flags.Set("label", "l2=baz"))
    66  
    67  	_, err := loadDaemonCliConfig(opts)
    68  	assert.Check(t, is.ErrorContains(err, "as a flag and in the configuration file: labels"))
    69  }
    70  
    71  func TestLoadDaemonCliWithConflictingNodeGenericResources(t *testing.T) {
    72  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"node-generic-resources": ["foo=bar", "bar=baz"]}`))
    73  	defer tempFile.Remove()
    74  	configFile := tempFile.Path()
    75  
    76  	opts := defaultOptions(t, configFile)
    77  	flags := opts.flags
    78  
    79  	assert.Check(t, flags.Set("config-file", configFile))
    80  	assert.Check(t, flags.Set("node-generic-resource", "r1=bar"))
    81  	assert.Check(t, flags.Set("node-generic-resource", "r2=baz"))
    82  
    83  	_, err := loadDaemonCliConfig(opts)
    84  	assert.Check(t, is.ErrorContains(err, "as a flag and in the configuration file: node-generic-resources"))
    85  }
    86  
    87  func TestLoadDaemonCliWithConflictingLabels(t *testing.T) {
    88  	opts := defaultOptions(t, "")
    89  	flags := opts.flags
    90  
    91  	assert.Check(t, flags.Set("label", "foo=bar"))
    92  	assert.Check(t, flags.Set("label", "foo=baz"))
    93  
    94  	_, err := loadDaemonCliConfig(opts)
    95  	assert.Check(t, is.Error(err, "conflict labels for foo=baz and foo=bar"))
    96  }
    97  
    98  func TestLoadDaemonCliWithDuplicateLabels(t *testing.T) {
    99  	opts := defaultOptions(t, "")
   100  	flags := opts.flags
   101  
   102  	assert.Check(t, flags.Set("label", "foo=the-same"))
   103  	assert.Check(t, flags.Set("label", "foo=the-same"))
   104  
   105  	_, err := loadDaemonCliConfig(opts)
   106  	assert.Check(t, err)
   107  }
   108  
   109  func TestLoadDaemonCliConfigWithTLSVerify(t *testing.T) {
   110  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"tlsverify": true}`))
   111  	defer tempFile.Remove()
   112  
   113  	opts := defaultOptions(t, tempFile.Path())
   114  	opts.TLSOptions.CAFile = "/tmp/ca.pem"
   115  
   116  	loadedConfig, err := loadDaemonCliConfig(opts)
   117  	assert.NilError(t, err)
   118  	assert.Assert(t, loadedConfig != nil)
   119  	assert.Check(t, is.Equal(*loadedConfig.TLS, true))
   120  }
   121  
   122  func TestLoadDaemonCliConfigWithExplicitTLSVerifyFalse(t *testing.T) {
   123  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"tlsverify": false}`))
   124  	defer tempFile.Remove()
   125  
   126  	opts := defaultOptions(t, tempFile.Path())
   127  	opts.TLSOptions.CAFile = "/tmp/ca.pem"
   128  
   129  	loadedConfig, err := loadDaemonCliConfig(opts)
   130  	assert.NilError(t, err)
   131  	assert.Assert(t, loadedConfig != nil)
   132  	assert.Check(t, *loadedConfig.TLS)
   133  }
   134  
   135  func TestLoadDaemonCliConfigWithoutTLSVerify(t *testing.T) {
   136  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{}`))
   137  	defer tempFile.Remove()
   138  
   139  	opts := defaultOptions(t, tempFile.Path())
   140  	opts.TLSOptions.CAFile = "/tmp/ca.pem"
   141  
   142  	loadedConfig, err := loadDaemonCliConfig(opts)
   143  	assert.NilError(t, err)
   144  	assert.Assert(t, loadedConfig != nil)
   145  	assert.Check(t, loadedConfig.TLS == nil)
   146  }
   147  
   148  func TestLoadDaemonCliConfigWithLogLevel(t *testing.T) {
   149  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"log-level": "warn"}`))
   150  	defer tempFile.Remove()
   151  
   152  	opts := defaultOptions(t, tempFile.Path())
   153  	loadedConfig, err := loadDaemonCliConfig(opts)
   154  	assert.NilError(t, err)
   155  	assert.Assert(t, loadedConfig != nil)
   156  	assert.Check(t, is.Equal("warn", loadedConfig.LogLevel))
   157  }
   158  
   159  func TestLoadDaemonCliConfigWithLogFormat(t *testing.T) {
   160  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"log-format": "json"}`))
   161  	defer tempFile.Remove()
   162  
   163  	opts := defaultOptions(t, tempFile.Path())
   164  	loadedConfig, err := loadDaemonCliConfig(opts)
   165  	assert.NilError(t, err)
   166  	assert.Assert(t, loadedConfig != nil)
   167  	assert.Check(t, is.Equal(log.JSONFormat, loadedConfig.LogFormat))
   168  }
   169  
   170  func TestLoadDaemonCliConfigWithInvalidLogFormat(t *testing.T) {
   171  	tempFile := fs.NewFile(t, "config", fs.WithContent(`{"log-format": "foo"}`))
   172  	defer tempFile.Remove()
   173  
   174  	opts := defaultOptions(t, tempFile.Path())
   175  	_, err := loadDaemonCliConfig(opts)
   176  	assert.Check(t, is.ErrorContains(err, "invalid log format: foo"))
   177  }
   178  
   179  func TestLoadDaemonConfigWithEmbeddedOptions(t *testing.T) {
   180  	content := `{"tlscacert": "/etc/certs/ca.pem", "log-driver": "syslog"}`
   181  	tempFile := fs.NewFile(t, "config", fs.WithContent(content))
   182  	defer tempFile.Remove()
   183  
   184  	opts := defaultOptions(t, tempFile.Path())
   185  	loadedConfig, err := loadDaemonCliConfig(opts)
   186  	assert.NilError(t, err)
   187  	assert.Assert(t, loadedConfig != nil)
   188  	assert.Check(t, is.Equal("/etc/certs/ca.pem", loadedConfig.TLSOptions.CAFile))
   189  	assert.Check(t, is.Equal("syslog", loadedConfig.LogConfig.Type))
   190  }
   191  
   192  func TestLoadDaemonConfigWithRegistryOptions(t *testing.T) {
   193  	content := `{
   194  		"allow-nondistributable-artifacts": ["allow-nondistributable-artifacts.example.com"],
   195  		"registry-mirrors": ["https://mirrors.example.com"],
   196  		"insecure-registries": ["https://insecure-registry.example.com"]
   197  	}`
   198  	tempFile := fs.NewFile(t, "config", fs.WithContent(content))
   199  	defer tempFile.Remove()
   200  
   201  	opts := defaultOptions(t, tempFile.Path())
   202  	loadedConfig, err := loadDaemonCliConfig(opts)
   203  	assert.NilError(t, err)
   204  	assert.Assert(t, loadedConfig != nil)
   205  
   206  	assert.Check(t, is.Len(loadedConfig.AllowNondistributableArtifacts, 1))
   207  	assert.Check(t, is.Len(loadedConfig.Mirrors, 1))
   208  	assert.Check(t, is.Len(loadedConfig.InsecureRegistries, 1))
   209  }
   210  
   211  func TestConfigureDaemonLogs(t *testing.T) {
   212  	conf := &config.Config{}
   213  	configureDaemonLogs(conf)
   214  	assert.Check(t, is.Equal(log.InfoLevel, log.GetLevel()))
   215  
   216  	// log level should not be changed when passing an invalid value
   217  	conf.LogLevel = "foobar"
   218  	configureDaemonLogs(conf)
   219  	assert.Check(t, is.Equal(log.InfoLevel, log.GetLevel()))
   220  
   221  	conf.LogLevel = "warn"
   222  	configureDaemonLogs(conf)
   223  	assert.Check(t, is.Equal(log.WarnLevel, log.GetLevel()))
   224  }
   225  
   226  func TestCDISpecDirs(t *testing.T) {
   227  	testCases := []struct {
   228  		description         string
   229  		configContent       string
   230  		specDirs            []string
   231  		expectedCDISpecDirs []string
   232  	}{
   233  		{
   234  			description:         "CDI enabled and no spec dirs specified returns default",
   235  			specDirs:            nil,
   236  			configContent:       `{"features": {"cdi": true}}`,
   237  			expectedCDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"},
   238  		},
   239  		{
   240  			description:         "CDI enabled and specified spec dirs are returned",
   241  			specDirs:            []string{"/foo/bar", "/baz/qux"},
   242  			configContent:       `{"features": {"cdi": true}}`,
   243  			expectedCDISpecDirs: []string{"/foo/bar", "/baz/qux"},
   244  		},
   245  		{
   246  			description:         "CDI enabled and empty string as spec dir returns empty slice",
   247  			specDirs:            []string{""},
   248  			configContent:       `{"features": {"cdi": true}}`,
   249  			expectedCDISpecDirs: []string{},
   250  		},
   251  		{
   252  			description:         "CDI enabled and empty config option returns empty slice",
   253  			configContent:       `{"cdi-spec-dirs": [], "features": {"cdi": true}}`,
   254  			expectedCDISpecDirs: []string{},
   255  		},
   256  		{
   257  			description:         "CDI disabled and no spec dirs specified returns no cdi spec dirs",
   258  			specDirs:            nil,
   259  			expectedCDISpecDirs: nil,
   260  		},
   261  		{
   262  			description:         "CDI disabled and specified spec dirs returns no cdi spec dirs",
   263  			specDirs:            []string{"/foo/bar", "/baz/qux"},
   264  			expectedCDISpecDirs: nil,
   265  		},
   266  	}
   267  
   268  	for _, tc := range testCases {
   269  		t.Run(tc.description, func(t *testing.T) {
   270  			tempFile := fs.NewFile(t, "config", fs.WithContent(tc.configContent))
   271  			defer tempFile.Remove()
   272  
   273  			opts := defaultOptions(t, tempFile.Path())
   274  
   275  			flags := opts.flags
   276  			for _, specDir := range tc.specDirs {
   277  				assert.Check(t, flags.Set("cdi-spec-dir", specDir))
   278  			}
   279  
   280  			loadedConfig, err := loadDaemonCliConfig(opts)
   281  			assert.NilError(t, err)
   282  
   283  			assert.Check(t, is.DeepEqual(tc.expectedCDISpecDirs, loadedConfig.CDISpecDirs, cmpopts.EquateEmpty()))
   284  		})
   285  	}
   286  }