config_test.go 26 KB

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