@@ -23,6 +23,7 @@ import (
23
23
. "github.com/onsi/gomega"
24
24
v1 "k8s.io/api/core/v1"
25
25
"k8s.io/apimachinery/pkg/api/meta"
26
+ "k8s.io/apimachinery/pkg/api/resource"
26
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
28
"k8s.io/apimachinery/pkg/types"
28
29
"k8s.io/client-go/tools/record"
@@ -63,6 +64,8 @@ var _ = Describe("AppWrapper Controller", func() {
63
64
awConfig .FaultTolerance .RetryPausePeriod = 0 * time .Second
64
65
awConfig .FaultTolerance .RetryLimit = 0
65
66
awConfig .FaultTolerance .SuccessTTL = 0 * time .Second
67
+ awConfig .Autopilot .ResourceTaints ["nvidia.com/gpu" ] = append (awConfig .Autopilot .ResourceTaints ["nvidia.com/gpu" ], v1.Taint {Key : "extra" , Value : "test" , Effect : v1 .TaintEffectNoExecute })
68
+
66
69
awReconciler = & AppWrapperReconciler {
67
70
Client : k8sClient ,
68
71
Recorder : & record.FakeRecorder {},
@@ -156,6 +159,42 @@ var _ = Describe("AppWrapper Controller", func() {
156
159
Expect (finished ).Should (BeFalse ())
157
160
}
158
161
162
+ validateMarkers := func (p * v1.Pod ) {
163
+ for k , v := range markerPodSet .Annotations {
164
+ Expect (p .Annotations ).Should (HaveKeyWithValue (k , v ))
165
+ }
166
+ for k , v := range markerPodSet .Labels {
167
+ Expect (p .Labels ).Should (HaveKeyWithValue (k , v ))
168
+ }
169
+ for _ , v := range markerPodSet .Tolerations {
170
+ Expect (p .Spec .Tolerations ).Should (ContainElement (v ))
171
+ }
172
+ for k , v := range markerPodSet .NodeSelector {
173
+ Expect (p .Spec .NodeSelector ).Should (HaveKeyWithValue (k , v ))
174
+ }
175
+ }
176
+
177
+ validateAutopilot := func (p * v1.Pod ) {
178
+ if p .Spec .Containers [0 ].Resources .Requests .Name ("nvidia.com/gpu" , resource .DecimalSI ).IsZero () {
179
+ Expect (p .Spec .Affinity ).Should (BeNil ())
180
+ } else {
181
+ Expect (p .Spec .Affinity .NodeAffinity .RequiredDuringSchedulingIgnoredDuringExecution ).ShouldNot (BeNil ())
182
+ Expect (p .Spec .Affinity .NodeAffinity .RequiredDuringSchedulingIgnoredDuringExecution .NodeSelectorTerms ).Should (HaveLen (1 ))
183
+ mes := p .Spec .Affinity .NodeAffinity .RequiredDuringSchedulingIgnoredDuringExecution .NodeSelectorTerms [0 ].MatchExpressions
184
+ for _ , taint := range awReconciler .Config .Autopilot .ResourceTaints ["nvidia.com/gpu" ] {
185
+ found := false
186
+ for _ , me := range mes {
187
+ if me .Key == taint .Key {
188
+ Expect (me .Operator ).Should (Equal (v1 .NodeSelectorOpNotIn ))
189
+ Expect (me .Values ).Should (ContainElement (taint .Value ))
190
+ found = true
191
+ }
192
+ }
193
+ Expect (found ).Should (BeTrue ())
194
+ }
195
+ }
196
+ }
197
+
159
198
AfterEach (func () {
160
199
By ("Cleanup the AppWrapper and ensure no Pods remain" )
161
200
aw := & workloadv1beta2.AppWrapper {}
@@ -318,6 +357,54 @@ var _ = Describe("AppWrapper Controller", func() {
318
357
Expect (err ).NotTo (HaveOccurred ())
319
358
Expect (podStatus .pending ).Should (Equal (int32 (1 )))
320
359
})
360
+
361
+ It ("Validating PodSet Injection invariants on minimal pods" , func () {
362
+ advanceToResuming (pod (100 , 0 , false ), pod (100 , 1 , true ))
363
+ beginRunning ()
364
+ aw := getAppWrapper (awName )
365
+ pods := getPods (aw )
366
+ Expect (pods ).Should (HaveLen (2 ))
367
+
368
+ By ("Validate expected markers and Autopilot anti-affinities were injected" )
369
+ for _ , p := range pods {
370
+ Expect (p .Labels ).Should (HaveKeyWithValue (AppWrapperLabel , awName .Name ))
371
+ validateMarkers (& p )
372
+ validateAutopilot (& p )
373
+ }
374
+ })
375
+
376
+ It ("Validating PodSet Injection invariants on complex pods" , func () {
377
+ advanceToResuming (complexPodYaml (), complexPodYaml ())
378
+ beginRunning ()
379
+ aw := getAppWrapper (awName )
380
+ pods := getPods (aw )
381
+ Expect (pods ).Should (HaveLen (2 ))
382
+
383
+ By ("Validate expected markers and Autopilot anti-affinities were injected" )
384
+ for _ , p := range pods {
385
+ Expect (p .Labels ).Should (HaveKeyWithValue (AppWrapperLabel , awName .Name ))
386
+ validateMarkers (& p )
387
+ validateAutopilot (& p )
388
+ }
389
+
390
+ By ("Validate complex pod elements were not removed" )
391
+ for _ , p := range pods {
392
+ Expect (p .Labels ).Should (HaveKeyWithValue ("myComplexLabel" , "myComplexValue" ))
393
+ Expect (p .Annotations ).Should (HaveKeyWithValue ("myComplexAnnotation" , "myComplexValue" ))
394
+ Expect (p .Spec .NodeSelector ).Should (HaveKeyWithValue ("myComplexSelector" , "myComplexValue" ))
395
+ Expect (p .Spec .Tolerations ).Should (ContainElement (v1.Toleration {Key : "myComplexKey" , Value : "myComplexValue" , Operator : v1 .TolerationOpEqual , Effect : v1 .TaintEffectNoSchedule }))
396
+ mes := p .Spec .Affinity .NodeAffinity .RequiredDuringSchedulingIgnoredDuringExecution .NodeSelectorTerms [0 ].MatchExpressions
397
+ found := false
398
+ for _ , me := range mes {
399
+ if me .Key == "kubernetes.io/hostname" {
400
+ Expect (me .Operator ).Should (Equal (v1 .NodeSelectorOpNotIn ))
401
+ Expect (me .Values ).Should (ContainElement ("badHost1" ))
402
+ found = true
403
+ }
404
+ }
405
+ Expect (found ).Should (BeTrue ())
406
+ }
407
+ })
321
408
})
322
409
323
410
var _ = Describe ("AppWrapper Annotations" , func () {
@@ -433,5 +520,4 @@ var _ = Describe("AppWrapper Annotations", func() {
433
520
Expect (awReconciler .terminalExitCodes (ctx , aw )).Should (Equal ([]int {3 , 10 , 42 }))
434
521
Expect (awReconciler .retryableExitCodes (ctx , aw )).Should (Equal ([]int {10 , 20 }))
435
522
})
436
-
437
523
})
0 commit comments