@@ -38,6 +38,7 @@ import (
38
38
"k8s.io/client-go/informers"
39
39
"k8s.io/client-go/kubernetes/fake"
40
40
cgotesting "k8s.io/client-go/testing"
41
+ resourceslicetracker "k8s.io/dynamic-resource-allocation/resourceslice/tracker"
41
42
"k8s.io/kubernetes/pkg/scheduler/framework"
42
43
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
43
44
"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
@@ -183,8 +184,22 @@ var (
183
184
otherAllocatedClaim = st .FromResourceClaim (otherClaim ).
184
185
Allocation (allocationResult ).
185
186
Obj ()
187
+
188
+ deviceTaint = resourceapi.DeviceTaint {
189
+ Key : "taint-key" ,
190
+ Value : "taint-value" ,
191
+ Effect : resourceapi .DeviceTaintEffectNoSchedule ,
192
+ }
186
193
)
187
194
195
+ func taintDevices (slice * resourceapi.ResourceSlice ) * resourceapi.ResourceSlice {
196
+ slice = slice .DeepCopy ()
197
+ for i := range slice .Spec .Devices {
198
+ slice .Spec .Devices [i ].Basic .Taints = append (slice .Spec .Devices [i ].Basic .Taints , deviceTaint )
199
+ }
200
+ return slice
201
+ }
202
+
188
203
func reserve (claim * resourceapi.ResourceClaim , pod * v1.Pod ) * resourceapi.ResourceClaim {
189
204
return st .FromResourceClaim (claim ).
190
205
ReservedForPod (pod .Name , types .UID (pod .UID )).
@@ -343,6 +358,7 @@ func TestPlugin(t *testing.T) {
343
358
disableDRA bool
344
359
345
360
enableDRAPrioritizedList bool
361
+ enableDRADeviceTaints bool
346
362
}{
347
363
"empty" : {
348
364
pod : st .MakePod ().Name ("foo" ).Namespace ("default" ).Obj (),
@@ -604,6 +620,56 @@ func TestPlugin(t *testing.T) {
604
620
},
605
621
},
606
622
623
+ // The two test cases for device tainting only need to cover
624
+ // whether the feature gate is passed through to the allocator
625
+ // correctly. The actual logic around device taints and allocation
626
+ // is in the allocator.
627
+ "tainted-device-disabled" : {
628
+ enableDRADeviceTaints : false ,
629
+ pod : podWithClaimName ,
630
+ claims : []* resourceapi.ResourceClaim {pendingClaim },
631
+ classes : []* resourceapi.DeviceClass {deviceClass },
632
+ objs : []apiruntime.Object {taintDevices (workerNodeSlice )},
633
+ want : want {
634
+ reserve : result {
635
+ inFlightClaim : allocatedClaim ,
636
+ },
637
+ prebind : result {
638
+ assumedClaim : reserve (allocatedClaim , podWithClaimName ),
639
+ changes : change {
640
+ claim : func (claim * resourceapi.ResourceClaim ) * resourceapi.ResourceClaim {
641
+ if claim .Name == claimName {
642
+ claim = claim .DeepCopy ()
643
+ claim .Finalizers = allocatedClaim .Finalizers
644
+ claim .Status = inUseClaim .Status
645
+ }
646
+ return claim
647
+ },
648
+ },
649
+ },
650
+ postbind : result {
651
+ assumedClaim : reserve (allocatedClaim , podWithClaimName ),
652
+ },
653
+ },
654
+ },
655
+ "tainted-device-enabled" : {
656
+ enableDRADeviceTaints : true ,
657
+ pod : podWithClaimName ,
658
+ claims : []* resourceapi.ResourceClaim {pendingClaim },
659
+ classes : []* resourceapi.DeviceClass {deviceClass },
660
+ objs : []apiruntime.Object {taintDevices (workerNodeSlice )},
661
+ want : want {
662
+ filter : perNodeResult {
663
+ workerNode .Name : {
664
+ status : framework .NewStatus (framework .UnschedulableAndUnresolvable , `cannot allocate all claims` ),
665
+ },
666
+ },
667
+ postfilter : result {
668
+ status : framework .NewStatus (framework .Unschedulable , `still not schedulable` ),
669
+ },
670
+ },
671
+ },
672
+
607
673
"request-admin-access-with-DRAAdminAccess-featuregate" : {
608
674
// When the DRAAdminAccess feature gate is enabled,
609
675
// Because the pending claim asks for admin access,
@@ -920,6 +986,7 @@ func TestPlugin(t *testing.T) {
920
986
}
921
987
features := feature.Features {
922
988
EnableDRAAdminAccess : tc .enableDRAAdminAccess ,
989
+ EnableDRADeviceTaints : tc .enableDRADeviceTaints ,
923
990
EnableDynamicResourceAllocation : ! tc .disableDRA ,
924
991
EnableDRAPrioritizedList : tc .enableDRAPrioritizedList ,
925
992
}
@@ -1189,7 +1256,16 @@ func setup(t *testing.T, nodes []*v1.Node, claims []*resourceapi.ResourceClaim,
1189
1256
tc .client .PrependReactor ("*" , "*" , reactor )
1190
1257
1191
1258
tc .informerFactory = informers .NewSharedInformerFactory (tc .client , 0 )
1192
- tc .draManager = NewDRAManager (tCtx , assumecache .NewAssumeCache (tCtx .Logger (), tc .informerFactory .Resource ().V1beta1 ().ResourceClaims ().Informer (), "resource claim" , "" , nil ), tc .informerFactory )
1259
+ resourceSliceTrackerOpts := resourceslicetracker.Options {
1260
+ EnableDeviceTaints : true ,
1261
+ SliceInformer : tc .informerFactory .Resource ().V1beta1 ().ResourceSlices (),
1262
+ TaintInformer : tc .informerFactory .Resource ().V1alpha3 ().DeviceTaintRules (),
1263
+ ClassInformer : tc .informerFactory .Resource ().V1beta1 ().DeviceClasses (),
1264
+ KubeClient : tc .client ,
1265
+ }
1266
+ resourceSliceTracker , err := resourceslicetracker .StartTracker (tCtx , resourceSliceTrackerOpts )
1267
+ require .NoError (t , err , "couldn't start resource slice tracker" )
1268
+ tc .draManager = NewDRAManager (tCtx , assumecache .NewAssumeCache (tCtx .Logger (), tc .informerFactory .Resource ().V1beta1 ().ResourceClaims ().Informer (), "resource claim" , "" , nil ), resourceSliceTracker , tc .informerFactory )
1193
1269
opts := []runtime.Option {
1194
1270
runtime .WithClientSet (tc .client ),
1195
1271
runtime .WithInformerFactory (tc .informerFactory ),
0 commit comments