subnet_test.go 6.2 KB

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