mock_registry.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. "fmt"
  17. "path"
  18. "sort"
  19. "strings"
  20. "time"
  21. etcd "github.com/coreos/flannel/Godeps/_workspace/src/github.com/coreos/etcd/client"
  22. "github.com/coreos/flannel/Godeps/_workspace/src/golang.org/x/net/context"
  23. )
  24. type MockSubnetRegistry struct {
  25. networks map[string]*etcd.Node
  26. events chan *etcd.Response
  27. index uint64
  28. ttl time.Duration
  29. }
  30. const networkKeyPrefix = "/coreos.com/network"
  31. func NewMockRegistry(ttlOverride time.Duration, network, config string, initialSubnets []*etcd.Node) *MockSubnetRegistry {
  32. index := uint64(0)
  33. node := &etcd.Node{Key: normalizeNetKey(network), Value: config, ModifiedIndex: 0, Nodes: make([]*etcd.Node, 0, 20)}
  34. for _, n := range initialSubnets {
  35. if n.ModifiedIndex > index {
  36. index = n.ModifiedIndex
  37. }
  38. node.Nodes = append(node.Nodes, n)
  39. }
  40. msr := &MockSubnetRegistry{
  41. events: make(chan *etcd.Response, 1000),
  42. index: index + 1,
  43. ttl: ttlOverride,
  44. }
  45. msr.networks = make(map[string]*etcd.Node)
  46. msr.networks[network] = node
  47. return msr
  48. }
  49. func (msr *MockSubnetRegistry) getNetworkConfig(ctx context.Context, network string) (*etcd.Response, error) {
  50. return &etcd.Response{
  51. Index: msr.index,
  52. Node: msr.networks[network],
  53. }, nil
  54. }
  55. func (msr *MockSubnetRegistry) setConfig(network, config string) error {
  56. n, ok := msr.networks[network]
  57. if !ok {
  58. return fmt.Errorf("Network %s not found", network)
  59. }
  60. n.Value = config
  61. return nil
  62. }
  63. func (msr *MockSubnetRegistry) getSubnets(ctx context.Context, network string) (*etcd.Response, error) {
  64. n, ok := msr.networks[network]
  65. if !ok {
  66. return nil, fmt.Errorf("Network %s not found", network)
  67. }
  68. return &etcd.Response{
  69. Node: n,
  70. Index: msr.index,
  71. }, nil
  72. }
  73. func (msr *MockSubnetRegistry) createSubnet(ctx context.Context, network, sn, data string, ttl time.Duration) (*etcd.Response, error) {
  74. n, ok := msr.networks[network]
  75. if !ok {
  76. return nil, fmt.Errorf("Network %s not found", network)
  77. }
  78. msr.index += 1
  79. if msr.ttl > 0 {
  80. ttl = msr.ttl
  81. }
  82. exp := time.Now().Add(ttl)
  83. node := &etcd.Node{
  84. Key: sn,
  85. Value: data,
  86. ModifiedIndex: msr.index,
  87. Expiration: &exp,
  88. }
  89. n.Nodes = append(n.Nodes, node)
  90. msr.events <- &etcd.Response{
  91. Action: "add",
  92. Node: node,
  93. }
  94. return &etcd.Response{
  95. Node: node,
  96. Index: msr.index,
  97. }, nil
  98. }
  99. func (msr *MockSubnetRegistry) updateSubnet(ctx context.Context, network, sn, data string, ttl time.Duration) (*etcd.Response, error) {
  100. n, ok := msr.networks[network]
  101. if !ok {
  102. return nil, fmt.Errorf("Network %s not found", network)
  103. }
  104. msr.index += 1
  105. exp := time.Now().Add(ttl)
  106. for _, sub := range n.Nodes {
  107. if sub.Key == sn {
  108. sub.Value = data
  109. sub.ModifiedIndex = msr.index
  110. sub.Expiration = &exp
  111. msr.events <- &etcd.Response{
  112. Action: "add",
  113. Node: sub,
  114. }
  115. return &etcd.Response{
  116. Node: sub,
  117. Index: msr.index,
  118. }, nil
  119. }
  120. }
  121. return nil, fmt.Errorf("Subnet not found")
  122. }
  123. func (msr *MockSubnetRegistry) deleteSubnet(ctx context.Context, network, sn string) (*etcd.Response, error) {
  124. n, ok := msr.networks[network]
  125. if !ok {
  126. return nil, fmt.Errorf("Network %s not found", network)
  127. }
  128. msr.index += 1
  129. for i, sub := range n.Nodes {
  130. if sub.Key == sn {
  131. n.Nodes[i] = n.Nodes[len(n.Nodes)-1]
  132. n.Nodes = n.Nodes[:len(n.Nodes)-1]
  133. sub.ModifiedIndex = msr.index
  134. msr.events <- &etcd.Response{
  135. Action: "delete",
  136. Node: sub,
  137. }
  138. return &etcd.Response{
  139. Node: sub,
  140. Index: msr.index,
  141. }, nil
  142. }
  143. }
  144. return nil, fmt.Errorf("Subnet not found")
  145. }
  146. func (msr *MockSubnetRegistry) watch(ctx context.Context, network string, since uint64) (*etcd.Response, error) {
  147. for {
  148. if since < msr.index {
  149. return nil, etcd.Error{
  150. Code: etcd.ErrorCodeEventIndexCleared,
  151. Cause: "out of date",
  152. Message: "cursor is out of date",
  153. Index: msr.index,
  154. }
  155. }
  156. select {
  157. case <-ctx.Done():
  158. return nil, ctx.Err()
  159. case r := <-msr.events:
  160. if r.Node.ModifiedIndex <= since {
  161. continue
  162. }
  163. return r, nil
  164. }
  165. }
  166. }
  167. func (msr *MockSubnetRegistry) hasSubnet(network, sn string) bool {
  168. n, ok := msr.networks[network]
  169. if !ok {
  170. return false
  171. }
  172. for _, sub := range n.Nodes {
  173. if sub.Key == sn {
  174. return true
  175. }
  176. }
  177. return false
  178. }
  179. func (msr *MockSubnetRegistry) expireSubnet(network, sn string) {
  180. n, ok := msr.networks[network]
  181. if !ok {
  182. return
  183. }
  184. for i, sub := range n.Nodes {
  185. if sub.Key == sn {
  186. msr.index += 1
  187. n.Nodes[i] = n.Nodes[len(n.Nodes)-1]
  188. n.Nodes = n.Nodes[:len(n.Nodes)-2]
  189. sub.ModifiedIndex = msr.index
  190. msr.events <- &etcd.Response{
  191. Action: "expire",
  192. Node: sub,
  193. }
  194. return
  195. }
  196. }
  197. }
  198. func (msr *MockSubnetRegistry) getNetworks(ctx context.Context) (*etcd.Response, error) {
  199. var keys []string
  200. for k := range msr.networks {
  201. keys = append(keys, k)
  202. }
  203. sort.Strings(keys)
  204. networks := &etcd.Node{Key: networkKeyPrefix, Value: "", ModifiedIndex: msr.index, Nodes: make([]*etcd.Node, 0, len(keys))}
  205. for _, k := range keys {
  206. networks.Nodes = append(networks.Nodes, msr.networks[k])
  207. }
  208. return &etcd.Response{
  209. Node: networks,
  210. Index: msr.index,
  211. }, nil
  212. }
  213. func (msr *MockSubnetRegistry) getNetwork(ctx context.Context, network string) (*etcd.Response, error) {
  214. n, ok := msr.networks[network]
  215. if !ok {
  216. return nil, fmt.Errorf("Network %s not found", network)
  217. }
  218. return &etcd.Response{
  219. Node: n,
  220. Index: msr.index,
  221. }, nil
  222. }
  223. func (msr *MockSubnetRegistry) CreateNetwork(ctx context.Context, network, config string) (*etcd.Response, error) {
  224. _, ok := msr.networks[network]
  225. if ok {
  226. return nil, fmt.Errorf("Network %s already exists", network)
  227. }
  228. msr.index += 1
  229. node := &etcd.Node{
  230. Key: normalizeNetKey(network),
  231. Value: config,
  232. ModifiedIndex: msr.index,
  233. }
  234. msr.networks[network] = node
  235. msr.events <- &etcd.Response{
  236. Action: "add",
  237. Node: node,
  238. }
  239. return &etcd.Response{
  240. Node: node,
  241. Index: msr.index,
  242. }, nil
  243. }
  244. func (msr *MockSubnetRegistry) DeleteNetwork(ctx context.Context, network string) (*etcd.Response, error) {
  245. n, ok := msr.networks[network]
  246. if !ok {
  247. return nil, fmt.Errorf("Network %s not found", network)
  248. }
  249. msr.index += 1
  250. n.ModifiedIndex = msr.index
  251. delete(msr.networks, network)
  252. msr.events <- &etcd.Response{
  253. Action: "delete",
  254. Node: n,
  255. }
  256. return &etcd.Response{
  257. Node: n,
  258. Index: msr.index,
  259. }, nil
  260. }
  261. func normalizeNetKey(key string) string {
  262. match := networkKeyPrefix
  263. newKey := key
  264. if !strings.HasPrefix(newKey, match+"/") {
  265. newKey = path.Join(match, key)
  266. }
  267. if !strings.HasSuffix(newKey, "/config") {
  268. newKey = path.Join(newKey, "config")
  269. }
  270. return newKey
  271. }