upgrade_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. package functional
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "os"
  8. "os/exec"
  9. "path"
  10. "path/filepath"
  11. "testing"
  12. )
  13. var (
  14. binDir = ".versions"
  15. v1BinPath = path.Join(binDir, "1")
  16. v2BinPath = path.Join(binDir, "2")
  17. etcdctlBinPath string
  18. )
  19. func init() {
  20. os.RemoveAll(binDir)
  21. if err := os.Mkdir(binDir, 0700); err != nil {
  22. fmt.Printf("unexpected Mkdir error: %v\n", err)
  23. os.Exit(1)
  24. }
  25. if err := os.Symlink(absPathFromEnv("ETCD_V1_BIN"), v1BinPath); err != nil {
  26. fmt.Printf("unexpected Symlink error: %v\n", err)
  27. os.Exit(1)
  28. }
  29. if err := os.Symlink(absPathFromEnv("ETCD_V2_BIN"), v2BinPath); err != nil {
  30. fmt.Printf("unexpected Symlink error: %v\n", err)
  31. os.Exit(1)
  32. }
  33. etcdctlBinPath = os.Getenv("ETCDCTL_BIN")
  34. mustExist(v1BinPath)
  35. mustExist(v2BinPath)
  36. mustExist(etcdctlBinPath)
  37. }
  38. func TestStartNewMember(t *testing.T) {
  39. tests := []*Proc{
  40. NewProcWithDefaultFlags(v2BinPath),
  41. NewProcWithV1Flags(v2BinPath),
  42. NewProcWithV2Flags(v2BinPath),
  43. }
  44. for i, tt := range tests {
  45. if err := tt.Start(); err != nil {
  46. t.Fatalf("#%d: Start error: %v", i, err)
  47. }
  48. defer tt.Terminate()
  49. ver, err := checkInternalVersion(tt.URL)
  50. if err != nil {
  51. t.Fatalf("#%d: checkVersion error: %v", i, err)
  52. }
  53. if ver != "2" {
  54. t.Errorf("#%d: internal version = %s, want %s", i, ver, "2")
  55. }
  56. }
  57. }
  58. func TestStartV2Member(t *testing.T) {
  59. tests := []*Proc{
  60. NewProcWithDefaultFlags(v2BinPath),
  61. NewProcWithV1Flags(v2BinPath),
  62. NewProcWithV2Flags(v2BinPath),
  63. }
  64. for i, tt := range tests {
  65. // get v2 data dir
  66. p := NewProcWithDefaultFlags(v2BinPath)
  67. if err := p.Start(); err != nil {
  68. t.Fatalf("#%d: Start error: %v", i, err)
  69. }
  70. p.Stop()
  71. tt.SetDataDir(p.DataDir)
  72. if err := tt.Start(); err != nil {
  73. t.Fatalf("#%d: Start error: %v", i, err)
  74. }
  75. defer tt.Terminate()
  76. ver, err := checkInternalVersion(tt.URL)
  77. if err != nil {
  78. t.Fatalf("#%d: checkVersion error: %v", i, err)
  79. }
  80. if ver != "2" {
  81. t.Errorf("#%d: internal version = %s, want %s", i, ver, "2")
  82. }
  83. }
  84. }
  85. func TestStartV1Member(t *testing.T) {
  86. tests := []*Proc{
  87. NewProcWithDefaultFlags(v2BinPath),
  88. NewProcWithV1Flags(v2BinPath),
  89. NewProcWithV2Flags(v2BinPath),
  90. }
  91. for i, tt := range tests {
  92. // get v1 data dir
  93. p := NewProcWithDefaultFlags(v1BinPath)
  94. if err := p.Start(); err != nil {
  95. t.Fatalf("#%d: Start error: %v", i, err)
  96. }
  97. p.Stop()
  98. tt.SetDataDir(p.DataDir)
  99. if err := tt.Start(); err != nil {
  100. t.Fatalf("#%d: Start error: %v", i, err)
  101. }
  102. defer tt.Terminate()
  103. ver, err := checkInternalVersion(tt.URL)
  104. if err != nil {
  105. t.Fatalf("#%d: checkVersion error: %v", i, err)
  106. }
  107. if ver != "1" {
  108. t.Errorf("#%d: internal version = %s, want %s", i, ver, "1")
  109. }
  110. }
  111. }
  112. func TestUpgradeV1Cluster(t *testing.T) {
  113. // get v2-desired v1 data dir
  114. pg := NewProcGroupWithV1Flags(v1BinPath, 3)
  115. if err := pg.Start(); err != nil {
  116. t.Fatalf("Start error: %v", err)
  117. }
  118. cmd := exec.Command(etcdctlBinPath, "upgrade", "--peer-url", pg[1].PeerURL)
  119. if err := cmd.Start(); err != nil {
  120. t.Fatalf("Start error: %v", err)
  121. }
  122. if err := cmd.Wait(); err != nil {
  123. t.Fatalf("Wait error: %v", err)
  124. }
  125. t.Logf("wait until etcd exits...")
  126. if err := pg.Wait(); err != nil {
  127. t.Fatalf("Wait error: %v", err)
  128. }
  129. npg := NewProcGroupWithV1Flags(v2BinPath, 3)
  130. npg.InheritDataDir(pg)
  131. npg.CleanUnsuppportedV1Flags()
  132. if err := npg.Start(); err != nil {
  133. t.Fatalf("Start error: %v", err)
  134. }
  135. defer npg.Terminate()
  136. for _, p := range npg {
  137. ver, err := checkInternalVersion(p.URL)
  138. if err != nil {
  139. t.Fatalf("checkVersion error: %v", err)
  140. }
  141. if ver != "2" {
  142. t.Errorf("internal version = %s, want %s", ver, "2")
  143. }
  144. }
  145. }
  146. func TestUpgradeV1SnapshotedCluster(t *testing.T) {
  147. // get v2-desired v1 data dir
  148. pg := NewProcGroupWithV1Flags(v1BinPath, 3)
  149. pg.SetSnapCount(10)
  150. if err := pg.Start(); err != nil {
  151. t.Fatalf("Start error: %v", err)
  152. }
  153. cmd := exec.Command(etcdctlBinPath, "upgrade", "--peer-url", pg[1].PeerURL)
  154. if err := cmd.Start(); err != nil {
  155. t.Fatalf("Start error: %v", err)
  156. }
  157. if err := cmd.Wait(); err != nil {
  158. t.Fatalf("Wait error: %v", err)
  159. }
  160. t.Logf("wait until etcd exits...")
  161. if err := pg.Wait(); err != nil {
  162. t.Fatalf("Wait error: %v", err)
  163. }
  164. for _, p := range pg {
  165. // check it has taken snapshot
  166. fis, err := ioutil.ReadDir(path.Join(p.DataDir, "snapshot"))
  167. if err != nil {
  168. t.Fatalf("unexpected ReadDir error: %v", err)
  169. }
  170. if len(fis) == 0 {
  171. t.Fatalf("unexpected no-snapshot data dir")
  172. }
  173. }
  174. npg := NewProcGroupWithV1Flags(v2BinPath, 3)
  175. npg.InheritDataDir(pg)
  176. npg.CleanUnsuppportedV1Flags()
  177. if err := npg.Start(); err != nil {
  178. t.Fatalf("Start error: %v", err)
  179. }
  180. defer npg.Terminate()
  181. for _, p := range npg {
  182. ver, err := checkInternalVersion(p.URL)
  183. if err != nil {
  184. t.Fatalf("checkVersion error: %v", err)
  185. }
  186. if ver != "2" {
  187. t.Errorf("internal version = %s, want %s", ver, "2")
  188. }
  189. }
  190. }
  191. func TestJoinV1Cluster(t *testing.T) {
  192. pg := NewProcGroupWithV1Flags(v1BinPath, 1)
  193. if err := pg.Start(); err != nil {
  194. t.Fatalf("Start error: %v", err)
  195. }
  196. pg.Stop()
  197. npg := NewProcGroupWithV1Flags(v2BinPath, 3)
  198. npg[0].SetDataDir(pg[0].DataDir)
  199. if err := npg.Start(); err != nil {
  200. t.Fatalf("Start error: %v", err)
  201. }
  202. defer npg.Terminate()
  203. for _, p := range npg {
  204. ver, err := checkInternalVersion(p.URL)
  205. if err != nil {
  206. t.Fatalf("checkVersion error: %v", err)
  207. }
  208. if ver != "1" {
  209. t.Errorf("internal version = %s, want %s", ver, "1")
  210. }
  211. }
  212. }
  213. func TestJoinV1ClusterViaDiscovery(t *testing.T) {
  214. dp := NewProcWithDefaultFlags(v1BinPath)
  215. dp.SetV1Addr("127.0.0.1:5001")
  216. dp.SetV1PeerAddr("127.0.0.1:8001")
  217. if err := dp.Start(); err != nil {
  218. t.Fatalf("Start error: %v", err)
  219. }
  220. defer dp.Terminate()
  221. durl := "http://127.0.0.1:5001/v2/keys/cluster/"
  222. pg := NewProcGroupViaDiscoveryWithV1Flags(v1BinPath, 1, durl)
  223. if err := pg.Start(); err != nil {
  224. t.Fatalf("Start error: %v", err)
  225. }
  226. pg.Stop()
  227. npg := NewProcGroupViaDiscoveryWithV1Flags(v2BinPath, 3, durl)
  228. npg[0].SetDataDir(pg[0].DataDir)
  229. if err := npg.Start(); err != nil {
  230. t.Fatalf("Start error: %v", err)
  231. }
  232. defer npg.Terminate()
  233. for _, p := range npg {
  234. ver, err := checkInternalVersion(p.URL)
  235. if err != nil {
  236. t.Fatalf("checkVersion error: %v", err)
  237. }
  238. if ver != "1" {
  239. t.Errorf("internal version = %s, want %s", ver, "1")
  240. }
  241. }
  242. }
  243. func absPathFromEnv(name string) string {
  244. path, err := filepath.Abs(os.Getenv(name))
  245. if err != nil {
  246. fmt.Printf("unexpected Abs error: %v\n", err)
  247. }
  248. return path
  249. }
  250. func mustExist(path string) {
  251. if _, err := os.Stat(path); err != nil {
  252. fmt.Printf("%v\n", err)
  253. os.Exit(1)
  254. }
  255. }
  256. func checkInternalVersion(url string) (string, error) {
  257. resp, err := http.Get(url + "/version")
  258. if err != nil {
  259. return "", err
  260. }
  261. b, err := ioutil.ReadAll(resp.Body)
  262. if err != nil {
  263. return "", err
  264. }
  265. var m map[string]string
  266. err = json.Unmarshal(b, &m)
  267. return m["internalVersion"], err
  268. }