Skip to content

Commit a95db41

Browse files
authored
Merge pull request kubernetes#127523 from googs1025/scheduler/dra/queuehint
chore(scheduler dra): improve dra queue hint unit test
2 parents 9865737 + 24a2876 commit a95db41

File tree

2 files changed

+133
-10
lines changed

2 files changed

+133
-10
lines changed

pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go

Lines changed: 119 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ var (
125125
Namespace(namespace).
126126
Request(className).
127127
Obj()
128+
deleteClaim = st.FromResourceClaim(claim).
129+
OwnerReference(podName, podUID, podKind).
130+
Deleting(metav1.Now()).Obj()
128131
pendingClaim = st.FromResourceClaim(claim).
129132
OwnerReference(podName, podUID, podKind).
130133
Obj()
@@ -188,6 +191,8 @@ var (
188191
ResourceClaims(resourceapi.ResourceClaimSchedulingStatus{Name: resourceName},
189192
resourceapi.ResourceClaimSchedulingStatus{Name: resourceName2}).
190193
Obj()
194+
resourceSlice = st.MakeResourceSlice(nodeName, driver).Device("instance-1", nil).Obj()
195+
resourceSliceUpdated = st.FromResourceSlice(resourceSlice).Device("instance-1", map[resourceapi.QualifiedName]resourceapi.DeviceAttribute{attrName: {BoolValue: ptr.To(true)}}).Obj()
191196
)
192197

193198
func reserve(claim *resourceapi.ResourceClaim, pod *v1.Pod) *resourceapi.ResourceClaim {
@@ -1499,16 +1504,16 @@ func Test_isSchedulableAfterClaimChange(t *testing.T) {
14991504
gotHint, err := testCtx.p.isSchedulableAfterClaimChange(logger, tc.pod, oldObj, newObj)
15001505
if tc.wantErr {
15011506
if err == nil {
1502-
t.Fatal("expected an error, got none")
1507+
t.Fatal("want an error, got none")
15031508
}
15041509
return
15051510
}
15061511

15071512
if err != nil {
1508-
t.Fatalf("expected no error, got: %v", err)
1513+
t.Fatalf("want no error, got: %v", err)
15091514
}
15101515
if tc.wantHint != gotHint {
1511-
t.Fatalf("expected hint %#v, got %#v", tc.wantHint, gotHint)
1516+
t.Fatalf("want %#v, got %#v", tc.wantHint.String(), gotHint.String())
15121517
}
15131518
})
15141519
}
@@ -1577,16 +1582,16 @@ func Test_isSchedulableAfterPodChange(t *testing.T) {
15771582
gotHint, err := testCtx.p.isSchedulableAfterPodChange(logger, tc.pod, nil, tc.obj)
15781583
if tc.wantErr {
15791584
if err == nil {
1580-
t.Fatal("expected an error, got none")
1585+
t.Fatal("want an error, got none")
15811586
}
15821587
return
15831588
}
15841589

15851590
if err != nil {
1586-
t.Fatalf("expected no error, got: %v", err)
1591+
t.Fatalf("want no error, got: %v", err)
15871592
}
15881593
if tc.wantHint != gotHint {
1589-
t.Fatalf("expected hint %#v, got %#v", tc.wantHint, gotHint)
1594+
t.Fatalf("want %#v, got %#v", tc.wantHint.String(), gotHint.String())
15901595
}
15911596
})
15921597
}
@@ -1716,16 +1721,121 @@ func Test_isSchedulableAfterPodSchedulingContextChange(t *testing.T) {
17161721
gotHint, err := testCtx.p.isSchedulableAfterPodSchedulingContextChange(logger, tc.pod, tc.oldObj, tc.newObj)
17171722
if tc.wantErr {
17181723
if err == nil {
1719-
t.Fatal("expected an error, got none")
1724+
t.Fatal("want an error, got none")
1725+
}
1726+
return
1727+
}
1728+
1729+
if err != nil {
1730+
t.Fatalf("want no error, got: %v", err)
1731+
}
1732+
if tc.wantHint != gotHint {
1733+
t.Fatalf("want %#v, got %#v", tc.wantHint.String(), gotHint.String())
1734+
}
1735+
})
1736+
}
1737+
}
1738+
1739+
func Test_isSchedulableAfterResourceSliceChange(t *testing.T) {
1740+
testcases := map[string]struct {
1741+
pod *v1.Pod
1742+
claims []*resourceapi.ResourceClaim
1743+
oldObj, newObj interface{}
1744+
wantHint framework.QueueingHint
1745+
wantErr bool
1746+
}{
1747+
"queue-new-resource-slice": {
1748+
pod: podWithClaimName,
1749+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1750+
newObj: resourceSlice,
1751+
wantHint: framework.Queue,
1752+
},
1753+
"queue1-update-resource-slice-with-claim-is-allocated": {
1754+
pod: podWithClaimName,
1755+
claims: []*resourceapi.ResourceClaim{allocatedClaim},
1756+
oldObj: resourceSlice,
1757+
newObj: resourceSliceUpdated,
1758+
wantHint: framework.Queue,
1759+
},
1760+
"queue-update-resource-slice-with-claim-is-deleting": {
1761+
pod: podWithClaimName,
1762+
claims: []*resourceapi.ResourceClaim{deleteClaim},
1763+
oldObj: resourceSlice,
1764+
newObj: resourceSliceUpdated,
1765+
wantHint: framework.QueueSkip,
1766+
},
1767+
"queue-new-resource-slice-with-two-claim": {
1768+
pod: podWithTwoClaimNames,
1769+
claims: []*resourceapi.ResourceClaim{pendingClaim, pendingClaim2},
1770+
oldObj: resourceSlice,
1771+
newObj: resourceSliceUpdated,
1772+
wantHint: framework.Queue,
1773+
},
1774+
"queue-update-resource-slice-with-two-claim-but-one-hasn't-been-created": {
1775+
pod: podWithTwoClaimNames,
1776+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1777+
oldObj: resourceSlice,
1778+
newObj: resourceSliceUpdated,
1779+
wantHint: framework.QueueSkip,
1780+
},
1781+
"queue-update-resource-slice": {
1782+
pod: podWithClaimName,
1783+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1784+
oldObj: resourceSlice,
1785+
newObj: resourceSliceUpdated,
1786+
wantHint: framework.Queue,
1787+
},
1788+
"skip-not-find-resource-claim": {
1789+
pod: podWithClaimName,
1790+
claims: []*resourceapi.ResourceClaim{},
1791+
oldObj: resourceSlice,
1792+
newObj: resourceSliceUpdated,
1793+
wantHint: framework.QueueSkip,
1794+
},
1795+
"backoff-unexpected-object-with-oldObj-newObj": {
1796+
pod: podWithClaimName,
1797+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1798+
oldObj: scheduling,
1799+
newObj: scheduling,
1800+
wantErr: true,
1801+
},
1802+
"backoff-unexpected-object-with-oldObj": {
1803+
pod: podWithClaimName,
1804+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1805+
oldObj: scheduling,
1806+
newObj: resourceSlice,
1807+
wantErr: true,
1808+
},
1809+
"backoff-unexpected-object-with-newObj": {
1810+
pod: podWithClaimName,
1811+
claims: []*resourceapi.ResourceClaim{pendingClaim},
1812+
oldObj: resourceSlice,
1813+
newObj: scheduling,
1814+
wantErr: true,
1815+
},
1816+
}
1817+
for name, tc := range testcases {
1818+
tc := tc
1819+
t.Run(name, func(t *testing.T) {
1820+
t.Parallel()
1821+
logger, _ := ktesting.NewTestContext(t)
1822+
features := feature.Features{
1823+
EnableDynamicResourceAllocation: true,
1824+
}
1825+
testCtx := setup(t, nil, tc.claims, nil, nil, nil, features)
1826+
gotHint, err := testCtx.p.isSchedulableAfterResourceSliceChange(logger, tc.pod, tc.oldObj, tc.newObj)
1827+
if tc.wantErr {
1828+
if err == nil {
1829+
t.Fatal("want an error, got none")
17201830
}
17211831
return
17221832
}
17231833

17241834
if err != nil {
1725-
t.Fatalf("expected no error, got: %v", err)
1835+
t.Fatalf("want no error, got: %v", err)
17261836
}
17271837
if tc.wantHint != gotHint {
1728-
t.Fatalf("expected hint %#v, got %#v", tc.wantHint, gotHint)
1838+
t.Fatalf("want %#v, got %#v", tc.wantHint.String(), gotHint.String())
17291839
}
17301840
})
17311841
}

pkg/scheduler/testing/wrappers.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,12 @@ func (wrapper *ResourceClaimWrapper) Allocation(allocation *resourceapi.Allocati
983983
return wrapper
984984
}
985985

986+
// Deleting sets the deletion timestamp of the inner object.
987+
func (wrapper *ResourceClaimWrapper) Deleting(time metav1.Time) *ResourceClaimWrapper {
988+
wrapper.ResourceClaim.DeletionTimestamp = &time
989+
return wrapper
990+
}
991+
986992
// Structured turns a "normal" claim into one which was allocated via structured parameters.
987993
// The only difference is that there is no controller name and the special finalizer
988994
// gets added.
@@ -1007,7 +1013,7 @@ func (wrapper *ResourceClaimWrapper) ReservedFor(consumers ...resourceapi.Resour
10071013
return wrapper
10081014
}
10091015

1010-
// ReservedFor sets that field of the inner object given information about one pod.
1016+
// ReservedForPod sets that field of the inner object given information about one pod.
10111017
func (wrapper *ResourceClaimWrapper) ReservedForPod(podName string, podUID types.UID) *ResourceClaimWrapper {
10121018
return wrapper.ReservedFor(resourceapi.ResourceClaimConsumerReference{Resource: "pods", Name: podName, UID: podUID})
10131019
}
@@ -1105,17 +1111,24 @@ func MakeResourceSlice(nodeName, driverName string) *ResourceSliceWrapper {
11051111
return wrapper
11061112
}
11071113

1114+
// FromResourceSlice creates a ResourceSlice wrapper from some existing object.
1115+
func FromResourceSlice(other *resourceapi.ResourceSlice) *ResourceSliceWrapper {
1116+
return &ResourceSliceWrapper{*other.DeepCopy()}
1117+
}
1118+
11081119
func (wrapper *ResourceSliceWrapper) Obj() *resourceapi.ResourceSlice {
11091120
return &wrapper.ResourceSlice
11101121
}
11111122

1123+
// Devices sets the devices field of the inner object.
11121124
func (wrapper *ResourceSliceWrapper) Devices(names ...string) *ResourceSliceWrapper {
11131125
for _, name := range names {
11141126
wrapper.Spec.Devices = append(wrapper.Spec.Devices, resourceapi.Device{Name: name})
11151127
}
11161128
return wrapper
11171129
}
11181130

1131+
// Device sets the devices field of the inner object.
11191132
func (wrapper *ResourceSliceWrapper) Device(name string, attrs map[resourceapi.QualifiedName]resourceapi.DeviceAttribute) *ResourceSliceWrapper {
11201133
wrapper.Spec.Devices = append(wrapper.Spec.Devices, resourceapi.Device{Name: name, Basic: &resourceapi.BasicDevice{Attributes: attrs}})
11211134
return wrapper

0 commit comments

Comments
 (0)