reload_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. package daemon // import "github.com/docker/docker/daemon"
  2. import (
  3. "reflect"
  4. "sort"
  5. "testing"
  6. "time"
  7. "github.com/docker/docker/daemon/config"
  8. "github.com/docker/docker/daemon/images"
  9. "github.com/docker/docker/pkg/discovery"
  10. _ "github.com/docker/docker/pkg/discovery/memory"
  11. "github.com/docker/docker/registry"
  12. "github.com/docker/libnetwork"
  13. "github.com/gotestyourself/gotestyourself/assert"
  14. is "github.com/gotestyourself/gotestyourself/assert/cmp"
  15. )
  16. func TestDaemonReloadLabels(t *testing.T) {
  17. daemon := &Daemon{
  18. configStore: &config.Config{
  19. CommonConfig: config.CommonConfig{
  20. Labels: []string{"foo:bar"},
  21. },
  22. },
  23. imageService: images.NewImageService(images.ImageServiceConfig{}),
  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. if err := daemon.Reload(newConfig); err != nil {
  34. t.Fatal(err)
  35. }
  36. label := daemon.configStore.Labels[0]
  37. if label != "foo:baz" {
  38. t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
  39. }
  40. }
  41. func TestDaemonReloadAllowNondistributableArtifacts(t *testing.T) {
  42. daemon := &Daemon{
  43. configStore: &config.Config{},
  44. imageService: images.NewImageService(images.ImageServiceConfig{}),
  45. }
  46. var err error
  47. // Initialize daemon with some registries.
  48. daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{
  49. AllowNondistributableArtifacts: []string{
  50. "127.0.0.0/8",
  51. "10.10.1.11:5000",
  52. "10.10.1.22:5000", // This will be removed during reload.
  53. "docker1.com",
  54. "docker2.com", // This will be removed during reload.
  55. },
  56. })
  57. if err != nil {
  58. t.Fatal(err)
  59. }
  60. registries := []string{
  61. "127.0.0.0/8",
  62. "10.10.1.11:5000",
  63. "10.10.1.33:5000", // This will be added during reload.
  64. "docker1.com",
  65. "docker3.com", // This will be added during reload.
  66. }
  67. newConfig := &config.Config{
  68. CommonConfig: config.CommonConfig{
  69. ServiceOptions: registry.ServiceOptions{
  70. AllowNondistributableArtifacts: registries,
  71. },
  72. ValuesSet: map[string]interface{}{
  73. "allow-nondistributable-artifacts": registries,
  74. },
  75. },
  76. }
  77. if err := daemon.Reload(newConfig); err != nil {
  78. t.Fatal(err)
  79. }
  80. var actual []string
  81. serviceConfig := daemon.RegistryService.ServiceConfig()
  82. for _, value := range serviceConfig.AllowNondistributableArtifactsCIDRs {
  83. actual = append(actual, value.String())
  84. }
  85. actual = append(actual, serviceConfig.AllowNondistributableArtifactsHostnames...)
  86. sort.Strings(registries)
  87. sort.Strings(actual)
  88. assert.Check(t, is.DeepEqual(registries, actual))
  89. }
  90. func TestDaemonReloadMirrors(t *testing.T) {
  91. daemon := &Daemon{
  92. imageService: images.NewImageService(images.ImageServiceConfig{}),
  93. }
  94. var err error
  95. daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{
  96. InsecureRegistries: []string{},
  97. Mirrors: []string{
  98. "https://mirror.test1.com",
  99. "https://mirror.test2.com", // this will be removed when reloading
  100. "https://mirror.test3.com", // this will be removed when reloading
  101. },
  102. })
  103. if err != nil {
  104. t.Fatal(err)
  105. }
  106. daemon.configStore = &config.Config{}
  107. type pair struct {
  108. valid bool
  109. mirrors []string
  110. after []string
  111. }
  112. loadMirrors := []pair{
  113. {
  114. valid: false,
  115. mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid
  116. after: []string{},
  117. },
  118. {
  119. valid: false,
  120. mirrors: []string{"mirror.test1.com"}, // this mirror is invalid
  121. after: []string{},
  122. },
  123. {
  124. valid: false,
  125. mirrors: []string{"10.10.1.11:5000", "mirror.test1.com"}, // mirrors are invalid
  126. after: []string{},
  127. },
  128. {
  129. valid: true,
  130. mirrors: []string{"https://mirror.test1.com", "https://mirror.test4.com"},
  131. after: []string{"https://mirror.test1.com/", "https://mirror.test4.com/"},
  132. },
  133. }
  134. for _, value := range loadMirrors {
  135. valuesSets := make(map[string]interface{})
  136. valuesSets["registry-mirrors"] = value.mirrors
  137. newConfig := &config.Config{
  138. CommonConfig: config.CommonConfig{
  139. ServiceOptions: registry.ServiceOptions{
  140. Mirrors: value.mirrors,
  141. },
  142. ValuesSet: valuesSets,
  143. },
  144. }
  145. err := daemon.Reload(newConfig)
  146. if !value.valid && err == nil {
  147. // mirrors should be invalid, should be a non-nil error
  148. t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors)
  149. }
  150. if value.valid {
  151. if err != nil {
  152. // mirrors should be valid, should be no error
  153. t.Fatal(err)
  154. }
  155. registryService := daemon.RegistryService.ServiceConfig()
  156. if len(registryService.Mirrors) != len(value.after) {
  157. t.Fatalf("Expected %d daemon mirrors %s while get %d with %s",
  158. len(value.after),
  159. value.after,
  160. len(registryService.Mirrors),
  161. registryService.Mirrors)
  162. }
  163. dataMap := map[string]struct{}{}
  164. for _, mirror := range registryService.Mirrors {
  165. if _, exist := dataMap[mirror]; !exist {
  166. dataMap[mirror] = struct{}{}
  167. }
  168. }
  169. for _, address := range value.after {
  170. if _, exist := dataMap[address]; !exist {
  171. t.Fatalf("Expected %s in daemon mirrors, while get none", address)
  172. }
  173. }
  174. }
  175. }
  176. }
  177. func TestDaemonReloadInsecureRegistries(t *testing.T) {
  178. daemon := &Daemon{
  179. imageService: images.NewImageService(images.ImageServiceConfig{}),
  180. }
  181. var err error
  182. // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000"
  183. daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{
  184. InsecureRegistries: []string{
  185. "127.0.0.0/8",
  186. "10.10.1.11:5000",
  187. "10.10.1.22:5000", // this will be removed when reloading
  188. "docker1.com",
  189. "docker2.com", // this will be removed when reloading
  190. },
  191. })
  192. if err != nil {
  193. t.Fatal(err)
  194. }
  195. daemon.configStore = &config.Config{}
  196. insecureRegistries := []string{
  197. "127.0.0.0/8", // this will be kept
  198. "10.10.1.11:5000", // this will be kept
  199. "10.10.1.33:5000", // this will be newly added
  200. "docker1.com", // this will be kept
  201. "docker3.com", // this will be newly added
  202. }
  203. valuesSets := make(map[string]interface{})
  204. valuesSets["insecure-registries"] = insecureRegistries
  205. newConfig := &config.Config{
  206. CommonConfig: config.CommonConfig{
  207. ServiceOptions: registry.ServiceOptions{
  208. InsecureRegistries: insecureRegistries,
  209. },
  210. ValuesSet: valuesSets,
  211. },
  212. }
  213. if err := daemon.Reload(newConfig); err != nil {
  214. t.Fatal(err)
  215. }
  216. // After Reload, daemon.RegistryService will be changed which is useful
  217. // for registry communication in daemon.
  218. registries := daemon.RegistryService.ServiceConfig()
  219. // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon.
  220. // Then collect registries.InsecureRegistryCIDRs in dataMap.
  221. // When collecting, we need to convert CIDRS into string as a key,
  222. // while the times of key appears as value.
  223. dataMap := map[string]int{}
  224. for _, value := range registries.InsecureRegistryCIDRs {
  225. if _, ok := dataMap[value.String()]; !ok {
  226. dataMap[value.String()] = 1
  227. } else {
  228. dataMap[value.String()]++
  229. }
  230. }
  231. for _, value := range registries.IndexConfigs {
  232. if _, ok := dataMap[value.Name]; !ok {
  233. dataMap[value.Name] = 1
  234. } else {
  235. dataMap[value.Name]++
  236. }
  237. }
  238. // Finally compare dataMap with the original insecureRegistries.
  239. // Each value in insecureRegistries should appear in daemon's insecure registries,
  240. // and each can only appear exactly ONCE.
  241. for _, r := range insecureRegistries {
  242. if value, ok := dataMap[r]; !ok {
  243. t.Fatalf("Expected daemon insecure registry %s, got none", r)
  244. } else if value != 1 {
  245. t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value)
  246. }
  247. }
  248. // assert if "10.10.1.22:5000" is removed when reloading
  249. if value, ok := dataMap["10.10.1.22:5000"]; ok {
  250. t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value)
  251. }
  252. // assert if "docker2.com" is removed when reloading
  253. if value, ok := dataMap["docker2.com"]; ok {
  254. t.Fatalf("Expected no insecure registry of docker2.com, got %d", value)
  255. }
  256. }
  257. func TestDaemonReloadNotAffectOthers(t *testing.T) {
  258. daemon := &Daemon{
  259. imageService: images.NewImageService(images.ImageServiceConfig{}),
  260. }
  261. daemon.configStore = &config.Config{
  262. CommonConfig: config.CommonConfig{
  263. Labels: []string{"foo:bar"},
  264. Debug: true,
  265. },
  266. }
  267. valuesSets := make(map[string]interface{})
  268. valuesSets["labels"] = "foo:baz"
  269. newConfig := &config.Config{
  270. CommonConfig: config.CommonConfig{
  271. Labels: []string{"foo:baz"},
  272. ValuesSet: valuesSets,
  273. },
  274. }
  275. if err := daemon.Reload(newConfig); err != nil {
  276. t.Fatal(err)
  277. }
  278. label := daemon.configStore.Labels[0]
  279. if label != "foo:baz" {
  280. t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
  281. }
  282. debug := daemon.configStore.Debug
  283. if !debug {
  284. t.Fatal("Expected debug 'enabled', got 'disabled'")
  285. }
  286. }
  287. func TestDaemonDiscoveryReload(t *testing.T) {
  288. daemon := &Daemon{
  289. imageService: images.NewImageService(images.ImageServiceConfig{}),
  290. }
  291. daemon.configStore = &config.Config{
  292. CommonConfig: config.CommonConfig{
  293. ClusterStore: "memory://127.0.0.1",
  294. ClusterAdvertise: "127.0.0.1:3333",
  295. },
  296. }
  297. if err := daemon.initDiscovery(daemon.configStore); err != nil {
  298. t.Fatal(err)
  299. }
  300. expected := discovery.Entries{
  301. &discovery.Entry{Host: "127.0.0.1", Port: "3333"},
  302. }
  303. select {
  304. case <-time.After(10 * time.Second):
  305. t.Fatal("timeout waiting for discovery")
  306. case <-daemon.discoveryWatcher.ReadyCh():
  307. }
  308. stopCh := make(chan struct{})
  309. defer close(stopCh)
  310. ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
  311. select {
  312. case <-time.After(1 * time.Second):
  313. t.Fatal("failed to get discovery advertisements in time")
  314. case e := <-ch:
  315. if !reflect.DeepEqual(e, expected) {
  316. t.Fatalf("expected %v, got %v\n", expected, e)
  317. }
  318. case e := <-errCh:
  319. t.Fatal(e)
  320. }
  321. valuesSets := make(map[string]interface{})
  322. valuesSets["cluster-store"] = "memory://127.0.0.1:2222"
  323. valuesSets["cluster-advertise"] = "127.0.0.1:5555"
  324. newConfig := &config.Config{
  325. CommonConfig: config.CommonConfig{
  326. ClusterStore: "memory://127.0.0.1:2222",
  327. ClusterAdvertise: "127.0.0.1:5555",
  328. ValuesSet: valuesSets,
  329. },
  330. }
  331. expected = discovery.Entries{
  332. &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
  333. }
  334. if err := daemon.Reload(newConfig); err != nil {
  335. t.Fatal(err)
  336. }
  337. select {
  338. case <-time.After(10 * time.Second):
  339. t.Fatal("timeout waiting for discovery")
  340. case <-daemon.discoveryWatcher.ReadyCh():
  341. }
  342. ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
  343. select {
  344. case <-time.After(1 * time.Second):
  345. t.Fatal("failed to get discovery advertisements in time")
  346. case e := <-ch:
  347. if !reflect.DeepEqual(e, expected) {
  348. t.Fatalf("expected %v, got %v\n", expected, e)
  349. }
  350. case e := <-errCh:
  351. t.Fatal(e)
  352. }
  353. }
  354. func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
  355. daemon := &Daemon{
  356. imageService: images.NewImageService(images.ImageServiceConfig{}),
  357. }
  358. daemon.configStore = &config.Config{}
  359. valuesSet := make(map[string]interface{})
  360. valuesSet["cluster-store"] = "memory://127.0.0.1:2222"
  361. valuesSet["cluster-advertise"] = "127.0.0.1:5555"
  362. newConfig := &config.Config{
  363. CommonConfig: config.CommonConfig{
  364. ClusterStore: "memory://127.0.0.1:2222",
  365. ClusterAdvertise: "127.0.0.1:5555",
  366. ValuesSet: valuesSet,
  367. },
  368. }
  369. expected := discovery.Entries{
  370. &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
  371. }
  372. if err := daemon.Reload(newConfig); err != nil {
  373. t.Fatal(err)
  374. }
  375. select {
  376. case <-time.After(10 * time.Second):
  377. t.Fatal("timeout waiting for discovery")
  378. case <-daemon.discoveryWatcher.ReadyCh():
  379. }
  380. stopCh := make(chan struct{})
  381. defer close(stopCh)
  382. ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
  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. func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) {
  395. daemon := &Daemon{
  396. imageService: images.NewImageService(images.ImageServiceConfig{}),
  397. }
  398. daemon.configStore = &config.Config{
  399. CommonConfig: config.CommonConfig{
  400. ClusterStore: "memory://127.0.0.1",
  401. },
  402. }
  403. valuesSets := make(map[string]interface{})
  404. valuesSets["cluster-advertise"] = "127.0.0.1:5555"
  405. newConfig := &config.Config{
  406. CommonConfig: config.CommonConfig{
  407. ClusterAdvertise: "127.0.0.1:5555",
  408. ValuesSet: valuesSets,
  409. },
  410. }
  411. expected := discovery.Entries{
  412. &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
  413. }
  414. if err := daemon.Reload(newConfig); err != nil {
  415. t.Fatal(err)
  416. }
  417. select {
  418. case <-daemon.discoveryWatcher.ReadyCh():
  419. case <-time.After(10 * time.Second):
  420. t.Fatal("Timeout waiting for discovery")
  421. }
  422. stopCh := make(chan struct{})
  423. defer close(stopCh)
  424. ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
  425. select {
  426. case <-time.After(1 * time.Second):
  427. t.Fatal("failed to get discovery advertisements in time")
  428. case e := <-ch:
  429. if !reflect.DeepEqual(e, expected) {
  430. t.Fatalf("expected %v, got %v\n", expected, e)
  431. }
  432. case e := <-errCh:
  433. t.Fatal(e)
  434. }
  435. }
  436. func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) {
  437. daemon := &Daemon{
  438. imageService: images.NewImageService(images.ImageServiceConfig{}),
  439. }
  440. daemon.configStore = &config.Config{}
  441. valuesSet := make(map[string]interface{})
  442. valuesSet["network-diagnostic-port"] = 2000
  443. enableConfig := &config.Config{
  444. CommonConfig: config.CommonConfig{
  445. NetworkDiagnosticPort: 2000,
  446. ValuesSet: valuesSet,
  447. },
  448. }
  449. disableConfig := &config.Config{
  450. CommonConfig: config.CommonConfig{},
  451. }
  452. netOptions, err := daemon.networkOptions(enableConfig, nil, nil)
  453. if err != nil {
  454. t.Fatal(err)
  455. }
  456. controller, err := libnetwork.New(netOptions...)
  457. if err != nil {
  458. t.Fatal(err)
  459. }
  460. daemon.netController = controller
  461. // Enable/Disable the server for some iterations
  462. for i := 0; i < 10; i++ {
  463. enableConfig.CommonConfig.NetworkDiagnosticPort++
  464. if err := daemon.Reload(enableConfig); err != nil {
  465. t.Fatal(err)
  466. }
  467. // Check that the diagnostic is enabled
  468. if !daemon.netController.IsDiagnosticEnabled() {
  469. t.Fatalf("diagnostic should be enable")
  470. }
  471. // Reload
  472. if err := daemon.Reload(disableConfig); err != nil {
  473. t.Fatal(err)
  474. }
  475. // Check that the diagnostic is disabled
  476. if daemon.netController.IsDiagnosticEnabled() {
  477. t.Fatalf("diagnostic should be disable")
  478. }
  479. }
  480. enableConfig.CommonConfig.NetworkDiagnosticPort++
  481. // 2 times the enable should not create problems
  482. if err := daemon.Reload(enableConfig); err != nil {
  483. t.Fatal(err)
  484. }
  485. // Check that the diagnostic is enabled
  486. if !daemon.netController.IsDiagnosticEnabled() {
  487. t.Fatalf("diagnostic should be enable")
  488. }
  489. // Check that another reload does not cause issues
  490. if err := daemon.Reload(enableConfig); err != nil {
  491. t.Fatal(err)
  492. }
  493. // Check that the diagnostic is enable
  494. if !daemon.netController.IsDiagnosticEnabled() {
  495. t.Fatalf("diagnostic should be enable")
  496. }
  497. }