reload_test.go 12 KB

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