reload_test.go 15 KB

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