subnet_test.go 7.4 KB

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