test_utils.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package node
  14. import (
  15. "errors"
  16. "fmt"
  17. "sync"
  18. "time"
  19. "k8s.io/kubernetes/pkg/api"
  20. apierrors "k8s.io/kubernetes/pkg/api/errors"
  21. "k8s.io/kubernetes/pkg/api/resource"
  22. "k8s.io/kubernetes/pkg/api/unversioned"
  23. "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
  24. unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
  25. "k8s.io/kubernetes/pkg/runtime"
  26. "k8s.io/kubernetes/pkg/util/clock"
  27. utilnode "k8s.io/kubernetes/pkg/util/node"
  28. "k8s.io/kubernetes/pkg/util/sets"
  29. "k8s.io/kubernetes/pkg/watch"
  30. )
  31. // FakeNodeHandler is a fake implementation of NodesInterface and NodeInterface. It
  32. // allows test cases to have fine-grained control over mock behaviors. We also need
  33. // PodsInterface and PodInterface to test list & delet pods, which is implemented in
  34. // the embedded client.Fake field.
  35. type FakeNodeHandler struct {
  36. *fake.Clientset
  37. // Input: Hooks determine if request is valid or not
  38. CreateHook func(*FakeNodeHandler, *api.Node) bool
  39. Existing []*api.Node
  40. // Output
  41. CreatedNodes []*api.Node
  42. DeletedNodes []*api.Node
  43. UpdatedNodes []*api.Node
  44. UpdatedNodeStatuses []*api.Node
  45. RequestCount int
  46. // Synchronization
  47. lock sync.Mutex
  48. deleteWaitChan chan struct{}
  49. }
  50. type FakeLegacyHandler struct {
  51. unversionedcore.CoreInterface
  52. n *FakeNodeHandler
  53. }
  54. func (c *FakeNodeHandler) getUpdatedNodesCopy() []*api.Node {
  55. c.lock.Lock()
  56. defer c.lock.Unlock()
  57. updatedNodesCopy := make([]*api.Node, len(c.UpdatedNodes), len(c.UpdatedNodes))
  58. for i, ptr := range c.UpdatedNodes {
  59. updatedNodesCopy[i] = ptr
  60. }
  61. return updatedNodesCopy
  62. }
  63. func (c *FakeNodeHandler) Core() unversionedcore.CoreInterface {
  64. return &FakeLegacyHandler{c.Clientset.Core(), c}
  65. }
  66. func (m *FakeLegacyHandler) Nodes() unversionedcore.NodeInterface {
  67. return m.n
  68. }
  69. func (m *FakeNodeHandler) Create(node *api.Node) (*api.Node, error) {
  70. m.lock.Lock()
  71. defer func() {
  72. m.RequestCount++
  73. m.lock.Unlock()
  74. }()
  75. for _, n := range m.Existing {
  76. if n.Name == node.Name {
  77. return nil, apierrors.NewAlreadyExists(api.Resource("nodes"), node.Name)
  78. }
  79. }
  80. if m.CreateHook == nil || m.CreateHook(m, node) {
  81. nodeCopy := *node
  82. m.CreatedNodes = append(m.CreatedNodes, &nodeCopy)
  83. return node, nil
  84. } else {
  85. return nil, errors.New("Create error.")
  86. }
  87. }
  88. func (m *FakeNodeHandler) Get(name string) (*api.Node, error) {
  89. m.lock.Lock()
  90. defer func() {
  91. m.RequestCount++
  92. m.lock.Unlock()
  93. }()
  94. for i := range m.Existing {
  95. if m.Existing[i].Name == name {
  96. nodeCopy := *m.Existing[i]
  97. return &nodeCopy, nil
  98. }
  99. }
  100. return nil, nil
  101. }
  102. func (m *FakeNodeHandler) List(opts api.ListOptions) (*api.NodeList, error) {
  103. m.lock.Lock()
  104. defer func() {
  105. m.RequestCount++
  106. m.lock.Unlock()
  107. }()
  108. var nodes []*api.Node
  109. for i := 0; i < len(m.UpdatedNodes); i++ {
  110. if !contains(m.UpdatedNodes[i], m.DeletedNodes) {
  111. nodes = append(nodes, m.UpdatedNodes[i])
  112. }
  113. }
  114. for i := 0; i < len(m.Existing); i++ {
  115. if !contains(m.Existing[i], m.DeletedNodes) && !contains(m.Existing[i], nodes) {
  116. nodes = append(nodes, m.Existing[i])
  117. }
  118. }
  119. for i := 0; i < len(m.CreatedNodes); i++ {
  120. if !contains(m.CreatedNodes[i], m.DeletedNodes) && !contains(m.CreatedNodes[i], nodes) {
  121. nodes = append(nodes, m.CreatedNodes[i])
  122. }
  123. }
  124. nodeList := &api.NodeList{}
  125. for _, node := range nodes {
  126. nodeList.Items = append(nodeList.Items, *node)
  127. }
  128. return nodeList, nil
  129. }
  130. func (m *FakeNodeHandler) Delete(id string, opt *api.DeleteOptions) error {
  131. m.lock.Lock()
  132. defer func() {
  133. m.RequestCount++
  134. if m.deleteWaitChan != nil {
  135. m.deleteWaitChan <- struct{}{}
  136. }
  137. m.lock.Unlock()
  138. }()
  139. m.DeletedNodes = append(m.DeletedNodes, newNode(id))
  140. return nil
  141. }
  142. func (m *FakeNodeHandler) DeleteCollection(opt *api.DeleteOptions, listOpts api.ListOptions) error {
  143. return nil
  144. }
  145. func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) {
  146. m.lock.Lock()
  147. defer func() {
  148. m.RequestCount++
  149. m.lock.Unlock()
  150. }()
  151. nodeCopy := *node
  152. m.UpdatedNodes = append(m.UpdatedNodes, &nodeCopy)
  153. return node, nil
  154. }
  155. func (m *FakeNodeHandler) UpdateStatus(node *api.Node) (*api.Node, error) {
  156. m.lock.Lock()
  157. defer func() {
  158. m.RequestCount++
  159. m.lock.Unlock()
  160. }()
  161. nodeCopy := *node
  162. m.UpdatedNodeStatuses = append(m.UpdatedNodeStatuses, &nodeCopy)
  163. return node, nil
  164. }
  165. func (m *FakeNodeHandler) PatchStatus(nodeName string, data []byte) (*api.Node, error) {
  166. m.RequestCount++
  167. return &api.Node{}, nil
  168. }
  169. func (m *FakeNodeHandler) Watch(opts api.ListOptions) (watch.Interface, error) {
  170. return nil, nil
  171. }
  172. func (m *FakeNodeHandler) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (*api.Node, error) {
  173. return nil, nil
  174. }
  175. // FakeRecorder is used as a fake during testing.
  176. type FakeRecorder struct {
  177. source api.EventSource
  178. events []*api.Event
  179. clock clock.Clock
  180. }
  181. func (f *FakeRecorder) Event(obj runtime.Object, eventtype, reason, message string) {
  182. f.generateEvent(obj, unversioned.Now(), eventtype, reason, message)
  183. }
  184. func (f *FakeRecorder) Eventf(obj runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
  185. f.Event(obj, eventtype, reason, fmt.Sprintf(messageFmt, args...))
  186. }
  187. func (f *FakeRecorder) PastEventf(obj runtime.Object, timestamp unversioned.Time, eventtype, reason, messageFmt string, args ...interface{}) {
  188. }
  189. func (f *FakeRecorder) generateEvent(obj runtime.Object, timestamp unversioned.Time, eventtype, reason, message string) {
  190. ref, err := api.GetReference(obj)
  191. if err != nil {
  192. return
  193. }
  194. event := f.makeEvent(ref, eventtype, reason, message)
  195. event.Source = f.source
  196. if f.events != nil {
  197. fmt.Println("write event")
  198. f.events = append(f.events, event)
  199. }
  200. }
  201. func (f *FakeRecorder) makeEvent(ref *api.ObjectReference, eventtype, reason, message string) *api.Event {
  202. fmt.Println("make event")
  203. t := unversioned.Time{Time: f.clock.Now()}
  204. namespace := ref.Namespace
  205. if namespace == "" {
  206. namespace = api.NamespaceDefault
  207. }
  208. return &api.Event{
  209. ObjectMeta: api.ObjectMeta{
  210. Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()),
  211. Namespace: namespace,
  212. },
  213. InvolvedObject: *ref,
  214. Reason: reason,
  215. Message: message,
  216. FirstTimestamp: t,
  217. LastTimestamp: t,
  218. Count: 1,
  219. Type: eventtype,
  220. }
  221. }
  222. func NewFakeRecorder() *FakeRecorder {
  223. return &FakeRecorder{
  224. source: api.EventSource{Component: "nodeControllerTest"},
  225. events: []*api.Event{},
  226. clock: clock.NewFakeClock(time.Now()),
  227. }
  228. }
  229. func newNode(name string) *api.Node {
  230. return &api.Node{
  231. ObjectMeta: api.ObjectMeta{Name: name},
  232. Spec: api.NodeSpec{
  233. ExternalID: name,
  234. },
  235. Status: api.NodeStatus{
  236. Capacity: api.ResourceList{
  237. api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
  238. api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
  239. },
  240. },
  241. }
  242. }
  243. func newPod(name, host string) *api.Pod {
  244. pod := &api.Pod{
  245. ObjectMeta: api.ObjectMeta{
  246. Namespace: "default",
  247. Name: name,
  248. },
  249. Spec: api.PodSpec{
  250. NodeName: host,
  251. },
  252. Status: api.PodStatus{
  253. Conditions: []api.PodCondition{
  254. {
  255. Type: api.PodReady,
  256. Status: api.ConditionTrue,
  257. },
  258. },
  259. },
  260. }
  261. return pod
  262. }
  263. func contains(node *api.Node, nodes []*api.Node) bool {
  264. for i := 0; i < len(nodes); i++ {
  265. if node.Name == nodes[i].Name {
  266. return true
  267. }
  268. }
  269. return false
  270. }
  271. // Returns list of zones for all Nodes stored in FakeNodeHandler
  272. func getZones(nodeHandler *FakeNodeHandler) []string {
  273. nodes, _ := nodeHandler.List(api.ListOptions{})
  274. zones := sets.NewString()
  275. for _, node := range nodes.Items {
  276. zones.Insert(utilnode.GetZoneKey(&node))
  277. }
  278. return zones.List()
  279. }
  280. func createZoneID(region, zone string) string {
  281. return region + ":\x00:" + zone
  282. }