config_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. package config
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "testing"
  6. "github.com/coreos/etcd/third_party/github.com/BurntSushi/toml"
  7. "github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
  8. )
  9. // Ensures that a configuration can be deserialized from TOML.
  10. func TestConfigTOML(t *testing.T) {
  11. content := `
  12. addr = "127.0.0.1:4002"
  13. ca_file = "/tmp/file.ca"
  14. cert_file = "/tmp/file.cert"
  15. cors = ["*"]
  16. cpu_profile_file = "XXX"
  17. data_dir = "/tmp/data"
  18. discovery = "http://example.com/foobar"
  19. key_file = "/tmp/file.key"
  20. bind_addr = "127.0.0.1:4003"
  21. peers = ["coreos.com:4001", "coreos.com:4002"]
  22. peers_file = "/tmp/peers"
  23. max_cluster_size = 10
  24. max_result_buffer = 512
  25. max_retry_attempts = 5
  26. name = "test-name"
  27. http_read_timeout = 2.34
  28. snapshot = true
  29. verbose = true
  30. very_verbose = true
  31. http_write_timeout = 1.23
  32. [peer]
  33. addr = "127.0.0.1:7002"
  34. ca_file = "/tmp/peer/file.ca"
  35. cert_file = "/tmp/peer/file.cert"
  36. key_file = "/tmp/peer/file.key"
  37. bind_addr = "127.0.0.1:7003"
  38. [cluster]
  39. active_size = 5
  40. remove_delay = 100.0
  41. sync_interval = 10.0
  42. `
  43. c := New()
  44. _, err := toml.Decode(content, &c)
  45. assert.Nil(t, err, "")
  46. assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
  47. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  48. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  49. assert.Equal(t, c.CorsOrigins, []string{"*"}, "")
  50. assert.Equal(t, c.DataDir, "/tmp/data", "")
  51. assert.Equal(t, c.Discovery, "http://example.com/foobar", "")
  52. assert.Equal(t, c.HTTPReadTimeout, 2.34, "")
  53. assert.Equal(t, c.HTTPWriteTimeout, 1.23, "")
  54. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  55. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  56. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  57. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  58. assert.Equal(t, c.MaxResultBuffer, 512, "")
  59. assert.Equal(t, c.MaxRetryAttempts, 5, "")
  60. assert.Equal(t, c.Name, "test-name", "")
  61. assert.Equal(t, c.Snapshot, true, "")
  62. assert.Equal(t, c.Verbose, true, "")
  63. assert.Equal(t, c.VeryVerbose, true, "")
  64. assert.Equal(t, c.Peer.Addr, "127.0.0.1:7002", "")
  65. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  66. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  67. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  68. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:7003", "")
  69. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  70. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  71. assert.Equal(t, c.Cluster.SyncInterval, 10.0, "")
  72. }
  73. // Ensures that a configuration can be retrieved from environment variables.
  74. func TestConfigEnv(t *testing.T) {
  75. os.Setenv("ETCD_CA_FILE", "/tmp/file.ca")
  76. os.Setenv("ETCD_CERT_FILE", "/tmp/file.cert")
  77. os.Setenv("ETCD_CPU_PROFILE_FILE", "XXX")
  78. os.Setenv("ETCD_CORS", "localhost:4001,localhost:4002")
  79. os.Setenv("ETCD_DATA_DIR", "/tmp/data")
  80. os.Setenv("ETCD_DISCOVERY", "http://example.com/foobar")
  81. os.Setenv("ETCD_HTTP_READ_TIMEOUT", "2.34")
  82. os.Setenv("ETCD_HTTP_WRITE_TIMEOUT", "1.23")
  83. os.Setenv("ETCD_KEY_FILE", "/tmp/file.key")
  84. os.Setenv("ETCD_BIND_ADDR", "127.0.0.1:4003")
  85. os.Setenv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002")
  86. os.Setenv("ETCD_PEERS_FILE", "/tmp/peers")
  87. os.Setenv("ETCD_MAX_CLUSTER_SIZE", "10")
  88. os.Setenv("ETCD_MAX_RESULT_BUFFER", "512")
  89. os.Setenv("ETCD_MAX_RETRY_ATTEMPTS", "5")
  90. os.Setenv("ETCD_NAME", "test-name")
  91. os.Setenv("ETCD_SNAPSHOT", "true")
  92. os.Setenv("ETCD_VERBOSE", "1")
  93. os.Setenv("ETCD_VERY_VERBOSE", "yes")
  94. os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:7002")
  95. os.Setenv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca")
  96. os.Setenv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert")
  97. os.Setenv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key")
  98. os.Setenv("ETCD_PEER_BIND_ADDR", "127.0.0.1:7003")
  99. os.Setenv("ETCD_CLUSTER_ACTIVE_SIZE", "5")
  100. os.Setenv("ETCD_CLUSTER_REMOVE_DELAY", "100")
  101. os.Setenv("ETCD_CLUSTER_SYNC_INTERVAL", "10")
  102. c := New()
  103. c.LoadEnv()
  104. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  105. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  106. assert.Equal(t, c.CorsOrigins, []string{"localhost:4001", "localhost:4002"}, "")
  107. assert.Equal(t, c.DataDir, "/tmp/data", "")
  108. assert.Equal(t, c.Discovery, "http://example.com/foobar", "")
  109. assert.Equal(t, c.HTTPReadTimeout, 2.34, "")
  110. assert.Equal(t, c.HTTPWriteTimeout, 1.23, "")
  111. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  112. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  113. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  114. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  115. assert.Equal(t, c.MaxResultBuffer, 512, "")
  116. assert.Equal(t, c.MaxRetryAttempts, 5, "")
  117. assert.Equal(t, c.Name, "test-name", "")
  118. assert.Equal(t, c.Snapshot, true, "")
  119. assert.Equal(t, c.Verbose, true, "")
  120. assert.Equal(t, c.VeryVerbose, true, "")
  121. assert.Equal(t, c.Peer.Addr, "127.0.0.1:7002", "")
  122. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  123. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  124. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  125. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:7003", "")
  126. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  127. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  128. assert.Equal(t, c.Cluster.SyncInterval, 10.0, "")
  129. // Clear this as it will mess up other tests
  130. os.Setenv("ETCD_DISCOVERY", "")
  131. }
  132. // Ensures that the "help" flag can be parsed.
  133. func TestConfigHelpFlag(t *testing.T) {
  134. c := New()
  135. assert.Nil(t, c.LoadFlags([]string{"-help"}), "")
  136. assert.True(t, c.ShowHelp)
  137. }
  138. // Ensures that the abbreviated "help" flag can be parsed.
  139. func TestConfigAbbreviatedHelpFlag(t *testing.T) {
  140. c := New()
  141. assert.Nil(t, c.LoadFlags([]string{"-h"}), "")
  142. assert.True(t, c.ShowHelp)
  143. }
  144. // Ensures that the "version" flag can be parsed.
  145. func TestConfigVersionFlag(t *testing.T) {
  146. c := New()
  147. assert.Nil(t, c.LoadFlags([]string{"-version"}), "")
  148. assert.True(t, c.ShowVersion)
  149. }
  150. // Ensures that the "force config" flag can be parsed.
  151. func TestConfigForceFlag(t *testing.T) {
  152. c := New()
  153. assert.Nil(t, c.LoadFlags([]string{"-force"}), "")
  154. assert.True(t, c.Force)
  155. }
  156. // Ensures that the abbreviated "force config" flag can be parsed.
  157. func TestConfigAbbreviatedForceFlag(t *testing.T) {
  158. c := New()
  159. assert.Nil(t, c.LoadFlags([]string{"-f"}), "")
  160. assert.True(t, c.Force)
  161. }
  162. // Ensures that the advertised url can be parsed from the environment.
  163. func TestConfigAddrEnv(t *testing.T) {
  164. withEnv("ETCD_ADDR", "127.0.0.1:4002", func(c *Config) {
  165. assert.Nil(t, c.LoadEnv(), "")
  166. assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
  167. })
  168. }
  169. // Ensures that the advertised flag can be parsed.
  170. func TestConfigAddrFlag(t *testing.T) {
  171. c := New()
  172. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4002"}), "")
  173. assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
  174. }
  175. // Ensures that the CA file can be parsed from the environment.
  176. func TestConfigCAFileEnv(t *testing.T) {
  177. withEnv("ETCD_CA_FILE", "/tmp/file.ca", func(c *Config) {
  178. assert.Nil(t, c.LoadEnv(), "")
  179. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  180. })
  181. }
  182. // Ensures that the CA file flag can be parsed.
  183. func TestConfigCAFileFlag(t *testing.T) {
  184. c := New()
  185. assert.Nil(t, c.LoadFlags([]string{"-ca-file", "/tmp/file.ca"}), "")
  186. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  187. }
  188. // Ensures that the CA file can be parsed from the environment.
  189. func TestConfigCertFileEnv(t *testing.T) {
  190. withEnv("ETCD_CERT_FILE", "/tmp/file.cert", func(c *Config) {
  191. assert.Nil(t, c.LoadEnv(), "")
  192. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  193. })
  194. }
  195. // Ensures that the Cert file flag can be parsed.
  196. func TestConfigCertFileFlag(t *testing.T) {
  197. c := New()
  198. assert.Nil(t, c.LoadFlags([]string{"-cert-file", "/tmp/file.cert"}), "")
  199. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  200. }
  201. // Ensures that the Key file can be parsed from the environment.
  202. func TestConfigKeyFileEnv(t *testing.T) {
  203. withEnv("ETCD_KEY_FILE", "/tmp/file.key", func(c *Config) {
  204. assert.Nil(t, c.LoadEnv(), "")
  205. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  206. })
  207. }
  208. // Ensures that the Key file flag can be parsed.
  209. func TestConfigKeyFileFlag(t *testing.T) {
  210. c := New()
  211. assert.Nil(t, c.LoadFlags([]string{"-key-file", "/tmp/file.key"}), "")
  212. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  213. }
  214. // Ensures that the Listen Host can be parsed from the environment.
  215. func TestConfigBindAddrEnv(t *testing.T) {
  216. withEnv("ETCD_BIND_ADDR", "127.0.0.1:4003", func(c *Config) {
  217. assert.Nil(t, c.LoadEnv(), "")
  218. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  219. })
  220. }
  221. // Ensures that the Listen Host file flag can be parsed.
  222. func TestConfigBindAddrFlag(t *testing.T) {
  223. c := New()
  224. assert.Nil(t, c.LoadFlags([]string{"-bind-addr", "127.0.0.1:4003"}), "")
  225. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  226. }
  227. // Ensures that the Listen Host port overrides the advertised port
  228. func TestConfigBindAddrOverride(t *testing.T) {
  229. c := New()
  230. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1:4010"}), "")
  231. assert.Nil(t, c.Sanitize())
  232. assert.Equal(t, c.BindAddr, "127.0.0.1:4010", "")
  233. }
  234. // Ensures that the Listen Host port overrides the advertised port
  235. func TestConfigBindIPv6AddrOverride(t *testing.T) {
  236. c := New()
  237. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1]:4009", "-bind-addr", "[::1]:4010"}), "")
  238. assert.Nil(t, c.Sanitize())
  239. assert.Equal(t, c.BindAddr, "[::1]:4010", "")
  240. }
  241. // Ensures that the Listen Host port overrides the advertised port
  242. func TestConfigBindIPv6WithZoneAddrOverride(t *testing.T) {
  243. c := New()
  244. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%25lo]:4009", "-bind-addr", "[::1%25lo]:4010"}), "")
  245. assert.Nil(t, c.Sanitize())
  246. assert.Equal(t, c.BindAddr, "[::1%25lo]:4010", "")
  247. }
  248. // Ensures that the Listen Host inherits its port from the advertised addr
  249. func TestConfigBindAddrInheritPort(t *testing.T) {
  250. c := New()
  251. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1"}), "")
  252. assert.Nil(t, c.Sanitize())
  253. assert.Equal(t, c.BindAddr, "127.0.0.1:4009", "")
  254. }
  255. // Ensures that the Listen Host inherits its port from the advertised addr
  256. func TestConfigBindIPv6AddrInheritPort(t *testing.T) {
  257. c := New()
  258. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1]:4009", "-bind-addr", "::1"}), "")
  259. assert.Nil(t, c.Sanitize())
  260. assert.Equal(t, c.BindAddr, "[::1]:4009", "")
  261. }
  262. // Ensures that the Listen Host inherits its port from the advertised addr
  263. func TestConfigBindIPv6WithZoneAddrInheritPort(t *testing.T) {
  264. c := New()
  265. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%25lo]:4009", "-bind-addr", "::1%25lo"}), "")
  266. assert.Nil(t, c.Sanitize())
  267. assert.Equal(t, c.BindAddr, "[::1%25lo]:4009", "")
  268. }
  269. // Ensures that a port only argument errors out
  270. func TestConfigBindAddrErrorOnNoHost(t *testing.T) {
  271. c := New()
  272. assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", ":4010"}), "")
  273. assert.Error(t, c.Sanitize())
  274. }
  275. // Ensures that a bad IPv6 address will raise an error
  276. func TestConfigBindAddrErrorOnBadIPv6Addr(t *testing.T) {
  277. c := New()
  278. assert.Nil(t, c.LoadFlags([]string{"-addr", "[::1%lo]:4009"}), "")
  279. assert.Error(t, c.Sanitize())
  280. }
  281. // Ensures that the peers can be parsed from the environment.
  282. func TestConfigPeersEnv(t *testing.T) {
  283. withEnv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002", func(c *Config) {
  284. assert.Nil(t, c.LoadEnv(), "")
  285. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  286. })
  287. }
  288. // Ensures that the Peers flag can be parsed.
  289. func TestConfigPeersFlag(t *testing.T) {
  290. c := New()
  291. assert.Nil(t, c.LoadFlags([]string{"-peers", "coreos.com:4001,coreos.com:4002"}), "")
  292. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  293. }
  294. // Ensures that the Peers File can be parsed from the environment.
  295. func TestConfigPeersFileEnv(t *testing.T) {
  296. withEnv("ETCD_PEERS_FILE", "/tmp/peers", func(c *Config) {
  297. assert.Nil(t, c.LoadEnv(), "")
  298. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  299. })
  300. }
  301. // Ensures that the Peers File flag can be parsed.
  302. func TestConfigPeersFileFlag(t *testing.T) {
  303. c := New()
  304. assert.Nil(t, c.LoadFlags([]string{"-peers-file", "/tmp/peers"}), "")
  305. assert.Equal(t, c.PeersFile, "/tmp/peers", "")
  306. }
  307. // Ensures that the Max Result Buffer can be parsed from the environment.
  308. func TestConfigMaxResultBufferEnv(t *testing.T) {
  309. withEnv("ETCD_MAX_RESULT_BUFFER", "512", func(c *Config) {
  310. assert.Nil(t, c.LoadEnv(), "")
  311. assert.Equal(t, c.MaxResultBuffer, 512, "")
  312. })
  313. }
  314. // Ensures that the Max Result Buffer flag can be parsed.
  315. func TestConfigMaxResultBufferFlag(t *testing.T) {
  316. c := New()
  317. assert.Nil(t, c.LoadFlags([]string{"-max-result-buffer", "512"}), "")
  318. assert.Equal(t, c.MaxResultBuffer, 512, "")
  319. }
  320. // Ensures that the Max Retry Attempts can be parsed from the environment.
  321. func TestConfigMaxRetryAttemptsEnv(t *testing.T) {
  322. withEnv("ETCD_MAX_RETRY_ATTEMPTS", "10", func(c *Config) {
  323. assert.Nil(t, c.LoadEnv(), "")
  324. assert.Equal(t, c.MaxRetryAttempts, 10, "")
  325. })
  326. }
  327. // Ensures that the Max Retry Attempts flag can be parsed.
  328. func TestConfigMaxRetryAttemptsFlag(t *testing.T) {
  329. c := New()
  330. assert.Nil(t, c.LoadFlags([]string{"-max-retry-attempts", "10"}), "")
  331. assert.Equal(t, c.MaxRetryAttempts, 10, "")
  332. }
  333. // Ensures that the Name can be parsed from the environment.
  334. func TestConfigNameEnv(t *testing.T) {
  335. withEnv("ETCD_NAME", "test-name", func(c *Config) {
  336. assert.Nil(t, c.LoadEnv(), "")
  337. assert.Equal(t, c.Name, "test-name", "")
  338. })
  339. }
  340. // Ensures that the Name flag can be parsed.
  341. func TestConfigNameFlag(t *testing.T) {
  342. c := New()
  343. assert.Nil(t, c.LoadFlags([]string{"-name", "test-name"}), "")
  344. assert.Equal(t, c.Name, "test-name", "")
  345. }
  346. // Ensures that a Name gets guessed if not specified
  347. func TestConfigNameGuess(t *testing.T) {
  348. c := New()
  349. assert.Nil(t, c.LoadFlags([]string{}), "")
  350. assert.Nil(t, c.Sanitize())
  351. name, _ := os.Hostname()
  352. assert.Equal(t, c.Name, name, "")
  353. }
  354. // Ensures that a DataDir gets guessed if not specified
  355. func TestConfigDataDirGuess(t *testing.T) {
  356. c := New()
  357. assert.Nil(t, c.LoadFlags([]string{}), "")
  358. assert.Nil(t, c.Sanitize())
  359. name, _ := os.Hostname()
  360. assert.Equal(t, c.DataDir, name+".etcd", "")
  361. }
  362. // Ensures that Snapshot can be parsed from the environment.
  363. func TestConfigSnapshotEnv(t *testing.T) {
  364. withEnv("ETCD_SNAPSHOT", "1", func(c *Config) {
  365. assert.Nil(t, c.LoadEnv(), "")
  366. assert.Equal(t, c.Snapshot, true, "")
  367. })
  368. }
  369. // Ensures that the Snapshot flag can be parsed.
  370. func TestConfigSnapshotFlag(t *testing.T) {
  371. c := New()
  372. assert.Nil(t, c.LoadFlags([]string{"-snapshot"}), "")
  373. assert.Equal(t, c.Snapshot, true, "")
  374. }
  375. // Ensures that Verbose can be parsed from the environment.
  376. func TestConfigVerboseEnv(t *testing.T) {
  377. withEnv("ETCD_VERBOSE", "true", func(c *Config) {
  378. assert.Nil(t, c.LoadEnv(), "")
  379. assert.Equal(t, c.Verbose, true, "")
  380. })
  381. }
  382. // Ensures that the Verbose flag can be parsed.
  383. func TestConfigVerboseFlag(t *testing.T) {
  384. c := New()
  385. assert.Nil(t, c.LoadFlags([]string{"-v"}), "")
  386. assert.Equal(t, c.Verbose, true, "")
  387. }
  388. // Ensures that Very Verbose can be parsed from the environment.
  389. func TestConfigVeryVerboseEnv(t *testing.T) {
  390. withEnv("ETCD_VERY_VERBOSE", "true", func(c *Config) {
  391. assert.Nil(t, c.LoadEnv(), "")
  392. assert.Equal(t, c.VeryVerbose, true, "")
  393. })
  394. }
  395. // Ensures that the Very Verbose flag can be parsed.
  396. func TestConfigVeryVerboseFlag(t *testing.T) {
  397. c := New()
  398. assert.Nil(t, c.LoadFlags([]string{"-vv"}), "")
  399. assert.Equal(t, c.VeryVerbose, true, "")
  400. }
  401. // Ensures that the Peer Advertised URL can be parsed from the environment.
  402. func TestConfigPeerAddrEnv(t *testing.T) {
  403. withEnv("ETCD_PEER_ADDR", "localhost:7002", func(c *Config) {
  404. assert.Nil(t, c.LoadEnv(), "")
  405. assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
  406. })
  407. }
  408. // Ensures that the Peer Advertised URL flag can be parsed.
  409. func TestConfigPeerAddrFlag(t *testing.T) {
  410. c := New()
  411. assert.Nil(t, c.LoadFlags([]string{"-peer-addr", "localhost:7002"}), "")
  412. assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
  413. }
  414. // Ensures that the Peer CA File can be parsed from the environment.
  415. func TestConfigPeerCAFileEnv(t *testing.T) {
  416. withEnv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca", func(c *Config) {
  417. assert.Nil(t, c.LoadEnv(), "")
  418. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  419. })
  420. }
  421. // Ensures that the Peer CA file flag can be parsed.
  422. func TestConfigPeerCAFileFlag(t *testing.T) {
  423. c := New()
  424. assert.Nil(t, c.LoadFlags([]string{"-peer-ca-file", "/tmp/peer/file.ca"}), "")
  425. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  426. }
  427. // Ensures that the Peer Cert File can be parsed from the environment.
  428. func TestConfigPeerCertFileEnv(t *testing.T) {
  429. withEnv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert", func(c *Config) {
  430. assert.Nil(t, c.LoadEnv(), "")
  431. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  432. })
  433. }
  434. // Ensures that the Cert file flag can be parsed.
  435. func TestConfigPeerCertFileFlag(t *testing.T) {
  436. c := New()
  437. assert.Nil(t, c.LoadFlags([]string{"-peer-cert-file", "/tmp/peer/file.cert"}), "")
  438. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  439. }
  440. // Ensures that the Peer Key File can be parsed from the environment.
  441. func TestConfigPeerKeyFileEnv(t *testing.T) {
  442. withEnv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key", func(c *Config) {
  443. assert.Nil(t, c.LoadEnv(), "")
  444. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  445. })
  446. }
  447. // Ensures that the Peer Key file flag can be parsed.
  448. func TestConfigPeerKeyFileFlag(t *testing.T) {
  449. c := New()
  450. assert.Nil(t, c.LoadFlags([]string{"-peer-key-file", "/tmp/peer/file.key"}), "")
  451. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  452. }
  453. // Ensures that the Peer Listen Host can be parsed from the environment.
  454. func TestConfigPeerBindAddrEnv(t *testing.T) {
  455. withEnv("ETCD_PEER_BIND_ADDR", "localhost:7004", func(c *Config) {
  456. assert.Nil(t, c.LoadEnv(), "")
  457. assert.Equal(t, c.Peer.BindAddr, "localhost:7004", "")
  458. })
  459. }
  460. // Ensures that a bad flag returns an error.
  461. func TestConfigBadFlag(t *testing.T) {
  462. c := New()
  463. err := c.LoadFlags([]string{"-no-such-flag"})
  464. assert.Error(t, err)
  465. assert.Equal(t, err.Error(), `flag provided but not defined: -no-such-flag`)
  466. }
  467. // Ensures that the Peer Listen Host file flag can be parsed.
  468. func TestConfigPeerBindAddrFlag(t *testing.T) {
  469. c := New()
  470. assert.Nil(t, c.LoadFlags([]string{"-peer-bind-addr", "127.0.0.1:4003"}), "")
  471. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "")
  472. }
  473. // Ensures that the cluster active size can be parsed from the environment.
  474. func TestConfigClusterActiveSizeEnv(t *testing.T) {
  475. withEnv("ETCD_CLUSTER_ACTIVE_SIZE", "5", func(c *Config) {
  476. assert.Nil(t, c.LoadEnv(), "")
  477. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  478. })
  479. }
  480. // Ensures that the cluster active size flag can be parsed.
  481. func TestConfigClusterActiveSizeFlag(t *testing.T) {
  482. c := New()
  483. assert.Nil(t, c.LoadFlags([]string{"-cluster-active-size", "5"}), "")
  484. assert.Equal(t, c.Cluster.ActiveSize, 5, "")
  485. }
  486. // Ensures that the cluster remove delay can be parsed from the environment.
  487. func TestConfigClusterRemoveDelayEnv(t *testing.T) {
  488. withEnv("ETCD_CLUSTER_REMOVE_DELAY", "100", func(c *Config) {
  489. assert.Nil(t, c.LoadEnv(), "")
  490. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  491. })
  492. }
  493. // Ensures that the cluster remove delay flag can be parsed.
  494. func TestConfigClusterRemoveDelayFlag(t *testing.T) {
  495. c := New()
  496. assert.Nil(t, c.LoadFlags([]string{"-cluster-remove-delay", "100"}), "")
  497. assert.Equal(t, c.Cluster.RemoveDelay, 100.0, "")
  498. }
  499. func TestConfigClusterSyncIntervalFlag(t *testing.T) {
  500. c := New()
  501. assert.Nil(t, c.LoadFlags([]string{"-http-read-timeout", "2.34"}), "")
  502. assert.Equal(t, c.HTTPReadTimeout, 2.34, "")
  503. assert.Nil(t, c.LoadFlags([]string{"-http-write-timeout", "1.23"}), "")
  504. assert.Equal(t, c.HTTPWriteTimeout, 1.23, "")
  505. }
  506. // Ensures that a system config field is overridden by a custom config field.
  507. func TestConfigCustomConfigOverrideSystemConfig(t *testing.T) {
  508. system := `addr = "127.0.0.1:5000"`
  509. custom := `addr = "127.0.0.1:6000"`
  510. withTempFile(system, func(p1 string) {
  511. withTempFile(custom, func(p2 string) {
  512. c := New()
  513. c.SystemPath = p1
  514. assert.Nil(t, c.Load([]string{"-config", p2}), "")
  515. assert.Equal(t, c.Addr, "127.0.0.1:6000", "")
  516. })
  517. })
  518. }
  519. // Ensures that a custom config field is overridden by an environment variable.
  520. func TestConfigEnvVarOverrideCustomConfig(t *testing.T) {
  521. os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:8000")
  522. defer os.Setenv("ETCD_PEER_ADDR", "")
  523. custom := `[peer]` + "\n" + `advertised_url = "127.0.0.1:9000"`
  524. withTempFile(custom, func(path string) {
  525. c := New()
  526. c.SystemPath = ""
  527. assert.Nil(t, c.Load([]string{"-config", path}), "")
  528. assert.Equal(t, c.Peer.Addr, "127.0.0.1:8000", "")
  529. })
  530. }
  531. // Ensures that an environment variable field is overridden by a command line argument.
  532. func TestConfigCLIArgsOverrideEnvVar(t *testing.T) {
  533. os.Setenv("ETCD_ADDR", "127.0.0.1:1000")
  534. defer os.Setenv("ETCD_ADDR", "")
  535. c := New()
  536. c.SystemPath = ""
  537. assert.Nil(t, c.Load([]string{"-addr", "127.0.0.1:2000"}), "")
  538. assert.Equal(t, c.Addr, "127.0.0.1:2000", "")
  539. }
  540. //--------------------------------------
  541. // DEPRECATED (v1)
  542. //--------------------------------------
  543. func TestConfigDeprecatedAddrFlag(t *testing.T) {
  544. _, stderr := capture(func() {
  545. c := New()
  546. err := c.LoadFlags([]string{"-c", "127.0.0.1:4002"})
  547. assert.NoError(t, err)
  548. assert.Equal(t, c.Addr, "127.0.0.1:4002")
  549. })
  550. assert.Equal(t, stderr, "[deprecated] use -addr, not -c\n")
  551. }
  552. func TestConfigDeprecatedBindAddrFlag(t *testing.T) {
  553. _, stderr := capture(func() {
  554. c := New()
  555. err := c.LoadFlags([]string{"-cl", "127.0.0.1:4003"})
  556. assert.NoError(t, err)
  557. assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
  558. })
  559. assert.Equal(t, stderr, "[deprecated] use -bind-addr, not -cl\n", "")
  560. }
  561. func TestConfigDeprecatedCAFileFlag(t *testing.T) {
  562. _, stderr := capture(func() {
  563. c := New()
  564. err := c.LoadFlags([]string{"-clientCAFile", "/tmp/file.ca"})
  565. assert.NoError(t, err)
  566. assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
  567. })
  568. assert.Equal(t, stderr, "[deprecated] use -ca-file, not -clientCAFile\n", "")
  569. }
  570. func TestConfigDeprecatedCertFileFlag(t *testing.T) {
  571. _, stderr := capture(func() {
  572. c := New()
  573. err := c.LoadFlags([]string{"-clientCert", "/tmp/file.cert"})
  574. assert.NoError(t, err)
  575. assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
  576. })
  577. assert.Equal(t, stderr, "[deprecated] use -cert-file, not -clientCert\n", "")
  578. }
  579. func TestConfigDeprecatedKeyFileFlag(t *testing.T) {
  580. _, stderr := capture(func() {
  581. c := New()
  582. err := c.LoadFlags([]string{"-clientKey", "/tmp/file.key"})
  583. assert.NoError(t, err)
  584. assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
  585. })
  586. assert.Equal(t, stderr, "[deprecated] use -key-file, not -clientKey\n", "")
  587. }
  588. func TestConfigDeprecatedPeersFlag(t *testing.T) {
  589. _, stderr := capture(func() {
  590. c := New()
  591. err := c.LoadFlags([]string{"-C", "coreos.com:4001,coreos.com:4002"})
  592. assert.NoError(t, err)
  593. assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
  594. })
  595. assert.Equal(t, stderr, "[deprecated] use -peers, not -C\n", "")
  596. }
  597. func TestConfigDeprecatedPeersFileFlag(t *testing.T) {
  598. _, stderr := capture(func() {
  599. c := New()
  600. err := c.LoadFlags([]string{"-CF", "/tmp/machines"})
  601. assert.NoError(t, err)
  602. assert.Equal(t, c.PeersFile, "/tmp/machines", "")
  603. })
  604. assert.Equal(t, stderr, "[deprecated] use -peers-file, not -CF\n", "")
  605. }
  606. func TestConfigDeprecatedMaxRetryAttemptsFlag(t *testing.T) {
  607. _, stderr := capture(func() {
  608. c := New()
  609. err := c.LoadFlags([]string{"-r", "10"})
  610. assert.NoError(t, err)
  611. assert.Equal(t, c.MaxRetryAttempts, 10, "")
  612. })
  613. assert.Equal(t, stderr, "[deprecated] use -max-retry-attempts, not -r\n", "")
  614. }
  615. func TestConfigDeprecatedNameFlag(t *testing.T) {
  616. _, stderr := capture(func() {
  617. c := New()
  618. err := c.LoadFlags([]string{"-n", "test-name"})
  619. assert.NoError(t, err)
  620. assert.Equal(t, c.Name, "test-name", "")
  621. })
  622. assert.Equal(t, stderr, "[deprecated] use -name, not -n\n", "")
  623. }
  624. func TestConfigDeprecatedPeerAddrFlag(t *testing.T) {
  625. _, stderr := capture(func() {
  626. c := New()
  627. err := c.LoadFlags([]string{"-s", "localhost:7002"})
  628. assert.NoError(t, err)
  629. assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
  630. })
  631. assert.Equal(t, stderr, "[deprecated] use -peer-addr, not -s\n", "")
  632. }
  633. func TestConfigDeprecatedPeerBindAddrFlag(t *testing.T) {
  634. _, stderr := capture(func() {
  635. c := New()
  636. err := c.LoadFlags([]string{"-sl", "127.0.0.1:4003"})
  637. assert.NoError(t, err)
  638. assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "")
  639. })
  640. assert.Equal(t, stderr, "[deprecated] use -peer-bind-addr, not -sl\n", "")
  641. }
  642. func TestConfigDeprecatedPeerCAFileFlag(t *testing.T) {
  643. _, stderr := capture(func() {
  644. c := New()
  645. err := c.LoadFlags([]string{"-serverCAFile", "/tmp/peer/file.ca"})
  646. assert.NoError(t, err)
  647. assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
  648. })
  649. assert.Equal(t, stderr, "[deprecated] use -peer-ca-file, not -serverCAFile\n", "")
  650. }
  651. func TestConfigDeprecatedPeerCertFileFlag(t *testing.T) {
  652. _, stderr := capture(func() {
  653. c := New()
  654. err := c.LoadFlags([]string{"-serverCert", "/tmp/peer/file.cert"})
  655. assert.NoError(t, err)
  656. assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
  657. })
  658. assert.Equal(t, stderr, "[deprecated] use -peer-cert-file, not -serverCert\n", "")
  659. }
  660. func TestConfigDeprecatedPeerKeyFileFlag(t *testing.T) {
  661. _, stderr := capture(func() {
  662. c := New()
  663. err := c.LoadFlags([]string{"-serverKey", "/tmp/peer/file.key"})
  664. assert.NoError(t, err)
  665. assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
  666. })
  667. assert.Equal(t, stderr, "[deprecated] use -peer-key-file, not -serverKey\n", "")
  668. }
  669. //--------------------------------------
  670. // Helpers
  671. //--------------------------------------
  672. // Sets up the environment with a given environment variable set.
  673. func withEnv(key, value string, f func(c *Config)) {
  674. os.Setenv(key, value)
  675. defer os.Setenv(key, "")
  676. c := New()
  677. f(c)
  678. }
  679. // Creates a temp file and calls a function with the context.
  680. func withTempFile(content string, fn func(string)) {
  681. f, _ := ioutil.TempFile("", "")
  682. f.WriteString(content)
  683. f.Close()
  684. defer os.Remove(f.Name())
  685. fn(f.Name())
  686. }
  687. // Captures STDOUT & STDERR and returns the output as strings.
  688. func capture(fn func()) (string, string) {
  689. // Create temp files.
  690. tmpout, _ := ioutil.TempFile("", "")
  691. defer os.Remove(tmpout.Name())
  692. tmperr, _ := ioutil.TempFile("", "")
  693. defer os.Remove(tmperr.Name())
  694. stdout, stderr := os.Stdout, os.Stderr
  695. os.Stdout, os.Stderr = tmpout, tmperr
  696. // Execute function argument and then reassign stdout/stderr.
  697. fn()
  698. os.Stdout, os.Stderr = stdout, stderr
  699. // Close temp files and read them.
  700. tmpout.Close()
  701. bout, _ := ioutil.ReadFile(tmpout.Name())
  702. tmperr.Close()
  703. berr, _ := ioutil.ReadFile(tmperr.Name())
  704. return string(bout), string(berr)
  705. }