subnet_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. package subnet
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "testing"
  6. "time"
  7. "github.com/coreos/flannel/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd"
  8. "github.com/coreos/flannel/pkg/ip"
  9. )
  10. type mockSubnetRegistry struct {
  11. subnets *etcd.Node
  12. addCh chan string
  13. delCh chan string
  14. index uint64
  15. ttl uint64
  16. }
  17. func newMockSubnetRegistry(ttlOverride uint64) *mockSubnetRegistry {
  18. subnodes := []*etcd.Node{
  19. &etcd.Node{Key: "10.3.1.0-24", Value: `{ "PublicIP": "1.1.1.1" }`, ModifiedIndex: 10},
  20. &etcd.Node{Key: "10.3.2.0-24", Value: `{ "PublicIP": "1.1.1.1" }`, ModifiedIndex: 11},
  21. &etcd.Node{Key: "10.3.4.0-24", Value: `{ "PublicIP": "1.1.1.1" }`, ModifiedIndex: 12},
  22. &etcd.Node{Key: "10.3.5.0-24", Value: `{ "PublicIP": "1.1.1.1" }`, ModifiedIndex: 13},
  23. }
  24. return &mockSubnetRegistry{
  25. subnets: &etcd.Node{
  26. Nodes: subnodes,
  27. },
  28. addCh: make(chan string),
  29. delCh: make(chan string),
  30. index: 14,
  31. ttl: ttlOverride,
  32. }
  33. }
  34. func (msr *mockSubnetRegistry) getConfig() (*etcd.Response, error) {
  35. return &etcd.Response{
  36. EtcdIndex: msr.index,
  37. Node: &etcd.Node{
  38. Value: `{ "Network": "10.3.0.0/16", "SubnetMin": "10.3.1.0", "SubnetMax": "10.3.5.0" }`,
  39. },
  40. }, nil
  41. }
  42. func (msr *mockSubnetRegistry) getSubnets() (*etcd.Response, error) {
  43. return &etcd.Response{
  44. Node: msr.subnets,
  45. EtcdIndex: msr.index,
  46. }, nil
  47. }
  48. func (msr *mockSubnetRegistry) createSubnet(sn, data string, ttl uint64) (*etcd.Response, error) {
  49. msr.index += 1
  50. if msr.ttl > 0 {
  51. ttl = msr.ttl
  52. }
  53. // add squared durations :)
  54. exp := time.Now().Add(time.Duration(ttl) * time.Second)
  55. node := &etcd.Node{
  56. Key: sn,
  57. Value: data,
  58. ModifiedIndex: msr.index,
  59. Expiration: &exp,
  60. }
  61. msr.subnets.Nodes = append(msr.subnets.Nodes, node)
  62. return &etcd.Response{
  63. Node: node,
  64. EtcdIndex: msr.index,
  65. }, nil
  66. }
  67. func (msr *mockSubnetRegistry) updateSubnet(sn, data string, ttl uint64) (*etcd.Response, error) {
  68. msr.index += 1
  69. // add squared durations :)
  70. exp := time.Now().Add(time.Duration(ttl) * time.Second)
  71. for _, n := range msr.subnets.Nodes {
  72. if n.Key == sn {
  73. n.Value = data
  74. n.ModifiedIndex = msr.index
  75. n.Expiration = &exp
  76. return &etcd.Response{
  77. Node: n,
  78. EtcdIndex: msr.index,
  79. }, nil
  80. }
  81. }
  82. return nil, fmt.Errorf("Subnet not found")
  83. }
  84. func (msr *mockSubnetRegistry) watchSubnets(since uint64, stop chan bool) (*etcd.Response, error) {
  85. var sn string
  86. select {
  87. case <-stop:
  88. return nil, nil
  89. case sn = <-msr.addCh:
  90. n := etcd.Node{
  91. Key: sn,
  92. Value: `{"PublicIP": "1.1.1.1"}`,
  93. ModifiedIndex: msr.index,
  94. }
  95. msr.subnets.Nodes = append(msr.subnets.Nodes, &n)
  96. return &etcd.Response{
  97. Action: "add",
  98. Node: &n,
  99. }, nil
  100. case sn = <-msr.delCh:
  101. for i, n := range msr.subnets.Nodes {
  102. if n.Key == sn {
  103. msr.subnets.Nodes[i] = msr.subnets.Nodes[len(msr.subnets.Nodes)-1]
  104. msr.subnets.Nodes = msr.subnets.Nodes[:len(msr.subnets.Nodes)-2]
  105. return &etcd.Response{
  106. Action: "expire",
  107. Node: n,
  108. }, nil
  109. }
  110. }
  111. return nil, fmt.Errorf("Subnet (%s) to delete was not found: ", sn)
  112. }
  113. }
  114. func (msr *mockSubnetRegistry) hasSubnet(sn string) bool {
  115. for _, n := range msr.subnets.Nodes {
  116. if n.Key == sn {
  117. return true
  118. }
  119. }
  120. return false
  121. }
  122. func TestAcquireLease(t *testing.T) {
  123. msr := newMockSubnetRegistry(0)
  124. sm, err := newSubnetManager(msr)
  125. if err != nil {
  126. t.Fatalf("Failed to create subnet manager: %s", err)
  127. }
  128. extIP, _ := ip.ParseIP4("1.2.3.4")
  129. attrs := LeaseAttrs{
  130. PublicIP: extIP,
  131. }
  132. cancel := make(chan bool)
  133. sn, err := sm.AcquireLease(&attrs, cancel)
  134. if err != nil {
  135. t.Fatal("AcquireLease failed: ", err)
  136. }
  137. if sn.String() != "10.3.3.0/24" {
  138. t.Fatal("Subnet mismatch: expected 10.3.3.0/24, got: ", sn)
  139. }
  140. // Acquire again, should reuse
  141. if sn, err = sm.AcquireLease(&attrs, cancel); err != nil {
  142. t.Fatal("AcquireLease failed: ", err)
  143. }
  144. if sn.String() != "10.3.3.0/24" {
  145. t.Fatal("Subnet mismatch: expected 10.3.3.0/24, got: ", sn)
  146. }
  147. }
  148. func TestWatchLeaseAdded(t *testing.T) {
  149. msr := newMockSubnetRegistry(0)
  150. sm, err := newSubnetManager(msr)
  151. if err != nil {
  152. t.Fatalf("Failed to create subnet manager: %s", err)
  153. }
  154. events := make(chan EventBatch)
  155. cancel := make(chan bool)
  156. go sm.WatchLeases(events, cancel)
  157. expected := "10.3.3.0-24"
  158. msr.addCh <- expected
  159. evtBatch, ok := <-events
  160. if !ok {
  161. t.Fatalf("WatchSubnets did not publish")
  162. }
  163. if len(evtBatch) != 1 {
  164. t.Fatalf("WatchSubnets produced wrong sized event batch")
  165. }
  166. evt := evtBatch[0]
  167. if evt.Type != SubnetAdded {
  168. t.Fatalf("WatchSubnets produced wrong event type")
  169. }
  170. actual := evt.Lease.Network.StringSep(".", "-")
  171. if actual != expected {
  172. t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
  173. }
  174. close(cancel)
  175. }
  176. func TestWatchLeaseRemoved(t *testing.T) {
  177. msr := newMockSubnetRegistry(0)
  178. sm, err := newSubnetManager(msr)
  179. if err != nil {
  180. t.Fatalf("Failed to create subnet manager: %s", err)
  181. }
  182. events := make(chan EventBatch)
  183. cancel := make(chan bool)
  184. go sm.WatchLeases(events, cancel)
  185. expected := "10.3.4.0-24"
  186. msr.delCh <- expected
  187. evtBatch, ok := <-events
  188. if !ok {
  189. t.Fatalf("WatchSubnets did not publish")
  190. }
  191. if len(evtBatch) != 1 {
  192. t.Fatalf("WatchSubnets produced wrong sized event batch")
  193. }
  194. evt := evtBatch[0]
  195. if evt.Type != SubnetRemoved {
  196. t.Fatalf("WatchSubnets produced wrong event type")
  197. }
  198. actual := evt.Lease.Network.StringSep(".", "-")
  199. if actual != expected {
  200. t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
  201. }
  202. close(cancel)
  203. }
  204. func TestRenewLease(t *testing.T) {
  205. msr := newMockSubnetRegistry(1)
  206. sm, err := newSubnetManager(msr)
  207. if err != nil {
  208. t.Fatalf("Failed to create subnet manager: %s", err)
  209. }
  210. extIP, _ := ip.ParseIP4("1.2.3.4")
  211. attrs := LeaseAttrs{
  212. PublicIP: extIP,
  213. }
  214. cancel := make(chan bool)
  215. defer close(cancel)
  216. sn, err := sm.AcquireLease(&attrs, cancel)
  217. if err != nil {
  218. t.Fatal("AcquireLease failed: ", err)
  219. }
  220. go sm.LeaseRenewer(cancel)
  221. fmt.Println("Waiting for lease to pass original expiration")
  222. time.Sleep(2 * time.Second)
  223. // check that it's still good
  224. for _, n := range msr.subnets.Nodes {
  225. if n.Key == sn.StringSep(".", "-") {
  226. if n.Expiration.Before(time.Now()) {
  227. t.Error("Failed to renew lease: expiration did not advance")
  228. }
  229. a := LeaseAttrs{}
  230. if err := json.Unmarshal([]byte(n.Value), &a); err != nil {
  231. t.Errorf("Failed to JSON-decode LeaseAttrs: %v", err)
  232. return
  233. }
  234. if a.PublicIP != attrs.PublicIP {
  235. t.Errorf("LeaseAttrs changed: was %v, now %v", attrs.PublicIP, a.PublicIP)
  236. }
  237. return
  238. }
  239. }
  240. t.Fatalf("Failed to find acquired lease")
  241. }