config_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. package conf
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "testing"
  6. "github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
  7. )
  8. // Ensures that a configuration can be retrieved from environment variables.
  9. func TestConfigEnv(t *testing.T) {
  10. os.Setenv("ETCD_CA_FILE", "/tmp/file.ca")
  11. os.Setenv("ETCD_CERT_FILE", "/tmp/file.cert")
  12. os.Setenv("ETCD_CPU_PROFILE_FILE", "XXX")
  13. os.Setenv("ETCD_CORS", "localhost:4001,localhost:4002")
  14. os.Setenv("ETCD_DATA_DIR", "/tmp/data")
  15. os.Setenv("ETCD_DISCOVERY", "http://example.com/foobar")
  16. os.Setenv("ETCD_HTTP_READ_TIMEOUT", "2.34")
  17. os.Setenv("ETCD_HTTP_WRITE_TIMEOUT", "1.23")
  18. os.Setenv("ETCD_KEY_FILE", "/tmp/file.key")
  19. os.Setenv("ETCD_BIND_ADDR", "127.0.0.1:4003")
  20. os.Setenv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002")
  21. os.Setenv("ETCD_PEERS_FILE", "/tmp/peers")
  22. os.Setenv("ETCD_MAX_CLUSTER_SIZE", "10")
  23. os.Setenv("ETCD_MAX_RESULT_BUFFER", "512")
  24. os.Setenv("ETCD_MAX_RETRY_ATTEMPTS", "5")
  25. os.Setenv("ETCD_NAME", "test-name")
  26. os.Setenv("ETCD_SNAPSHOT", "true")
  27. os.Setenv("ETCD_VERBOSE", "1")
  28. os.Setenv("ETCD_VERY_VERBOSE", "yes")
  29. os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:7002")
  30. os.Setenv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca")
  31. os.Setenv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert")
  32. os.Setenv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key")
  33. os.Setenv("ETCD_PEER_BIND_ADDR", "127.0.0.1:7003")
  34. os.Setenv("ETCD_CLUSTER_ACTIVE_SIZE", "5")
  35. os.Setenv("ETCD_CLUSTER_REMOVE_DELAY", "100")
  36. os.Setenv("ETCD_CLUSTER_SYNC_INTERVAL", "10")
  37. c := New()
  38. c.LoadEnv()
  39. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  40. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  41. assert.Equal(t, c.CorsOrigins, []string{"localhost:4001", "localhost:4002"}, "")
  42. assert.Equal(t, c.DataDir, "/tmp/data", "")
  43. assert.Equal(t, c.Discovery, "http://example.com/foobar", "")
  44. assert.Equal(t, c.HTTPReadTimeout, 2.34, "")
  45. assert.Equal(t, c.HTTPWriteTimeout, 1.23, "")
  46. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  47. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  48. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  49. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  50. assert.Equal(t, c.MaxResultBuffer, 512, "")
  51. assert.Equal(t, c.MaxRetryAttempts, 5, "")
  52. assert.Equal(t, c.Name, "test-name", "")
  53. assert.Equal(t, c.Snapshot, true, "")
  54. assert.Equal(t, c.Verbose, true, "")
  55. assert.Equal(t, c.VeryVerbose, true, "")
  56. assert.Equal(t, c.Peer.Addr, "127.0.0.1:7002", "")
  57. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  58. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  59. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  60. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:7003", "")
  61. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  62. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  63. assert.Equal(t, c.Cluster.SyncInterval, 10.0, "")
  64. // Clear this as it will mess up other tests
  65. os.Setenv("ETCD_DISCOVERY", "")
  66. }
  67. // Ensures that the "help" flag can be parsed.
  68. func TestConfigHelpFlag(t *testing.T) {
  69. c := New()
  70. assert.Nil(t, c.LoadFlags([]string{"-help"}), "")
  71. assert.True(t, c.ShowHelp)
  72. }
  73. // Ensures that the abbreviated "help" flag can be parsed.
  74. func TestConfigAbbreviatedHelpFlag(t *testing.T) {
  75. c := New()
  76. assert.Nil(t, c.LoadFlags([]string{"-h"}), "")
  77. assert.True(t, c.ShowHelp)
  78. }
  79. // Ensures that the "version" flag can be parsed.
  80. func TestConfigVersionFlag(t *testing.T) {
  81. c := New()
  82. assert.Nil(t, c.LoadFlags([]string{"-version"}), "")
  83. assert.True(t, c.ShowVersion)
  84. }
  85. // Ensures that the "force config" flag can be parsed.
  86. func TestConfigForceFlag(t *testing.T) {
  87. c := New()
  88. assert.Nil(t, c.LoadFlags([]string{"-force"}), "")
  89. assert.True(t, c.Force)
  90. }
  91. // Ensures that the abbreviated "force config" flag can be parsed.
  92. func TestConfigAbbreviatedForceFlag(t *testing.T) {
  93. c := New()
  94. assert.Nil(t, c.LoadFlags([]string{"-f"}), "")
  95. assert.True(t, c.Force)
  96. }
  97. // Ensures that the advertised url can be parsed from the environment.
  98. func TestConfigAddrEnv(t *testing.T) {
  99. withEnv("ETCD_ADDR", "127.0.0.1:4002", func(c *Config) {
  100. assert.Nil(t, c.LoadEnv(), "")
  101. assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
  102. })
  103. }
  104. // Ensures that the advertised flag can be parsed.
  105. func TestConfigAddrFlag(t *testing.T) {
  106. c := New()
  107. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4002"}), "")
  108. assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
  109. }
  110. // Ensures that the CA file can be parsed from the environment.
  111. func TestConfigCAFileEnv(t *testing.T) {
  112. withEnv("ETCD_CA_FILE", "/tmp/file.ca", func(c *Config) {
  113. assert.Nil(t, c.LoadEnv(), "")
  114. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  115. })
  116. }
  117. // Ensures that the CA file flag can be parsed.
  118. func TestConfigCAFileFlag(t *testing.T) {
  119. c := New()
  120. assert.Nil(t, c.LoadFlags([]string{"-ca-file", "/tmp/file.ca"}), "")
  121. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  122. }
  123. // Ensures that the CA file can be parsed from the environment.
  124. func TestConfigCertFileEnv(t *testing.T) {
  125. withEnv("ETCD_CERT_FILE", "/tmp/file.cert", func(c *Config) {
  126. assert.Nil(t, c.LoadEnv(), "")
  127. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  128. })
  129. }
  130. // Ensures that the Cert file flag can be parsed.
  131. func TestConfigCertFileFlag(t *testing.T) {
  132. c := New()
  133. assert.Nil(t, c.LoadFlags([]string{"-cert-file", "/tmp/file.cert"}), "")
  134. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  135. }
  136. // Ensures that the Key file can be parsed from the environment.
  137. func TestConfigKeyFileEnv(t *testing.T) {
  138. withEnv("ETCD_KEY_FILE", "/tmp/file.key", func(c *Config) {
  139. assert.Nil(t, c.LoadEnv(), "")
  140. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  141. })
  142. }
  143. // Ensures that the Key file flag can be parsed.
  144. func TestConfigKeyFileFlag(t *testing.T) {
  145. c := New()
  146. assert.Nil(t, c.LoadFlags([]string{"-key-file", "/tmp/file.key"}), "")
  147. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  148. }
  149. // Ensures that the Listen Host can be parsed from the environment.
  150. func TestConfigBindAddrEnv(t *testing.T) {
  151. withEnv("ETCD_BIND_ADDR", "127.0.0.1:4003", func(c *Config) {
  152. assert.Nil(t, c.LoadEnv(), "")
  153. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  154. })
  155. }
  156. // Ensures that the Listen Host file flag can be parsed.
  157. func TestConfigBindAddrFlag(t *testing.T) {
  158. c := New()
  159. assert.Nil(t, c.LoadFlags([]string{"-bind-addr", "127.0.0.1:4003"}), "")
  160. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  161. }
  162. // Ensures that the Listen Host port overrides the advertised port
  163. func TestConfigBindAddrOverride(t *testing.T) {
  164. c := New()
  165. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1:4010"}), "")
  166. assert.Nil(t, c.Sanitize())
  167. assert.Equal(t, c.BindAddr, "127.0.0.1:4010", "")
  168. }
  169. // Ensures that the Listen Host port overrides the advertised port
  170. func TestConfigBindIPv6AddrOverride(t *testing.T) {
  171. c := New()
  172. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1]:4009", "-bind-addr", "[::1]:4010"}), "")
  173. assert.Nil(t, c.Sanitize())
  174. assert.Equal(t, c.BindAddr, "[::1]:4010", "")
  175. }
  176. // Ensures that the Listen Host port overrides the advertised port
  177. func TestConfigBindIPv6WithZoneAddrOverride(t *testing.T) {
  178. c := New()
  179. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%25lo]:4009", "-bind-addr", "[::1%25lo]:4010"}), "")
  180. assert.Nil(t, c.Sanitize())
  181. assert.Equal(t, c.BindAddr, "[::1%25lo]:4010", "")
  182. }
  183. // Ensures that the Listen Host inherits its port from the advertised addr
  184. func TestConfigBindAddrInheritPort(t *testing.T) {
  185. c := New()
  186. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1"}), "")
  187. assert.Nil(t, c.Sanitize())
  188. assert.Equal(t, c.BindAddr, "127.0.0.1:4009", "")
  189. }
  190. // Ensures that the Listen Host inherits its port from the advertised addr
  191. func TestConfigBindIPv6AddrInheritPort(t *testing.T) {
  192. c := New()
  193. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1]:4009", "-bind-addr", "::1"}), "")
  194. assert.Nil(t, c.Sanitize())
  195. assert.Equal(t, c.BindAddr, "[::1]:4009", "")
  196. }
  197. // Ensures that the Listen Host inherits its port from the advertised addr
  198. func TestConfigBindIPv6WithZoneAddrInheritPort(t *testing.T) {
  199. c := New()
  200. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%25lo]:4009", "-bind-addr", "::1%25lo"}), "")
  201. assert.Nil(t, c.Sanitize())
  202. assert.Equal(t, c.BindAddr, "[::1%25lo]:4009", "")
  203. }
  204. // Ensures that a port only argument errors out
  205. func TestConfigBindAddrErrorOnNoHost(t *testing.T) {
  206. c := New()
  207. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", ":4010"}), "")
  208. assert.Error(t, c.Sanitize())
  209. }
  210. // Ensures that a bad IPv6 address will raise an error
  211. func TestConfigBindAddrErrorOnBadIPv6Addr(t *testing.T) {
  212. c := New()
  213. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%lo]:4009"}), "")
  214. assert.Error(t, c.Sanitize())
  215. }
  216. // Ensures that the peers can be parsed from the environment.
  217. func TestConfigPeersEnv(t *testing.T) {
  218. withEnv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002", func(c *Config) {
  219. assert.Nil(t, c.LoadEnv(), "")
  220. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  221. })
  222. }
  223. // Ensures that the Peers flag can be parsed.
  224. func TestConfigPeersFlag(t *testing.T) {
  225. c := New()
  226. assert.Nil(t, c.LoadFlags([]string{"-peers", "coreos.com:4001,coreos.com:4002"}), "")
  227. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  228. }
  229. // Ensures that the Peers File can be parsed from the environment.
  230. func TestConfigPeersFileEnv(t *testing.T) {
  231. withEnv("ETCD_PEERS_FILE", "/tmp/peers", func(c *Config) {
  232. assert.Nil(t, c.LoadEnv(), "")
  233. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  234. })
  235. }
  236. // Ensures that the Peers File flag can be parsed.
  237. func TestConfigPeersFileFlag(t *testing.T) {
  238. c := New()
  239. assert.Nil(t, c.LoadFlags([]string{"-peers-file", "/tmp/peers"}), "")
  240. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  241. }
  242. // Ensures that the Max Result Buffer can be parsed from the environment.
  243. func TestConfigMaxResultBufferEnv(t *testing.T) {
  244. withEnv("ETCD_MAX_RESULT_BUFFER", "512", func(c *Config) {
  245. assert.Nil(t, c.LoadEnv(), "")
  246. assert.Equal(t, c.MaxResultBuffer, 512, "")
  247. })
  248. }
  249. // Ensures that the Max Result Buffer flag can be parsed.
  250. func TestConfigMaxResultBufferFlag(t *testing.T) {
  251. c := New()
  252. assert.Nil(t, c.LoadFlags([]string{"-max-result-buffer", "512"}), "")
  253. assert.Equal(t, c.MaxResultBuffer, 512, "")
  254. }
  255. // Ensures that the Max Retry Attempts can be parsed from the environment.
  256. func TestConfigMaxRetryAttemptsEnv(t *testing.T) {
  257. withEnv("ETCD_MAX_RETRY_ATTEMPTS", "10", func(c *Config) {
  258. assert.Nil(t, c.LoadEnv(), "")
  259. assert.Equal(t, c.MaxRetryAttempts, 10, "")
  260. })
  261. }
  262. // Ensures that the Max Retry Attempts flag can be parsed.
  263. func TestConfigMaxRetryAttemptsFlag(t *testing.T) {
  264. c := New()
  265. assert.Nil(t, c.LoadFlags([]string{"-max-retry-attempts", "10"}), "")
  266. assert.Equal(t, c.MaxRetryAttempts, 10, "")
  267. }
  268. // Ensures that the Name can be parsed from the environment.
  269. func TestConfigNameEnv(t *testing.T) {
  270. withEnv("ETCD_NAME", "test-name", func(c *Config) {
  271. assert.Nil(t, c.LoadEnv(), "")
  272. assert.Equal(t, c.Name, "test-name", "")
  273. })
  274. }
  275. // Ensures that the Name flag can be parsed.
  276. func TestConfigNameFlag(t *testing.T) {
  277. c := New()
  278. assert.Nil(t, c.LoadFlags([]string{"-name", "test-name"}), "")
  279. assert.Equal(t, c.Name, "test-name", "")
  280. }
  281. // Ensures that a Name gets guessed if not specified
  282. func TestConfigNameGuess(t *testing.T) {
  283. c := New()
  284. assert.Nil(t, c.LoadFlags([]string{}), "")
  285. assert.Nil(t, c.Sanitize())
  286. name, _ := os.Hostname()
  287. assert.Equal(t, c.Name, name, "")
  288. }
  289. // Ensures that a DataDir gets guessed if not specified
  290. func TestConfigDataDirGuess(t *testing.T) {
  291. c := New()
  292. assert.Nil(t, c.LoadFlags([]string{}), "")
  293. assert.Nil(t, c.Sanitize())
  294. name, _ := os.Hostname()
  295. assert.Equal(t, c.DataDir, name+".etcd", "")
  296. }
  297. // Ensures that Snapshot can be parsed from the environment.
  298. func TestConfigSnapshotEnv(t *testing.T) {
  299. withEnv("ETCD_SNAPSHOT", "1", func(c *Config) {
  300. assert.Nil(t, c.LoadEnv(), "")
  301. assert.Equal(t, c.Snapshot, true, "")
  302. })
  303. }
  304. // Ensures that the Snapshot flag can be parsed.
  305. func TestConfigSnapshotFlag(t *testing.T) {
  306. c := New()
  307. assert.Nil(t, c.LoadFlags([]string{"-snapshot"}), "")
  308. assert.Equal(t, c.Snapshot, true, "")
  309. }
  310. // Ensures that Verbose can be parsed from the environment.
  311. func TestConfigVerboseEnv(t *testing.T) {
  312. withEnv("ETCD_VERBOSE", "true", func(c *Config) {
  313. assert.Nil(t, c.LoadEnv(), "")
  314. assert.Equal(t, c.Verbose, true, "")
  315. })
  316. }
  317. // Ensures that the Verbose flag can be parsed.
  318. func TestConfigVerboseFlag(t *testing.T) {
  319. c := New()
  320. assert.Nil(t, c.LoadFlags([]string{"-v"}), "")
  321. assert.Equal(t, c.Verbose, true, "")
  322. }
  323. // Ensures that Very Verbose can be parsed from the environment.
  324. func TestConfigVeryVerboseEnv(t *testing.T) {
  325. withEnv("ETCD_VERY_VERBOSE", "true", func(c *Config) {
  326. assert.Nil(t, c.LoadEnv(), "")
  327. assert.Equal(t, c.VeryVerbose, true, "")
  328. })
  329. }
  330. // Ensures that the Very Verbose flag can be parsed.
  331. func TestConfigVeryVerboseFlag(t *testing.T) {
  332. c := New()
  333. assert.Nil(t, c.LoadFlags([]string{"-vv"}), "")
  334. assert.Equal(t, c.VeryVerbose, true, "")
  335. }
  336. // Ensures that the Peer Advertised URL can be parsed from the environment.
  337. func TestConfigPeerAddrEnv(t *testing.T) {
  338. withEnv("ETCD_PEER_ADDR", "localhost:7002", func(c *Config) {
  339. assert.Nil(t, c.LoadEnv(), "")
  340. assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
  341. })
  342. }
  343. // Ensures that the Peer Advertised URL flag can be parsed.
  344. func TestConfigPeerAddrFlag(t *testing.T) {
  345. c := New()
  346. assert.Nil(t, c.LoadFlags([]string{"-peer-addr", "localhost:7002"}), "")
  347. assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
  348. }
  349. // Ensures that the Peer CA File can be parsed from the environment.
  350. func TestConfigPeerCAFileEnv(t *testing.T) {
  351. withEnv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca", func(c *Config) {
  352. assert.Nil(t, c.LoadEnv(), "")
  353. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  354. })
  355. }
  356. // Ensures that the Peer CA file flag can be parsed.
  357. func TestConfigPeerCAFileFlag(t *testing.T) {
  358. c := New()
  359. assert.Nil(t, c.LoadFlags([]string{"-peer-ca-file", "/tmp/peer/file.ca"}), "")
  360. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  361. }
  362. // Ensures that the Peer Cert File can be parsed from the environment.
  363. func TestConfigPeerCertFileEnv(t *testing.T) {
  364. withEnv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert", func(c *Config) {
  365. assert.Nil(t, c.LoadEnv(), "")
  366. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  367. })
  368. }
  369. // Ensures that the Cert file flag can be parsed.
  370. func TestConfigPeerCertFileFlag(t *testing.T) {
  371. c := New()
  372. assert.Nil(t, c.LoadFlags([]string{"-peer-cert-file", "/tmp/peer/file.cert"}), "")
  373. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  374. }
  375. // Ensures that the Peer Key File can be parsed from the environment.
  376. func TestConfigPeerKeyFileEnv(t *testing.T) {
  377. withEnv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key", func(c *Config) {
  378. assert.Nil(t, c.LoadEnv(), "")
  379. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  380. })
  381. }
  382. // Ensures that the Peer Key file flag can be parsed.
  383. func TestConfigPeerKeyFileFlag(t *testing.T) {
  384. c := New()
  385. assert.Nil(t, c.LoadFlags([]string{"-peer-key-file", "/tmp/peer/file.key"}), "")
  386. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  387. }
  388. // Ensures that the Peer Listen Host can be parsed from the environment.
  389. func TestConfigPeerBindAddrEnv(t *testing.T) {
  390. withEnv("ETCD_PEER_BIND_ADDR", "localhost:7004", func(c *Config) {
  391. assert.Nil(t, c.LoadEnv(), "")
  392. assert.Equal(t, c.Peer.BindAddr, "localhost:7004", "")
  393. })
  394. }
  395. // Ensures that a bad flag returns an error.
  396. func TestConfigBadFlag(t *testing.T) {
  397. c := New()
  398. err := c.LoadFlags([]string{"-no-such-flag"})
  399. assert.Error(t, err)
  400. assert.Equal(t, err.Error(), `flag provided but not defined: -no-such-flag`)
  401. }
  402. // Ensures that the Peer Listen Host file flag can be parsed.
  403. func TestConfigPeerBindAddrFlag(t *testing.T) {
  404. c := New()
  405. assert.Nil(t, c.LoadFlags([]string{"-peer-bind-addr", "127.0.0.1:4003"}), "")
  406. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "")
  407. }
  408. // Ensures that the cluster active size can be parsed from the environment.
  409. func TestConfigClusterActiveSizeEnv(t *testing.T) {
  410. withEnv("ETCD_CLUSTER_ACTIVE_SIZE", "5", func(c *Config) {
  411. assert.Nil(t, c.LoadEnv(), "")
  412. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  413. })
  414. }
  415. // Ensures that the cluster active size flag can be parsed.
  416. func TestConfigClusterActiveSizeFlag(t *testing.T) {
  417. c := New()
  418. assert.Nil(t, c.LoadFlags([]string{"-cluster-active-size", "5"}), "")
  419. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  420. }
  421. // Ensures that the cluster remove delay can be parsed from the environment.
  422. func TestConfigClusterRemoveDelayEnv(t *testing.T) {
  423. withEnv("ETCD_CLUSTER_REMOVE_DELAY", "100", func(c *Config) {
  424. assert.Nil(t, c.LoadEnv(), "")
  425. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  426. })
  427. }
  428. // Ensures that the cluster remove delay flag can be parsed.
  429. func TestConfigClusterRemoveDelayFlag(t *testing.T) {
  430. c := New()
  431. assert.Nil(t, c.LoadFlags([]string{"-cluster-remove-delay", "100"}), "")
  432. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  433. }
  434. func TestConfigClusterSyncIntervalFlag(t *testing.T) {
  435. c := New()
  436. assert.Nil(t, c.LoadFlags([]string{"-http-read-timeout", "2.34"}), "")
  437. assert.Equal(t, c.HTTPReadTimeout, 2.34, "")
  438. assert.Nil(t, c.LoadFlags([]string{"-http-write-timeout", "1.23"}), "")
  439. assert.Equal(t, c.HTTPWriteTimeout, 1.23, "")
  440. }
  441. // Ensures that a custom config field is overridden by an environment variable.
  442. func TestConfigEnvVarOverrideCustomConfig(t *testing.T) {
  443. os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:8000")
  444. defer os.Setenv("ETCD_PEER_ADDR", "")
  445. custom := `[peer]` + "\n" + `advertised_url = "127.0.0.1:9000"`
  446. withTempFile(custom, func(path string) {
  447. c := New()
  448. c.SystemPath = ""
  449. assert.Nil(t, c.Load([]string{"-config", path}), "")
  450. assert.Equal(t, c.Peer.Addr, "127.0.0.1:8000", "")
  451. })
  452. }
  453. // Ensures that an environment variable field is overridden by a command line argument.
  454. func TestConfigCLIArgsOverrideEnvVar(t *testing.T) {
  455. os.Setenv("ETCD_ADDR", "127.0.0.1:1000")
  456. defer os.Setenv("ETCD_ADDR", "")
  457. c := New()
  458. c.SystemPath = ""
  459. assert.Nil(t, c.Load([]string{"-addr", "127.0.0.1:2000"}), "")
  460. assert.Equal(t, c.Addr, "127.0.0.1:2000", "")
  461. }
  462. //--------------------------------------
  463. // Helpers
  464. //--------------------------------------
  465. // Sets up the environment with a given environment variable set.
  466. func withEnv(key, value string, f func(c *Config)) {
  467. os.Setenv(key, value)
  468. defer os.Setenv(key, "")
  469. c := New()
  470. f(c)
  471. }
  472. // Creates a temp file and calls a function with the context.
  473. func withTempFile(content string, fn func(string)) {
  474. f, _ := ioutil.TempFile("", "")
  475. f.WriteString(content)
  476. f.Close()
  477. defer os.Remove(f.Name())
  478. fn(f.Name())
  479. }
  480. // Captures STDOUT & STDERR and returns the output as strings.
  481. func capture(fn func()) (string, string) {
  482. // Create temp files.
  483. tmpout, _ := ioutil.TempFile("", "")
  484. defer os.Remove(tmpout.Name())
  485. tmperr, _ := ioutil.TempFile("", "")
  486. defer os.Remove(tmperr.Name())
  487. stdout, stderr := os.Stdout, os.Stderr
  488. os.Stdout, os.Stderr = tmpout, tmperr
  489. // Execute function argument and then reassign stdout/stderr.
  490. fn()
  491. os.Stdout, os.Stderr = stdout, stderr
  492. // Close temp files and read them.
  493. tmpout.Close()
  494. bout, _ := ioutil.ReadFile(tmpout.Name())
  495. tmperr.Close()
  496. berr, _ := ioutil.ReadFile(tmperr.Name())
  497. return string(bout), string(berr)
  498. }