daemon_test.go 9.3 KB

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