daemon_test.go 9.1 KB

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