reload_test.go 12 KB

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