config_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. package worker
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. units "github.com/docker/go-units"
  10. . "github.com/smartystreets/goconvey/convey"
  11. )
  12. func TestConfig(t *testing.T) {
  13. var cfgBlob = `
  14. [global]
  15. name = "test_worker"
  16. log_dir = "/var/log/tunasync/{{.Name}}"
  17. mirror_dir = "/data/mirrors"
  18. concurrent = 10
  19. interval = 240
  20. retry = 3
  21. timeout = 86400
  22. [manager]
  23. api_base = "https://127.0.0.1:5000"
  24. token = "some_token"
  25. [server]
  26. hostname = "worker1.example.com"
  27. listen_addr = "127.0.0.1"
  28. listen_port = 6000
  29. ssl_cert = "/etc/tunasync.d/worker1.cert"
  30. ssl_key = "/etc/tunasync.d/worker1.key"
  31. [[mirrors]]
  32. name = "AOSP"
  33. provider = "command"
  34. upstream = "https://aosp.google.com/"
  35. interval = 720
  36. retry = 2
  37. timeout = 3600
  38. mirror_dir = "/data/git/AOSP"
  39. exec_on_success = [
  40. "bash -c 'echo ${TUNASYNC_JOB_EXIT_STATUS} > ${TUNASYNC_WORKING_DIR}/exit_status'"
  41. ]
  42. [mirrors.env]
  43. REPO = "/usr/local/bin/aosp-repo"
  44. [[mirrors]]
  45. name = "debian"
  46. provider = "two-stage-rsync"
  47. stage1_profile = "debian"
  48. upstream = "rsync://ftp.debian.org/debian/"
  49. use_ipv6 = true
  50. memory_limit = "256MiB"
  51. [[mirrors]]
  52. name = "fedora"
  53. provider = "rsync"
  54. upstream = "rsync://ftp.fedoraproject.org/fedora/"
  55. use_ipv6 = true
  56. memory_limit = "128M"
  57. exclude_file = "/etc/tunasync.d/fedora-exclude.txt"
  58. exec_on_failure = [
  59. "bash -c 'echo ${TUNASYNC_JOB_EXIT_STATUS} > ${TUNASYNC_WORKING_DIR}/exit_status'"
  60. ]
  61. `
  62. Convey("When giving invalid file", t, func() {
  63. cfg, err := LoadConfig("/path/to/invalid/file")
  64. So(err, ShouldNotBeNil)
  65. So(cfg, ShouldBeNil)
  66. })
  67. Convey("Everything should work on valid config file", t, func() {
  68. tmpfile, err := ioutil.TempFile("", "tunasync")
  69. So(err, ShouldEqual, nil)
  70. defer os.Remove(tmpfile.Name())
  71. tmpDir, err := ioutil.TempDir("", "tunasync")
  72. So(err, ShouldBeNil)
  73. defer os.RemoveAll(tmpDir)
  74. incSection := fmt.Sprintf(
  75. "\n[include]\n"+
  76. "include_mirrors = \"%s/*.conf\"",
  77. tmpDir,
  78. )
  79. curCfgBlob := cfgBlob + incSection
  80. err = ioutil.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
  81. So(err, ShouldEqual, nil)
  82. defer tmpfile.Close()
  83. incBlob1 := `
  84. [[mirrors]]
  85. name = "debian-cd"
  86. provider = "two-stage-rsync"
  87. stage1_profile = "debian"
  88. use_ipv6 = true
  89. [[mirrors]]
  90. name = "debian-security"
  91. provider = "two-stage-rsync"
  92. stage1_profile = "debian"
  93. use_ipv6 = true
  94. `
  95. incBlob2 := `
  96. [[mirrors]]
  97. name = "ubuntu"
  98. provider = "two-stage-rsync"
  99. stage1_profile = "debian"
  100. use_ipv6 = true
  101. `
  102. err = ioutil.WriteFile(filepath.Join(tmpDir, "debian.conf"), []byte(incBlob1), 0644)
  103. So(err, ShouldEqual, nil)
  104. err = ioutil.WriteFile(filepath.Join(tmpDir, "ubuntu.conf"), []byte(incBlob2), 0644)
  105. So(err, ShouldEqual, nil)
  106. cfg, err := LoadConfig(tmpfile.Name())
  107. So(err, ShouldBeNil)
  108. So(cfg.Global.Name, ShouldEqual, "test_worker")
  109. So(cfg.Global.Interval, ShouldEqual, 240)
  110. So(cfg.Global.Retry, ShouldEqual, 3)
  111. So(cfg.Global.Timeout, ShouldEqual, 86400)
  112. So(cfg.Global.MirrorDir, ShouldEqual, "/data/mirrors")
  113. So(cfg.Manager.APIBase, ShouldEqual, "https://127.0.0.1:5000")
  114. So(cfg.Server.Hostname, ShouldEqual, "worker1.example.com")
  115. m := cfg.Mirrors[0]
  116. So(m.Name, ShouldEqual, "AOSP")
  117. So(m.MirrorDir, ShouldEqual, "/data/git/AOSP")
  118. So(m.Provider, ShouldEqual, provCommand)
  119. So(m.Interval, ShouldEqual, 720)
  120. So(m.Retry, ShouldEqual, 2)
  121. So(m.Timeout, ShouldEqual, 3600)
  122. So(m.Env["REPO"], ShouldEqual, "/usr/local/bin/aosp-repo")
  123. m = cfg.Mirrors[1]
  124. So(m.Name, ShouldEqual, "debian")
  125. So(m.MirrorDir, ShouldEqual, "")
  126. So(m.Provider, ShouldEqual, provTwoStageRsync)
  127. So(m.MemoryLimit.Value(), ShouldEqual, 256 * units.MiB)
  128. m = cfg.Mirrors[2]
  129. So(m.Name, ShouldEqual, "fedora")
  130. So(m.MirrorDir, ShouldEqual, "")
  131. So(m.Provider, ShouldEqual, provRsync)
  132. So(m.ExcludeFile, ShouldEqual, "/etc/tunasync.d/fedora-exclude.txt")
  133. So(m.MemoryLimit.Value(), ShouldEqual, 128 * units.MiB)
  134. m = cfg.Mirrors[3]
  135. So(m.Name, ShouldEqual, "debian-cd")
  136. So(m.MirrorDir, ShouldEqual, "")
  137. So(m.Provider, ShouldEqual, provTwoStageRsync)
  138. So(m.MemoryLimit.Value(), ShouldEqual, 0)
  139. m = cfg.Mirrors[4]
  140. So(m.Name, ShouldEqual, "debian-security")
  141. m = cfg.Mirrors[5]
  142. So(m.Name, ShouldEqual, "ubuntu")
  143. So(len(cfg.Mirrors), ShouldEqual, 6)
  144. })
  145. Convey("Everything should work on nested config file", t, func() {
  146. tmpfile, err := ioutil.TempFile("", "tunasync")
  147. So(err, ShouldEqual, nil)
  148. defer os.Remove(tmpfile.Name())
  149. tmpDir, err := ioutil.TempDir("", "tunasync")
  150. So(err, ShouldBeNil)
  151. defer os.RemoveAll(tmpDir)
  152. incSection := fmt.Sprintf(
  153. "\n[include]\n"+
  154. "include_mirrors = \"%s/*.conf\"",
  155. tmpDir,
  156. )
  157. curCfgBlob := cfgBlob + incSection
  158. err = ioutil.WriteFile(tmpfile.Name(), []byte(curCfgBlob), 0644)
  159. So(err, ShouldEqual, nil)
  160. defer tmpfile.Close()
  161. incBlob1 := `
  162. [[mirrors]]
  163. name = "ipv6s"
  164. use_ipv6 = true
  165. [[mirrors.mirrors]]
  166. name = "debians"
  167. mirror_subdir = "debian"
  168. provider = "two-stage-rsync"
  169. stage1_profile = "debian"
  170. [[mirrors.mirrors.mirrors]]
  171. name = "debian-security"
  172. upstream = "rsync://test.host/debian-security/"
  173. [[mirrors.mirrors.mirrors]]
  174. name = "ubuntu"
  175. stage1_profile = "ubuntu"
  176. upstream = "rsync://test.host2/ubuntu/"
  177. [[mirrors.mirrors]]
  178. name = "debian-cd"
  179. provider = "rsync"
  180. upstream = "rsync://test.host3/debian-cd/"
  181. `
  182. err = ioutil.WriteFile(filepath.Join(tmpDir, "nest.conf"), []byte(incBlob1), 0644)
  183. So(err, ShouldEqual, nil)
  184. cfg, err := LoadConfig(tmpfile.Name())
  185. So(err, ShouldBeNil)
  186. So(cfg.Global.Name, ShouldEqual, "test_worker")
  187. So(cfg.Global.Interval, ShouldEqual, 240)
  188. So(cfg.Global.Retry, ShouldEqual, 3)
  189. So(cfg.Global.MirrorDir, ShouldEqual, "/data/mirrors")
  190. So(cfg.Manager.APIBase, ShouldEqual, "https://127.0.0.1:5000")
  191. So(cfg.Server.Hostname, ShouldEqual, "worker1.example.com")
  192. m := cfg.Mirrors[0]
  193. So(m.Name, ShouldEqual, "AOSP")
  194. So(m.MirrorDir, ShouldEqual, "/data/git/AOSP")
  195. So(m.Provider, ShouldEqual, provCommand)
  196. So(m.Interval, ShouldEqual, 720)
  197. So(m.Retry, ShouldEqual, 2)
  198. So(m.Env["REPO"], ShouldEqual, "/usr/local/bin/aosp-repo")
  199. m = cfg.Mirrors[1]
  200. So(m.Name, ShouldEqual, "debian")
  201. So(m.MirrorDir, ShouldEqual, "")
  202. So(m.Provider, ShouldEqual, provTwoStageRsync)
  203. m = cfg.Mirrors[2]
  204. So(m.Name, ShouldEqual, "fedora")
  205. So(m.MirrorDir, ShouldEqual, "")
  206. So(m.Provider, ShouldEqual, provRsync)
  207. So(m.ExcludeFile, ShouldEqual, "/etc/tunasync.d/fedora-exclude.txt")
  208. m = cfg.Mirrors[3]
  209. So(m.Name, ShouldEqual, "debian-security")
  210. So(m.MirrorDir, ShouldEqual, "")
  211. So(m.Provider, ShouldEqual, provTwoStageRsync)
  212. So(m.UseIPv6, ShouldEqual, true)
  213. So(m.Stage1Profile, ShouldEqual, "debian")
  214. m = cfg.Mirrors[4]
  215. So(m.Name, ShouldEqual, "ubuntu")
  216. So(m.MirrorDir, ShouldEqual, "")
  217. So(m.Provider, ShouldEqual, provTwoStageRsync)
  218. So(m.UseIPv6, ShouldEqual, true)
  219. So(m.Stage1Profile, ShouldEqual, "ubuntu")
  220. m = cfg.Mirrors[5]
  221. So(m.Name, ShouldEqual, "debian-cd")
  222. So(m.UseIPv6, ShouldEqual, true)
  223. So(m.Provider, ShouldEqual, provRsync)
  224. So(len(cfg.Mirrors), ShouldEqual, 6)
  225. })
  226. Convey("Providers can be inited from a valid config file", t, func() {
  227. tmpfile, err := ioutil.TempFile("", "tunasync")
  228. So(err, ShouldEqual, nil)
  229. defer os.Remove(tmpfile.Name())
  230. err = ioutil.WriteFile(tmpfile.Name(), []byte(cfgBlob), 0644)
  231. So(err, ShouldEqual, nil)
  232. defer tmpfile.Close()
  233. cfg, err := LoadConfig(tmpfile.Name())
  234. So(err, ShouldBeNil)
  235. providers := map[string]mirrorProvider{}
  236. for _, m := range cfg.Mirrors {
  237. p := newMirrorProvider(m, cfg)
  238. providers[p.Name()] = p
  239. }
  240. p := providers["AOSP"]
  241. So(p.Name(), ShouldEqual, "AOSP")
  242. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/AOSP")
  243. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/AOSP/latest.log")
  244. _, ok := p.(*cmdProvider)
  245. So(ok, ShouldBeTrue)
  246. for _, hook := range p.Hooks() {
  247. switch h := hook.(type) {
  248. case *execPostHook:
  249. So(h.command, ShouldResemble, []string{"bash", "-c", `echo ${TUNASYNC_JOB_EXIT_STATUS} > ${TUNASYNC_WORKING_DIR}/exit_status`})
  250. }
  251. }
  252. p = providers["debian"]
  253. So(p.Name(), ShouldEqual, "debian")
  254. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/debian")
  255. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/debian/latest.log")
  256. r2p, ok := p.(*twoStageRsyncProvider)
  257. So(ok, ShouldBeTrue)
  258. So(r2p.stage1Profile, ShouldEqual, "debian")
  259. So(r2p.WorkingDir(), ShouldEqual, "/data/mirrors/debian")
  260. p = providers["fedora"]
  261. So(p.Name(), ShouldEqual, "fedora")
  262. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/fedora")
  263. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/fedora/latest.log")
  264. rp, ok := p.(*rsyncProvider)
  265. So(ok, ShouldBeTrue)
  266. So(rp.WorkingDir(), ShouldEqual, "/data/mirrors/fedora")
  267. So(rp.excludeFile, ShouldEqual, "/etc/tunasync.d/fedora-exclude.txt")
  268. })
  269. Convey("MirrorSubdir should work", t, func() {
  270. tmpfile, err := ioutil.TempFile("", "tunasync")
  271. So(err, ShouldEqual, nil)
  272. defer os.Remove(tmpfile.Name())
  273. cfgBlob1 := `
  274. [global]
  275. name = "test_worker"
  276. log_dir = "/var/log/tunasync/{{.Name}}"
  277. mirror_dir = "/data/mirrors"
  278. concurrent = 10
  279. interval = 240
  280. timeout = 86400
  281. retry = 3
  282. [manager]
  283. api_base = "https://127.0.0.1:5000"
  284. token = "some_token"
  285. [server]
  286. hostname = "worker1.example.com"
  287. listen_addr = "127.0.0.1"
  288. listen_port = 6000
  289. ssl_cert = "/etc/tunasync.d/worker1.cert"
  290. ssl_key = "/etc/tunasync.d/worker1.key"
  291. [[mirrors]]
  292. name = "ipv6s"
  293. use_ipv6 = true
  294. [[mirrors.mirrors]]
  295. name = "debians"
  296. mirror_subdir = "debian"
  297. provider = "two-stage-rsync"
  298. stage1_profile = "debian"
  299. [[mirrors.mirrors.mirrors]]
  300. name = "debian-security"
  301. upstream = "rsync://test.host/debian-security/"
  302. [[mirrors.mirrors.mirrors]]
  303. name = "ubuntu"
  304. stage1_profile = "ubuntu"
  305. upstream = "rsync://test.host2/ubuntu/"
  306. [[mirrors.mirrors]]
  307. name = "debian-cd"
  308. provider = "rsync"
  309. upstream = "rsync://test.host3/debian-cd/"
  310. `
  311. err = ioutil.WriteFile(tmpfile.Name(), []byte(cfgBlob1), 0644)
  312. So(err, ShouldEqual, nil)
  313. defer tmpfile.Close()
  314. cfg, err := LoadConfig(tmpfile.Name())
  315. So(err, ShouldBeNil)
  316. providers := map[string]mirrorProvider{}
  317. for _, m := range cfg.Mirrors {
  318. p := newMirrorProvider(m, cfg)
  319. providers[p.Name()] = p
  320. }
  321. p := providers["debian-security"]
  322. So(p.Name(), ShouldEqual, "debian-security")
  323. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/debian-security")
  324. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/debian-security/latest.log")
  325. r2p, ok := p.(*twoStageRsyncProvider)
  326. So(ok, ShouldBeTrue)
  327. So(r2p.stage1Profile, ShouldEqual, "debian")
  328. So(r2p.WorkingDir(), ShouldEqual, "/data/mirrors/debian/debian-security")
  329. p = providers["ubuntu"]
  330. So(p.Name(), ShouldEqual, "ubuntu")
  331. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/ubuntu")
  332. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/ubuntu/latest.log")
  333. r2p, ok = p.(*twoStageRsyncProvider)
  334. So(ok, ShouldBeTrue)
  335. So(r2p.stage1Profile, ShouldEqual, "ubuntu")
  336. So(r2p.WorkingDir(), ShouldEqual, "/data/mirrors/debian/ubuntu")
  337. p = providers["debian-cd"]
  338. So(p.Name(), ShouldEqual, "debian-cd")
  339. So(p.LogDir(), ShouldEqual, "/var/log/tunasync/debian-cd")
  340. So(p.LogFile(), ShouldEqual, "/var/log/tunasync/debian-cd/latest.log")
  341. rp, ok := p.(*rsyncProvider)
  342. So(ok, ShouldBeTrue)
  343. So(rp.WorkingDir(), ShouldEqual, "/data/mirrors/debian-cd")
  344. So(p.Timeout(), ShouldEqual, 86400*time.Second)
  345. })
  346. }