reload_test.go 12 KB

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