wrappers.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. Copyright 2019 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 testing
  14. import (
  15. "fmt"
  16. "k8s.io/api/core/v1"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. )
  19. var zero int64
  20. // NodeSelectorWrapper wraps a NodeSelector inside.
  21. type NodeSelectorWrapper struct{ v1.NodeSelector }
  22. // MakeNodeSelector creates a NodeSelector wrapper.
  23. func MakeNodeSelector() *NodeSelectorWrapper {
  24. return &NodeSelectorWrapper{v1.NodeSelector{}}
  25. }
  26. // In injects a matchExpression (with an operator IN) as a selectorTerm
  27. // to the inner nodeSelector.
  28. // NOTE: appended selecterTerms are ORed.
  29. func (s *NodeSelectorWrapper) In(key string, vals []string) *NodeSelectorWrapper {
  30. expression := v1.NodeSelectorRequirement{
  31. Key: key,
  32. Operator: v1.NodeSelectorOpIn,
  33. Values: vals,
  34. }
  35. selectorTerm := v1.NodeSelectorTerm{}
  36. selectorTerm.MatchExpressions = append(selectorTerm.MatchExpressions, expression)
  37. s.NodeSelectorTerms = append(s.NodeSelectorTerms, selectorTerm)
  38. return s
  39. }
  40. // NotIn injects a matchExpression (with an operator NotIn) as a selectorTerm
  41. // to the inner nodeSelector.
  42. func (s *NodeSelectorWrapper) NotIn(key string, vals []string) *NodeSelectorWrapper {
  43. expression := v1.NodeSelectorRequirement{
  44. Key: key,
  45. Operator: v1.NodeSelectorOpNotIn,
  46. Values: vals,
  47. }
  48. selectorTerm := v1.NodeSelectorTerm{}
  49. selectorTerm.MatchExpressions = append(selectorTerm.MatchExpressions, expression)
  50. s.NodeSelectorTerms = append(s.NodeSelectorTerms, selectorTerm)
  51. return s
  52. }
  53. // Obj returns the inner NodeSelector.
  54. func (s *NodeSelectorWrapper) Obj() *v1.NodeSelector {
  55. return &s.NodeSelector
  56. }
  57. // LabelSelectorWrapper wraps a LabelSelector inside.
  58. type LabelSelectorWrapper struct{ metav1.LabelSelector }
  59. // MakeLabelSelector creates a LabelSelector wrapper.
  60. func MakeLabelSelector() *LabelSelectorWrapper {
  61. return &LabelSelectorWrapper{metav1.LabelSelector{}}
  62. }
  63. // Label applies a {k,v} pair to the inner LabelSelector.
  64. func (s *LabelSelectorWrapper) Label(k, v string) *LabelSelectorWrapper {
  65. if s.MatchLabels == nil {
  66. s.MatchLabels = make(map[string]string)
  67. }
  68. s.MatchLabels[k] = v
  69. return s
  70. }
  71. // In injects a matchExpression (with an operator In) to the inner labelSelector.
  72. func (s *LabelSelectorWrapper) In(key string, vals []string) *LabelSelectorWrapper {
  73. expression := metav1.LabelSelectorRequirement{
  74. Key: key,
  75. Operator: metav1.LabelSelectorOpIn,
  76. Values: vals,
  77. }
  78. s.MatchExpressions = append(s.MatchExpressions, expression)
  79. return s
  80. }
  81. // NotIn injects a matchExpression (with an operator NotIn) to the inner labelSelector.
  82. func (s *LabelSelectorWrapper) NotIn(key string, vals []string) *LabelSelectorWrapper {
  83. expression := metav1.LabelSelectorRequirement{
  84. Key: key,
  85. Operator: metav1.LabelSelectorOpNotIn,
  86. Values: vals,
  87. }
  88. s.MatchExpressions = append(s.MatchExpressions, expression)
  89. return s
  90. }
  91. // Exists injects a matchExpression (with an operator Exists) to the inner labelSelector.
  92. func (s *LabelSelectorWrapper) Exists(k string) *LabelSelectorWrapper {
  93. expression := metav1.LabelSelectorRequirement{
  94. Key: k,
  95. Operator: metav1.LabelSelectorOpExists,
  96. }
  97. s.MatchExpressions = append(s.MatchExpressions, expression)
  98. return s
  99. }
  100. // NotExist injects a matchExpression (with an operator NotExist) to the inner labelSelector.
  101. func (s *LabelSelectorWrapper) NotExist(k string) *LabelSelectorWrapper {
  102. expression := metav1.LabelSelectorRequirement{
  103. Key: k,
  104. Operator: metav1.LabelSelectorOpDoesNotExist,
  105. }
  106. s.MatchExpressions = append(s.MatchExpressions, expression)
  107. return s
  108. }
  109. // Obj returns the inner LabelSelector.
  110. func (s *LabelSelectorWrapper) Obj() *metav1.LabelSelector {
  111. return &s.LabelSelector
  112. }
  113. // PodWrapper wraps a Pod inside.
  114. type PodWrapper struct{ v1.Pod }
  115. // MakePod creates a Pod wrapper.
  116. func MakePod() *PodWrapper {
  117. return &PodWrapper{v1.Pod{}}
  118. }
  119. // Obj returns the inner Pod.
  120. func (p *PodWrapper) Obj() *v1.Pod {
  121. return &p.Pod
  122. }
  123. // Name sets `s` as the name of the inner pod.
  124. func (p *PodWrapper) Name(s string) *PodWrapper {
  125. p.SetName(s)
  126. return p
  127. }
  128. // Namespace sets `s` as the namespace of the inner pod.
  129. func (p *PodWrapper) Namespace(s string) *PodWrapper {
  130. p.SetNamespace(s)
  131. return p
  132. }
  133. // Container appends a container into PodSpec of the inner pod.
  134. func (p *PodWrapper) Container(s string) *PodWrapper {
  135. p.Spec.Containers = append(p.Spec.Containers, v1.Container{
  136. Name: fmt.Sprintf("con%d", len(p.Spec.Containers)),
  137. Image: s,
  138. })
  139. return p
  140. }
  141. // Priority sets a priority value into PodSpec of the inner pod.
  142. func (p *PodWrapper) Priority(val int32) *PodWrapper {
  143. p.Spec.Priority = &val
  144. return p
  145. }
  146. // Terminating sets the inner pod's deletionTimestamp to current timestamp.
  147. func (p *PodWrapper) Terminating() *PodWrapper {
  148. now := metav1.Now()
  149. p.DeletionTimestamp = &now
  150. return p
  151. }
  152. // ZeroTerminationGracePeriod sets the TerminationGracePeriodSeconds of the inner pod to zero.
  153. func (p *PodWrapper) ZeroTerminationGracePeriod() *PodWrapper {
  154. p.Spec.TerminationGracePeriodSeconds = &zero
  155. return p
  156. }
  157. // Node sets `s` as the nodeName of the inner pod.
  158. func (p *PodWrapper) Node(s string) *PodWrapper {
  159. p.Spec.NodeName = s
  160. return p
  161. }
  162. // NodeSelector sets `m` as the nodeSelector of the inner pod.
  163. func (p *PodWrapper) NodeSelector(m map[string]string) *PodWrapper {
  164. p.Spec.NodeSelector = m
  165. return p
  166. }
  167. // NodeAffinityIn creates a HARD node affinity (with the operator In)
  168. // and injects into the inner pod.
  169. func (p *PodWrapper) NodeAffinityIn(key string, vals []string) *PodWrapper {
  170. if p.Spec.Affinity == nil {
  171. p.Spec.Affinity = &v1.Affinity{}
  172. }
  173. if p.Spec.Affinity.NodeAffinity == nil {
  174. p.Spec.Affinity.NodeAffinity = &v1.NodeAffinity{}
  175. }
  176. nodeSelector := MakeNodeSelector().In(key, vals).Obj()
  177. p.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = nodeSelector
  178. return p
  179. }
  180. // NodeAffinityNotIn creates a HARD node affinity (with the operator NotIn)
  181. // and injects into the inner pod.
  182. func (p *PodWrapper) NodeAffinityNotIn(key string, vals []string) *PodWrapper {
  183. if p.Spec.Affinity == nil {
  184. p.Spec.Affinity = &v1.Affinity{}
  185. }
  186. if p.Spec.Affinity.NodeAffinity == nil {
  187. p.Spec.Affinity.NodeAffinity = &v1.NodeAffinity{}
  188. }
  189. nodeSelector := MakeNodeSelector().NotIn(key, vals).Obj()
  190. p.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = nodeSelector
  191. return p
  192. }
  193. // PodAffinityKind represents different kinds of PodAffinity.
  194. type PodAffinityKind int
  195. const (
  196. // NilPodAffinity is a no-op which doesn't apply any PodAffinity.
  197. NilPodAffinity PodAffinityKind = iota
  198. // PodAffinityWithRequiredReq applies a HARD requirement to pod.spec.affinity.PodAffinity.
  199. PodAffinityWithRequiredReq
  200. // PodAffinityWithPreferredReq applies a SOFT requirement to pod.spec.affinity.PodAffinity.
  201. PodAffinityWithPreferredReq
  202. // PodAffinityWithRequiredPreferredReq applies HARD and SOFT requirements to pod.spec.affinity.PodAffinity.
  203. PodAffinityWithRequiredPreferredReq
  204. // PodAntiAffinityWithRequiredReq applies a HARD requirement to pod.spec.affinity.PodAntiAffinity.
  205. PodAntiAffinityWithRequiredReq
  206. // PodAntiAffinityWithPreferredReq applies a SOFT requirement to pod.spec.affinity.PodAntiAffinity.
  207. PodAntiAffinityWithPreferredReq
  208. // PodAntiAffinityWithRequiredPreferredReq applies HARD and SOFT requirements to pod.spec.affinity.PodAntiAffinity.
  209. PodAntiAffinityWithRequiredPreferredReq
  210. )
  211. // PodAffinityExists creates an PodAffinity with the operator "Exists"
  212. // and injects into the inner pod.
  213. func (p *PodWrapper) PodAffinityExists(labelKey, topologyKey string, kind PodAffinityKind) *PodWrapper {
  214. if kind == NilPodAffinity {
  215. return p
  216. }
  217. if p.Spec.Affinity == nil {
  218. p.Spec.Affinity = &v1.Affinity{}
  219. }
  220. if p.Spec.Affinity.PodAffinity == nil {
  221. p.Spec.Affinity.PodAffinity = &v1.PodAffinity{}
  222. }
  223. labelSelector := MakeLabelSelector().Exists(labelKey).Obj()
  224. term := v1.PodAffinityTerm{LabelSelector: labelSelector, TopologyKey: topologyKey}
  225. switch kind {
  226. case PodAffinityWithRequiredReq:
  227. p.Spec.Affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append(
  228. p.Spec.Affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
  229. term,
  230. )
  231. case PodAffinityWithPreferredReq:
  232. p.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution = append(
  233. p.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
  234. v1.WeightedPodAffinityTerm{Weight: 1, PodAffinityTerm: term},
  235. )
  236. case PodAffinityWithRequiredPreferredReq:
  237. p.Spec.Affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append(
  238. p.Spec.Affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
  239. term,
  240. )
  241. p.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution = append(
  242. p.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
  243. v1.WeightedPodAffinityTerm{Weight: 1, PodAffinityTerm: term},
  244. )
  245. }
  246. return p
  247. }
  248. // PodAntiAffinityExists creates an PodAntiAffinity with the operator "Exists"
  249. // and injects into the inner pod.
  250. func (p *PodWrapper) PodAntiAffinityExists(labelKey, topologyKey string, kind PodAffinityKind) *PodWrapper {
  251. if kind == NilPodAffinity {
  252. return p
  253. }
  254. if p.Spec.Affinity == nil {
  255. p.Spec.Affinity = &v1.Affinity{}
  256. }
  257. if p.Spec.Affinity.PodAntiAffinity == nil {
  258. p.Spec.Affinity.PodAntiAffinity = &v1.PodAntiAffinity{}
  259. }
  260. labelSelector := MakeLabelSelector().Exists(labelKey).Obj()
  261. term := v1.PodAffinityTerm{LabelSelector: labelSelector, TopologyKey: topologyKey}
  262. switch kind {
  263. case PodAntiAffinityWithRequiredReq:
  264. p.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append(
  265. p.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
  266. term,
  267. )
  268. case PodAntiAffinityWithPreferredReq:
  269. p.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution = append(
  270. p.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
  271. v1.WeightedPodAffinityTerm{Weight: 1, PodAffinityTerm: term},
  272. )
  273. case PodAntiAffinityWithRequiredPreferredReq:
  274. p.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append(
  275. p.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
  276. term,
  277. )
  278. p.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution = append(
  279. p.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
  280. v1.WeightedPodAffinityTerm{Weight: 1, PodAffinityTerm: term},
  281. )
  282. }
  283. return p
  284. }
  285. // SpreadConstraint constructs a TopologySpreadConstraint object and injects
  286. // into the inner pod.
  287. func (p *PodWrapper) SpreadConstraint(maxSkew int, tpKey string, mode v1.UnsatisfiableConstraintAction, selector *metav1.LabelSelector) *PodWrapper {
  288. c := v1.TopologySpreadConstraint{
  289. MaxSkew: int32(maxSkew),
  290. TopologyKey: tpKey,
  291. WhenUnsatisfiable: mode,
  292. LabelSelector: selector,
  293. }
  294. p.Spec.TopologySpreadConstraints = append(p.Spec.TopologySpreadConstraints, c)
  295. return p
  296. }
  297. // Label sets a {k,v} pair to the inner pod.
  298. func (p *PodWrapper) Label(k, v string) *PodWrapper {
  299. if p.Labels == nil {
  300. p.Labels = make(map[string]string)
  301. }
  302. p.Labels[k] = v
  303. return p
  304. }
  305. // NodeWrapper wraps a Node inside.
  306. type NodeWrapper struct{ v1.Node }
  307. // MakeNode creates a Node wrapper.
  308. func MakeNode() *NodeWrapper {
  309. return &NodeWrapper{v1.Node{}}
  310. }
  311. // Obj returns the inner Node.
  312. func (n *NodeWrapper) Obj() *v1.Node {
  313. return &n.Node
  314. }
  315. // Name sets `s` as the name of the inner pod.
  316. func (n *NodeWrapper) Name(s string) *NodeWrapper {
  317. n.SetName(s)
  318. return n
  319. }
  320. // Label applies a {k,v} label pair to the inner node.
  321. func (n *NodeWrapper) Label(k, v string) *NodeWrapper {
  322. if n.Labels == nil {
  323. n.Labels = make(map[string]string)
  324. }
  325. n.Labels[k] = v
  326. return n
  327. }