diff --git a/staging/src/k8s.io/dynamic-resource-allocation/resourceslice/tracker/tracker_test.go b/staging/src/k8s.io/dynamic-resource-allocation/resourceslice/tracker/tracker_test.go index 1e5feca7cea..331eb7016b6 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/resourceslice/tracker/tracker_test.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/resourceslice/tracker/tracker_test.go @@ -125,9 +125,189 @@ func inputEventGeneratorForTest(ctx context.Context, t *testing.T, tracker *Trac } } -func TestListPatchedResourceSlices(t *testing.T) { - now, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") +var ( + now, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + driver1 = "driver1.example.com" + driver2 = "driver2.example.com" + pool1 = "pool-1" + pool2 = "pool-2" + device0Name = "device-0" + device1Name = "device-1" + device2Name = "device-2" + deviceClass1 = &resourceapi.DeviceClass{ + ObjectMeta: metav1.ObjectMeta{Name: "device-class-1"}, + Spec: resourceapi.DeviceClassSpec{ + Selectors: []resourceapi.DeviceSelector{ + { + CEL: &resourceapi.CELDeviceSelector{ + Expression: `device.driver == "` + driver1 + `"`, + }, + }, + }, + }, + } + + sliceWithDevices = func(slice *resourceapi.ResourceSlice, devices []resourceapi.Device) *resourceapi.ResourceSlice { + slice = slice.DeepCopy() + slice.Spec.Devices = devices + return slice + } + slice1NoDevices = &resourceapi.ResourceSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "s1", + }, + Spec: resourceapi.ResourceSliceSpec{ + Driver: driver1, + Pool: resourceapi.ResourcePool{ + Name: pool1, + }, + }, + } + slice2NoDevices = &resourceapi.ResourceSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "s2", + }, + Spec: resourceapi.ResourceSliceSpec{ + Driver: driver2, + Pool: resourceapi.ResourcePool{ + Name: pool2, + }, + }, + } + unchangedSlice = &resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "no-change"}} + + deviceWithName = func(device resourceapi.Device, name string) resourceapi.Device { + device.Name = name + return device + } + deviceWithTaints = func(device resourceapi.Device, taints []resourceapi.DeviceTaint) resourceapi.Device { + if device.Basic != nil { + device.Basic = device.Basic.DeepCopy() + device.Basic.Taints = taints + } + return device + } + emptyDevice = resourceapi.Device{Basic: &resourceapi.BasicDevice{}} + device0 = deviceWithName(emptyDevice, device0Name) + device1 = deviceWithName(emptyDevice, device1Name) + device2 = deviceWithName(emptyDevice, device2Name) + + deviceTaint1 = resourceapi.DeviceTaint{ + Key: "example.com/taint", + Value: "tainted", + Effect: resourceapi.DeviceTaintEffectNoExecute, + TimeAdded: &metav1.Time{Time: now}, + } + deviceTaint2 = resourceapi.DeviceTaint{ + Key: "example.com/taint2", + Value: "tainted2", + Effect: resourceapi.DeviceTaintEffectNoExecute, + TimeAdded: &metav1.Time{Time: now}, + } + deviceTaints = []resourceapi.DeviceTaint{deviceTaint1} + device1Tainted = deviceWithTaints(device1, deviceTaints) + device2Tainted = deviceWithTaints(device2, deviceTaints) + devices = []resourceapi.Device{device1} + threeDevices = []resourceapi.Device{ + device0, + device1, + device2, + } + threeDevicesOneTainted = []resourceapi.Device{ + device0, + device1Tainted, + device2, + } + devices2 = []resourceapi.Device{device2} + taintedDevices = []resourceapi.Device{device1Tainted} + taintedDevices2 = []resourceapi.Device{device2Tainted} + + existingDeviceTaints = []resourceapi.DeviceTaint{deviceTaint2} + existingDevice1Tainted = deviceWithTaints(device1, existingDeviceTaints) + existingTaintedDevices = []resourceapi.Device{existingDevice1Tainted} + mergedDeviceTaints = []resourceapi.DeviceTaint{deviceTaint2, deviceTaint1} + mergedDevice1Tainted = deviceWithTaints(device1, mergedDeviceTaints) + mergedTaintedDevices = []resourceapi.Device{mergedDevice1Tainted} + + slice1 = sliceWithDevices(slice1NoDevices, devices) + slice1Tainted = sliceWithDevices(slice1, taintedDevices) + slice1AlreadyTainted = sliceWithDevices(slice1, existingTaintedDevices) + slice1MergedTaints = sliceWithDevices(slice1, mergedTaintedDevices) + slice2 = sliceWithDevices(slice2NoDevices, devices2) + slice2Tainted = sliceWithDevices(slice2, taintedDevices2) + + alphaDeviceTaint = func(taint resourceapi.DeviceTaint) resourcealphaapi.DeviceTaint { + return resourcealphaapi.DeviceTaint{ + Key: taint.Key, + Value: taint.Value, + Effect: resourcealphaapi.DeviceTaintEffect(taint.Effect), + TimeAdded: taint.TimeAdded, + } + } + taintAllDevicesRule = &resourcealphaapi.DeviceTaintRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rule", + }, + Spec: resourcealphaapi.DeviceTaintRuleSpec{ + Taint: alphaDeviceTaint(deviceTaint1), + }, + } + taintPoolDevicesRule = func(rule *resourcealphaapi.DeviceTaintRule, pool string) *resourcealphaapi.DeviceTaintRule { + rule = rule.DeepCopy() + rule.Spec.DeviceSelector = &resourcealphaapi.DeviceTaintSelector{ + Pool: &pool, + } + return rule + } + taintDriverDevicesRule = func(rule *resourcealphaapi.DeviceTaintRule, driver string) *resourcealphaapi.DeviceTaintRule { + rule = rule.DeepCopy() + rule.Spec.DeviceSelector = &resourcealphaapi.DeviceTaintSelector{ + Driver: &driver, + } + return rule + } + taintNamedDevicesRule = func(rule *resourcealphaapi.DeviceTaintRule, name string) *resourcealphaapi.DeviceTaintRule { + rule = rule.DeepCopy() + rule.Spec.DeviceSelector = &resourcealphaapi.DeviceTaintSelector{ + Device: &name, + } + return rule + } + taintCELSelectedDevicesRule = func(rule *resourcealphaapi.DeviceTaintRule, exprs ...string) *resourcealphaapi.DeviceTaintRule { + rule = rule.DeepCopy() + var selectors []resourcealphaapi.DeviceSelector + for _, expr := range exprs { + selectors = append(selectors, resourcealphaapi.DeviceSelector{ + CEL: &resourcealphaapi.CELDeviceSelector{ + Expression: expr, + }, + }) + } + rule.Spec.DeviceSelector = &resourcealphaapi.DeviceTaintSelector{ + Selectors: selectors, + } + return rule + } + taintDeviceClassRule = func(rule *resourcealphaapi.DeviceTaintRule, deviceClassName string) *resourcealphaapi.DeviceTaintRule { + rule = rule.DeepCopy() + rule.Spec.DeviceSelector = &resourcealphaapi.DeviceTaintSelector{ + DeviceClassName: &deviceClassName, + } + return rule + } + taintPool1DevicesRule = taintPoolDevicesRule(taintAllDevicesRule, pool1) + taintPool2DevicesRule = taintPoolDevicesRule(taintAllDevicesRule, pool2) + taintDriver1DevicesRule = taintDriverDevicesRule(taintAllDevicesRule, driver1) + taintDevice1Rule = taintNamedDevicesRule(taintAllDevicesRule, device1Name) + taintDriver1DevicesCELRule = taintCELSelectedDevicesRule(taintAllDevicesRule, `device.driver == "`+driver1+`"`) + taintNoDevicesCELRule = taintCELSelectedDevicesRule(taintAllDevicesRule, `true`, `false`, `true`) + taintNoDevicesCELRuntimeErrorRule = taintCELSelectedDevicesRule(taintAllDevicesRule, `device.attributes["test.example.com"].deviceAttr`) + taintNoDevicesInvalidCELRule = taintCELSelectedDevicesRule(taintAllDevicesRule, `invalid`) + taintDeviceClass1Rule = taintDeviceClassRule(taintAllDevicesRule, deviceClass1.Name) +) + +func TestListPatchedResourceSlices(t *testing.T) { tests := map[string]struct { deviceTaintsDisabled bool inputEvents func(event inputEventGenerator) @@ -138,918 +318,277 @@ func TestListPatchedResourceSlices(t *testing.T) { }{ "add-slices-no-patches": { inputEvents: func(event inputEventGenerator) { - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "s1"}}) - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "s2"}}) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - {ObjectMeta: metav1.ObjectMeta{Name: "s1"}}, - {ObjectMeta: metav1.ObjectMeta{Name: "s2"}}, + slice1, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "s1", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "s2", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "update-slices-no-patches": { inputEvents: func(event inputEventGenerator) { - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "s1", - }, - Spec: resourceapi.ResourceSliceSpec{ - // no devices - Devices: nil, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "s2", - }, - Spec: resourceapi.ResourceSliceSpec{ - // no devices - Devices: nil, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "no-change"}}) + event.addResourceSlice(slice1NoDevices) + event.addResourceSlice(slice2NoDevices) + event.addResourceSlice(unchangedSlice) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "s1", - }, - Spec: resourceapi.ResourceSliceSpec{ - // devices! - Devices: []resourceapi.Device{ - {Basic: &resourceapi.BasicDevice{}}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "s2", - }, - Spec: resourceapi.ResourceSliceSpec{ - // devices! - Devices: []resourceapi.Device{ - {Basic: &resourceapi.BasicDevice{}}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "no-change"}}) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) + event.addResourceSlice(unchangedSlice) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "s1", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - {Basic: &resourceapi.BasicDevice{}}, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "s2", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - {Basic: &resourceapi.BasicDevice{}}, - }, - }, - }, - {ObjectMeta: metav1.ObjectMeta{Name: "no-change"}}, + slice1, + slice2, + unchangedSlice, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 5) { - return - } - // The first events are adds. - assert.Equal(t, handlerEventUpdate, events[3].event) - assert.Equal(t, "s1", events[3].newObj.Name) - assert.Equal(t, "s1", events[3].oldObj.Name) - assert.Nil(t, events[3].oldObj.Spec.Devices) - assert.NotNil(t, events[3].newObj.Spec.Devices) - assert.Equal(t, handlerEventUpdate, events[4].event) - assert.Equal(t, "s2", events[4].newObj.Name) - assert.Equal(t, "s2", events[4].oldObj.Name) - assert.Nil(t, events[4].oldObj.Spec.Devices) - assert.NotNil(t, events[4].newObj.Spec.Devices) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1NoDevices}, + {event: handlerEventAdd, newObj: slice2NoDevices}, + {event: handlerEventAdd, newObj: unchangedSlice}, + {event: handlerEventUpdate, oldObj: slice1NoDevices, newObj: slice1}, + {event: handlerEventUpdate, oldObj: slice2NoDevices, newObj: slice2}, + }, + events, + ) }, }, "delete-slices": { inputEvents: func(event inputEventGenerator) { - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "s1"}}) - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "s2"}}) - event.addResourceSlice(&resourceapi.ResourceSlice{ObjectMeta: metav1.ObjectMeta{Name: "keep-me"}}) - event.deleteResourceSlice("s1") - event.deleteResourceSlice("s2") + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) + event.addResourceSlice(unchangedSlice) + event.deleteResourceSlice(slice1.Name) + event.deleteResourceSlice(slice2.Name) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - {ObjectMeta: metav1.ObjectMeta{Name: "keep-me"}}, + unchangedSlice, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 5) { - return - } - // The first events are adds. - assert.Equal(t, handlerEventDelete, events[3].event) - assert.Equal(t, "s1", events[3].oldObj.Name) - assert.Equal(t, handlerEventDelete, events[4].event) - assert.Equal(t, "s2", events[4].oldObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1}, + {event: handlerEventAdd, newObj: slice2}, + {event: handlerEventAdd, newObj: unchangedSlice}, + {event: handlerEventDelete, oldObj: slice1}, + {event: handlerEventDelete, oldObj: slice2}, + }, + events, + ) }, }, "patch-all-slices": { inputEvents: func(event inputEventGenerator) { - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "all-slices", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: nil, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) + event.addResourceSlice(slice1) + event.addDeviceTaintRule(taintAllDevicesRule) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, + slice1Tainted, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventUpdate, events[1].event) - assert.Equal(t, "slice", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1}, + {event: handlerEventUpdate, oldObj: slice1, newObj: slice1Tainted}, + }, + events, + ) }, }, "update-patch": { inputEvents: func(event inputEventGenerator) { - taintRule := &resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "taintRule", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Pool: ptr.To("pool-1"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - } - event.addDeviceTaintRule(taintRule.DeepCopy()) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice-1", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool-1", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice-2", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool-2", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - taintRule.Spec.DeviceSelector.Pool = ptr.To("pool-2") - event.addDeviceTaintRule(taintRule) + event.addDeviceTaintRule(taintPool1DevicesRule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) + event.addDeviceTaintRule(taintPool2DevicesRule) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice-1", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool-1", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice-2", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool-2", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, + slice1, + slice2Tainted, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 4) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice-1", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "slice-2", events[1].newObj.Name) - - assert.Equal(t, handlerEventUpdate, events[2].event) - assert.Equal(t, handlerEventUpdate, events[3].event) - assert.ElementsMatch(t, []string{"slice-1", "slice-2"}, []string{events[2].newObj.Name, events[3].newObj.Name}) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events[:2], + ) + // The remaining events may come in any order + assert.ElementsMatch( + t, + []handlerEvent{ + {event: handlerEventUpdate, oldObj: slice1Tainted, newObj: slice1}, + {event: handlerEventUpdate, oldObj: slice2, newObj: slice2Tainted}, + }, + events[2:], + ) }, }, "merge-taints": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "merge", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: nil, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint2", - Value: "tainted2", - Effect: resourceapi.DeviceTaintEffectNoSchedule, - }}, - }, - }, - }, - }, - }) + event.addDeviceTaintRule(taintAllDevicesRule) + event.addResourceSlice(slice1AlreadyTainted) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{ - { - Key: "example.com/taint2", - Value: "tainted2", - Effect: resourceapi.DeviceTaintEffectNoSchedule, - }, - { - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }, - }, - }, - }, - }, + slice1MergedTaints, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 1) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1MergedTaints}, + }, + events, + ) }, }, "add-taint-for-driver": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "driver", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Driver: ptr.To("test.example.com"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintDriver1DevicesRule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "wrong-driver", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "add-taint-for-pool": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pool", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Pool: ptr.To("pool"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-pool", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "other", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintPool1DevicesRule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-pool", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "other", - }, - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "wrong-pool", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "add-taint-for-device": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "device", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Device: ptr.To("device"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Name: "device", - Basic: &resourceapi.BasicDevice{}, - }, - { - Name: "wrong-device", - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintDevice1Rule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Name: "device", - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - { - Name: "wrong-device", - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 1) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "add-attribute-for-selector": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "selector", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Selectors: []resourcealphaapi.DeviceSelector{ - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `device.driver == "test.example.com"`, - }, - }, - }, - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintDriver1DevicesCELRule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "wrong-driver", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "selector-does-not-match": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "selector", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Selectors: []resourcealphaapi.DeviceSelector{ - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `true`, - }, - }, - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `false`, - }, - }, - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `true`, - }, - }, - }, - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintNoDevicesCELRule) + event.addResourceSlice(slice1) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 1) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1}, + }, + events, + ) }, }, "runtime-CEL-errors-skip-devices": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "selector", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Selectors: []resourcealphaapi.DeviceSelector{ - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `device.attributes["test.example.com"].deviceAttr`, - }, - }, - }, - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }) + event.addDeviceTaintRule(taintNoDevicesCELRuntimeErrorRule) + event.addResourceSlice(slice1) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, + slice1, }, expectEvents: func(t *assert.CollectT, events *v1.EventList) { if !assert.Len(t, events.Items, 1) { return } - assert.Equal(t, "selector", events.Items[0].InvolvedObject.Name) + assert.Equal(t, taintNoDevicesCELRuntimeErrorRule.Name, events.Items[0].InvolvedObject.Name) assert.Equal(t, "CELRuntimeError", events.Items[0].Reason) }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 1) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1}, + }, + events, + ) }, }, "invalid-CEL-expression-throws-error": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "selector", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Selectors: []resourcealphaapi.DeviceSelector{ - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `invalid`, - }, - }, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceTaintRule(taintNoDevicesInvalidCELRule) + event.addResourceSlice(slice1) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{}, expectUnhandledErrors: func(t *testing.T, errs []error) { @@ -1061,335 +600,88 @@ func TestListPatchedResourceSlices(t *testing.T) { }, "add-taint-for-device-class": { inputEvents: func(event inputEventGenerator) { - event.addDeviceClass(&resourceapi.DeviceClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "class.example.com", - }, - Spec: resourceapi.DeviceClassSpec{ - Selectors: []resourceapi.DeviceSelector{ - { - CEL: &resourceapi.CELDeviceSelector{ - Expression: `device.driver == "test.example.com"`, - }, - }, - }, - }, - }) - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "device-class", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - DeviceClassName: ptr.To("class.example.com"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceClass(deviceClass1) + event.addDeviceTaintRule(taintDeviceClass1Rule) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "wrong-driver", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "filter-all-criteria": { inputEvents: func(event inputEventGenerator) { - event.addDeviceClass(&resourceapi.DeviceClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "class.example.com", - }, - Spec: resourceapi.DeviceClassSpec{ - Selectors: []resourceapi.DeviceSelector{ - { - CEL: &resourceapi.CELDeviceSelector{ - Expression: `device.driver == "test.example.com"`, - }, - }, - }, - }, - }) - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "all-criteria", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - DeviceClassName: ptr.To("class.example.com"), - Driver: ptr.To("test.example.com"), - Pool: ptr.To("pool"), - Device: ptr.To("device"), - Selectors: []resourcealphaapi.DeviceSelector{ - { - CEL: &resourcealphaapi.CELDeviceSelector{ - Expression: `true`, - }, - }, - }, - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Name: "device", - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) - event.addResourceSlice(&resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }) + event.addDeviceClass(deviceClass1) + event.addDeviceTaintRule( + taintDeviceClassRule( + taintDriverDevicesRule( + taintPoolDevicesRule( + taintNamedDevicesRule( + taintCELSelectedDevicesRule( + taintAllDevicesRule, + `true`, + ), + device1Name, + ), + pool1, + ), + driver1, + ), + deviceClass1.Name, + ), + ) + event.addResourceSlice(slice1) + event.addResourceSlice(slice2) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "slice", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "test.example.com", - Pool: resourceapi.ResourcePool{ - Name: "pool", - }, - Devices: []resourceapi.Device{ - { - Name: "device", - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "wrong-driver", - }, - Spec: resourceapi.ResourceSliceSpec{ - Driver: "wrong.example.com", - Devices: []resourceapi.Device{ - { - Basic: &resourceapi.BasicDevice{}, - }, - }, - }, - }, + slice1Tainted, + slice2, }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 2) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "slice", events[0].newObj.Name) - assert.Equal(t, handlerEventAdd, events[1].event) - assert.Equal(t, "wrong-driver", events[1].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventAdd, newObj: slice2}, + }, + events, + ) }, }, "update-patched-slice": { inputEvents: func(event inputEventGenerator) { - event.addDeviceTaintRule(&resourcealphaapi.DeviceTaintRule{ - ObjectMeta: metav1.ObjectMeta{ - Name: "all-slices", - }, - Spec: resourcealphaapi.DeviceTaintRuleSpec{ - DeviceSelector: &resourcealphaapi.DeviceTaintSelector{ - Device: ptr.To("device-1"), - }, - Taint: resourcealphaapi.DeviceTaint{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourcealphaapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }, - }, - }) - oneDevice := []resourceapi.Device{ - {Name: "device-1", Basic: &resourceapi.BasicDevice{}}, - } - threeDevices := []resourceapi.Device{ - {Name: "device-0", Basic: &resourceapi.BasicDevice{}}, - {Name: "device-1", Basic: &resourceapi.BasicDevice{}}, - {Name: "device-2", Basic: &resourceapi.BasicDevice{}}, - } - devicesAdded := &resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "devices-added", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: oneDevice, - }, - } - devicesRemoved := &resourceapi.ResourceSlice{ - ObjectMeta: metav1.ObjectMeta{ - Name: "devices-removed", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: threeDevices, - }, - } - event.addResourceSlice(devicesAdded.DeepCopy()) - devicesAdded.Spec.Devices = threeDevices - event.addResourceSlice(devicesAdded) - event.addResourceSlice(devicesRemoved.DeepCopy()) - devicesRemoved.Spec.Devices = oneDevice - event.addResourceSlice(devicesRemoved) + event.addDeviceTaintRule(taintDevice1Rule) + event.addResourceSlice(slice1) + event.addResourceSlice(sliceWithDevices(slice1, threeDevices)) + event.addResourceSlice(sliceWithDevices(slice2, threeDevices)) + event.addResourceSlice(sliceWithDevices(slice2, devices)) }, expectedPatchedSlices: []*resourceapi.ResourceSlice{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "devices-added", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - {Name: "device-0", Basic: &resourceapi.BasicDevice{}}, - { - Name: "device-1", - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - {Name: "device-2", Basic: &resourceapi.BasicDevice{}}, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "devices-removed", - }, - Spec: resourceapi.ResourceSliceSpec{ - Devices: []resourceapi.Device{ - { - Name: "device-1", - Basic: &resourceapi.BasicDevice{ - Taints: []resourceapi.DeviceTaint{{ - Key: "example.com/taint", - Value: "tainted", - Effect: resourceapi.DeviceTaintEffectNoExecute, - TimeAdded: &metav1.Time{Time: now}, - }}, - }, - }, - }, - }, - }, + sliceWithDevices(slice1, threeDevicesOneTainted), + sliceWithDevices(slice2, taintedDevices), }, expectHandlerEvents: func(t *testing.T, events []handlerEvent) { - if !assert.Len(t, events, 4) { - return - } - assert.Equal(t, handlerEventAdd, events[0].event) - assert.Equal(t, "devices-added", events[0].newObj.Name) - assert.Equal(t, handlerEventUpdate, events[1].event) - assert.Equal(t, "devices-added", events[1].newObj.Name) - assert.Equal(t, handlerEventAdd, events[2].event) - assert.Equal(t, "devices-removed", events[2].newObj.Name) - assert.Equal(t, handlerEventUpdate, events[3].event) - assert.Equal(t, "devices-removed", events[3].newObj.Name) + assert.Equal( + t, + []handlerEvent{ + {event: handlerEventAdd, newObj: slice1Tainted}, + {event: handlerEventUpdate, oldObj: slice1Tainted, newObj: sliceWithDevices(slice1, threeDevicesOneTainted)}, + {event: handlerEventAdd, newObj: sliceWithDevices(slice2, threeDevicesOneTainted)}, + {event: handlerEventUpdate, oldObj: sliceWithDevices(slice2, threeDevicesOneTainted), newObj: sliceWithDevices(slice2, taintedDevices)}, + }, + events, + ) }, }, }