mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-23 10:26:22 +00:00
make input events a slice
This commit is contained in:
@@ -54,77 +54,104 @@ type handlerEvent struct {
|
||||
newObj *resourceapi.ResourceSlice
|
||||
}
|
||||
|
||||
type inputEventGenerator struct {
|
||||
addResourceSlice func(slice *resourceapi.ResourceSlice)
|
||||
deleteResourceSlice func(name string)
|
||||
addDeviceTaintRule func(taintRule *resourcealphaapi.DeviceTaintRule)
|
||||
deleteDeviceTaintRule func(name string)
|
||||
addDeviceClass func(class *resourceapi.DeviceClass)
|
||||
deleteDeviceClass func(name string)
|
||||
func add[T any](obj *T) [2]*T {
|
||||
return [2]*T{nil, obj}
|
||||
}
|
||||
|
||||
func inputEventGeneratorForTest(ctx context.Context, t *testing.T, tracker *Tracker) inputEventGenerator {
|
||||
return inputEventGenerator{
|
||||
addResourceSlice: func(slice *resourceapi.ResourceSlice) {
|
||||
oldObj, exists, err := tracker.resourceSlices.GetIndexer().Get(slice)
|
||||
require.NoError(t, err)
|
||||
err = tracker.resourceSlices.GetIndexer().Add(slice)
|
||||
require.NoError(t, err)
|
||||
if !exists {
|
||||
tracker.resourceSliceAdd(ctx)(slice)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, slice) {
|
||||
tracker.resourceSliceUpdate(ctx)(oldObj, slice)
|
||||
}
|
||||
},
|
||||
deleteResourceSlice: func(name string) {
|
||||
oldObj, exists, err := tracker.resourceSlices.GetIndexer().GetByKey(name)
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists, "deleting resource slice that was never created")
|
||||
err = tracker.resourceSlices.GetIndexer().Delete(oldObj)
|
||||
require.NoError(t, err)
|
||||
tracker.resourceSliceDelete(ctx)(oldObj)
|
||||
},
|
||||
addDeviceTaintRule: func(taintRule *resourcealphaapi.DeviceTaintRule) {
|
||||
oldObj, exists, err := tracker.deviceTaints.GetIndexer().Get(taintRule)
|
||||
require.NoError(t, err)
|
||||
err = tracker.deviceTaints.GetIndexer().Add(taintRule)
|
||||
require.NoError(t, err)
|
||||
if !exists {
|
||||
tracker.deviceTaintAdd(ctx)(taintRule)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, taintRule) {
|
||||
tracker.deviceTaintUpdate(ctx)(oldObj, taintRule)
|
||||
}
|
||||
},
|
||||
deleteDeviceTaintRule: func(name string) {
|
||||
oldObj, exists, err := tracker.deviceTaints.GetIndexer().GetByKey(name)
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists, "deleting DeviceTaintRule that was never created")
|
||||
err = tracker.deviceTaints.GetIndexer().Delete(oldObj)
|
||||
require.NoError(t, err)
|
||||
tracker.deviceTaintDelete(ctx)(oldObj)
|
||||
},
|
||||
addDeviceClass: func(class *resourceapi.DeviceClass) {
|
||||
oldObj, exists, err := tracker.deviceClasses.GetIndexer().Get(class)
|
||||
require.NoError(t, err)
|
||||
err = tracker.deviceClasses.GetIndexer().Add(class)
|
||||
require.NoError(t, err)
|
||||
if !exists {
|
||||
tracker.deviceClassAdd(ctx)(class)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, class) {
|
||||
tracker.deviceClassUpdate(ctx)(oldObj, class)
|
||||
}
|
||||
},
|
||||
deleteDeviceClass: func(name string) {
|
||||
oldObj, exists, err := tracker.deviceClasses.GetIndexer().GetByKey(name)
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists, "deleting device class that was never created")
|
||||
err = tracker.deviceClasses.GetIndexer().Delete(oldObj)
|
||||
require.NoError(t, err)
|
||||
tracker.deviceClassDelete(ctx)(oldObj)
|
||||
},
|
||||
func remove[T any](obj *T) [2]*T {
|
||||
return [2]*T{obj, nil}
|
||||
}
|
||||
|
||||
func update[T any](oldObj, newObj *T) [2]*T {
|
||||
return [2]*T{oldObj, newObj}
|
||||
}
|
||||
|
||||
func runInputEvents(tCtx *testContext, events []any) {
|
||||
for _, event := range events {
|
||||
applyEventPair(tCtx, event)
|
||||
}
|
||||
}
|
||||
|
||||
func applyEventPair(tCtx *testContext, event any) {
|
||||
switch pair := event.(type) {
|
||||
case [2]*resourceapi.ResourceSlice:
|
||||
slice := pair[0]
|
||||
if pair[1] != nil {
|
||||
slice = pair[1]
|
||||
}
|
||||
require.NotNil(tCtx, slice)
|
||||
|
||||
oldObj, exists, err := tCtx.resourceSlices.GetIndexer().Get(slice)
|
||||
require.NoError(tCtx, err)
|
||||
if pair[1] == nil {
|
||||
require.True(tCtx, exists, "device taint rule that was never created cannot be deleted")
|
||||
err = tCtx.resourceSlices.GetIndexer().Delete(oldObj)
|
||||
require.NoError(tCtx, err)
|
||||
tCtx.resourceSliceDelete(tCtx.Context)(oldObj)
|
||||
} else {
|
||||
err = tCtx.resourceSlices.GetIndexer().Add(slice)
|
||||
require.NoError(tCtx, err)
|
||||
if !exists {
|
||||
tCtx.resourceSliceAdd(tCtx.Context)(slice)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, slice) {
|
||||
tCtx.resourceSliceUpdate(tCtx.Context)(oldObj, slice)
|
||||
}
|
||||
}
|
||||
case [2]*resourcealphaapi.DeviceTaintRule:
|
||||
taint := pair[0]
|
||||
if pair[1] != nil {
|
||||
taint = pair[1]
|
||||
}
|
||||
require.NotNil(tCtx, taint)
|
||||
|
||||
oldObj, exists, err := tCtx.deviceTaints.GetIndexer().Get(taint)
|
||||
require.NoError(tCtx, err)
|
||||
if pair[1] == nil {
|
||||
require.True(tCtx, exists, "device taint rule that was never created cannot be deleted")
|
||||
err = tCtx.deviceTaints.GetIndexer().Delete(oldObj)
|
||||
require.NoError(tCtx, err)
|
||||
tCtx.deviceTaintDelete(tCtx.Context)(oldObj)
|
||||
} else {
|
||||
err = tCtx.deviceTaints.GetIndexer().Add(taint)
|
||||
require.NoError(tCtx, err)
|
||||
if !exists {
|
||||
tCtx.deviceTaintAdd(tCtx.Context)(taint)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, taint) {
|
||||
tCtx.deviceTaintUpdate(tCtx.Context)(oldObj, taint)
|
||||
}
|
||||
}
|
||||
case [2]*resourceapi.DeviceClass:
|
||||
class := pair[0]
|
||||
if pair[1] != nil {
|
||||
class = pair[1]
|
||||
}
|
||||
require.NotNil(tCtx, class)
|
||||
|
||||
oldObj, exists, err := tCtx.deviceClasses.GetIndexer().Get(class)
|
||||
require.NoError(tCtx, err)
|
||||
if pair[1] == nil {
|
||||
require.True(tCtx, exists, "device class that was never created cannot be deleted")
|
||||
err = tCtx.deviceClasses.GetIndexer().Delete(oldObj)
|
||||
require.NoError(tCtx, err)
|
||||
tCtx.deviceClassDelete(tCtx.Context)(oldObj)
|
||||
} else {
|
||||
err = tCtx.deviceClasses.GetIndexer().Add(class)
|
||||
require.NoError(tCtx, err)
|
||||
if !exists {
|
||||
tCtx.deviceClassAdd(tCtx.Context)(class)
|
||||
} else if !apiequality.Semantic.DeepEqual(oldObj, class) {
|
||||
tCtx.deviceClassUpdate(tCtx.Context)(oldObj, class)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testContext struct {
|
||||
*testing.T
|
||||
context.Context
|
||||
*Tracker
|
||||
}
|
||||
|
||||
var (
|
||||
now, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
||||
driver1 = "driver1.example.com"
|
||||
@@ -309,17 +336,16 @@ var (
|
||||
|
||||
func TestListPatchedResourceSlices(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
deviceTaintsDisabled bool
|
||||
inputEvents func(event inputEventGenerator)
|
||||
events []any
|
||||
expectedPatchedSlices []*resourceapi.ResourceSlice
|
||||
expectHandlerEvents func(t *testing.T, events []handlerEvent)
|
||||
expectEvents func(t *assert.CollectT, events *v1.EventList)
|
||||
expectUnhandledErrors func(t *testing.T, errs []error)
|
||||
}{
|
||||
"add-slices-no-patches": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1,
|
||||
@@ -337,14 +363,12 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"update-slices-no-patches": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addResourceSlice(slice1NoDevices)
|
||||
event.addResourceSlice(slice2NoDevices)
|
||||
event.addResourceSlice(unchangedSlice)
|
||||
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
event.addResourceSlice(unchangedSlice)
|
||||
events: []any{
|
||||
add(slice1NoDevices),
|
||||
add(slice2NoDevices),
|
||||
add(unchangedSlice),
|
||||
update(slice1NoDevices, slice1),
|
||||
update(slice2NoDevices, slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1,
|
||||
@@ -366,12 +390,12 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"delete-slices": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
event.addResourceSlice(unchangedSlice)
|
||||
event.deleteResourceSlice(slice1.Name)
|
||||
event.deleteResourceSlice(slice2.Name)
|
||||
events: []any{
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
add(unchangedSlice),
|
||||
remove(slice1),
|
||||
remove(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
unchangedSlice,
|
||||
@@ -391,9 +415,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"patch-all-slices": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addResourceSlice(slice1)
|
||||
event.addDeviceTaintRule(taintAllDevicesRule)
|
||||
events: []any{
|
||||
add(slice1),
|
||||
add(taintAllDevicesRule),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -410,11 +434,11 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"update-patch": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintPool1DevicesRule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
event.addDeviceTaintRule(taintPool2DevicesRule)
|
||||
events: []any{
|
||||
add(taintPool1DevicesRule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
update(taintPool1DevicesRule, taintPool2DevicesRule),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1,
|
||||
@@ -441,9 +465,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"merge-taints": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintAllDevicesRule)
|
||||
event.addResourceSlice(slice1AlreadyTainted)
|
||||
events: []any{
|
||||
add(taintAllDevicesRule),
|
||||
add(slice1AlreadyTainted),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1MergedTaints,
|
||||
@@ -459,10 +483,10 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"add-taint-for-driver": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintDriver1DevicesRule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(taintDriver1DevicesRule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -480,10 +504,10 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"add-taint-for-pool": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintPool1DevicesRule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(taintPool1DevicesRule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -501,10 +525,10 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"add-taint-for-device": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintDevice1Rule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(taintDevice1Rule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -522,10 +546,10 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"add-attribute-for-selector": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintDriver1DevicesCELRule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(taintDriver1DevicesCELRule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -543,9 +567,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"selector-does-not-match": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintNoDevicesCELRule)
|
||||
event.addResourceSlice(slice1)
|
||||
events: []any{
|
||||
add(taintNoDevicesCELRule),
|
||||
add(slice1),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1,
|
||||
@@ -561,9 +585,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"runtime-CEL-errors-skip-devices": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintNoDevicesCELRuntimeErrorRule)
|
||||
event.addResourceSlice(slice1)
|
||||
events: []any{
|
||||
add(taintNoDevicesCELRuntimeErrorRule),
|
||||
add(slice1),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1,
|
||||
@@ -586,9 +610,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"invalid-CEL-expression-throws-error": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintNoDevicesInvalidCELRule)
|
||||
event.addResourceSlice(slice1)
|
||||
events: []any{
|
||||
add(taintNoDevicesInvalidCELRule),
|
||||
add(slice1),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{},
|
||||
expectUnhandledErrors: func(t *testing.T, errs []error) {
|
||||
@@ -599,11 +623,11 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"add-taint-for-device-class": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceClass(deviceClass1)
|
||||
event.addDeviceTaintRule(taintDeviceClass1Rule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
events: []any{
|
||||
add(deviceClass1),
|
||||
add(taintDeviceClass1Rule),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -621,9 +645,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"filter-all-criteria": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceClass(deviceClass1)
|
||||
event.addDeviceTaintRule(
|
||||
events: []any{
|
||||
add(deviceClass1),
|
||||
add(
|
||||
taintDeviceClassRule(
|
||||
taintDriverDevicesRule(
|
||||
taintPoolDevicesRule(
|
||||
@@ -640,9 +664,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
),
|
||||
deviceClass1.Name,
|
||||
),
|
||||
)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(slice2)
|
||||
),
|
||||
add(slice1),
|
||||
add(slice2),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
slice1Tainted,
|
||||
@@ -660,12 +684,12 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"update-patched-slice": {
|
||||
inputEvents: func(event inputEventGenerator) {
|
||||
event.addDeviceTaintRule(taintDevice1Rule)
|
||||
event.addResourceSlice(slice1)
|
||||
event.addResourceSlice(sliceWithDevices(slice1, threeDevices))
|
||||
event.addResourceSlice(sliceWithDevices(slice2, threeDevices))
|
||||
event.addResourceSlice(sliceWithDevices(slice2, devices))
|
||||
events: []any{
|
||||
add(taintDevice1Rule),
|
||||
add(slice1),
|
||||
update(slice1, sliceWithDevices(slice1, threeDevices)),
|
||||
add(sliceWithDevices(slice2, threeDevices)),
|
||||
update(sliceWithDevices(slice2, threeDevices), sliceWithDevices(slice2, devices)),
|
||||
},
|
||||
expectedPatchedSlices: []*resourceapi.ResourceSlice{
|
||||
sliceWithDevices(slice1, threeDevicesOneTainted),
|
||||
@@ -707,7 +731,7 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := Options{
|
||||
EnableDeviceTaints: !test.deviceTaintsDisabled,
|
||||
EnableDeviceTaints: true,
|
||||
SliceInformer: informerFactory.Resource().V1beta1().ResourceSlices(),
|
||||
TaintInformer: informerFactory.Resource().V1alpha3().DeviceTaintRules(),
|
||||
ClassInformer: informerFactory.Resource().V1beta1().DeviceClasses(),
|
||||
@@ -721,10 +745,14 @@ func TestListPatchedResourceSlices(t *testing.T) {
|
||||
}
|
||||
_, _ = tracker.AddEventHandler(handler)
|
||||
|
||||
if test.inputEvents != nil {
|
||||
test.inputEvents(inputEventGeneratorForTest(ctx, t, tracker))
|
||||
tCtx := &testContext{
|
||||
T: t,
|
||||
Context: ctx,
|
||||
Tracker: tracker,
|
||||
}
|
||||
|
||||
runInputEvents(tCtx, test.events)
|
||||
|
||||
expectHandlerEvents := test.expectHandlerEvents
|
||||
if expectHandlerEvents == nil {
|
||||
expectHandlerEvents = func(t *testing.T, events []handlerEvent) {
|
||||
|
||||
Reference in New Issue
Block a user