diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index e465b5999c1..f74a5ddd8ec 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/util/certificate/csr" "k8s.io/kubernetes/pkg/apis/admissionregistration" @@ -46,6 +47,7 @@ import ( nodeapi "k8s.io/kubernetes/pkg/apis/node" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/rbac" + resourceapis "k8s.io/kubernetes/pkg/apis/resource" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/apis/storagemigration" @@ -6206,6 +6208,426 @@ func TestPrintFlowSchema(t *testing.T) { } } +func TestPrintDeviceClass(t *testing.T) { + + tests := []struct { + deviceClass resourceapis.DeviceClass + expected []metav1.TableRow + }{ + { + deviceClass: resourceapis.DeviceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-deviceclass", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.DeviceClassSpec{ + SuitableNodes: &api.NodeSelector{ + NodeSelectorTerms: []api.NodeSelectorTerm{{ + MatchExpressions: []api.NodeSelectorRequirement{{ + Key: "foo", + Operator: api.NodeSelectorOpExists, + }}, + }}, + }, + }, + }, + // Columns: Name, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-deviceclass", "5m"}}}, + }, + { + // test case for Empty creation timestamp that is translated to + deviceClass: resourceapis.DeviceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-deviceclass", + CreationTimestamp: metav1.Time{}, + }, + Spec: resourceapis.DeviceClassSpec{ + SuitableNodes: &api.NodeSelector{ + NodeSelectorTerms: []api.NodeSelectorTerm{{ + MatchExpressions: []api.NodeSelectorRequirement{{ + Key: "foo", + Operator: api.NodeSelectorOpExists, + }}, + }}, + }, + }, + }, + // Columns: Name, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-deviceclass", ""}}}, + }, + } + + for i, test := range tests { + rows, err := printDeviceClass(&test.deviceClass, printers.GenerateOptions{}) + if err != nil { + t.Fatal(err) + } + for i := range rows { + rows[i].Object.Object = nil + } + if !reflect.DeepEqual(test.expected, rows) { + t.Errorf("%d mismatch: %s", i, cmp.Diff(test.expected, rows)) + } + } +} + +func TestPrintResourceClaim(t *testing.T) { + + tests := []struct { + name string + resourceClaim resourceapis.ResourceClaim + expected []metav1.TableRow + }{ + { + name: "ResourceClaim with Pending State", + resourceClaim: resourceapis.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaim", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{ + { + Name: "deviceRequest", + DeviceClassName: "deviceClass", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }, + }, + }, + }, + }, + // Columns: Name, State, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaim", "pending", "5m"}}}, + }, + { + // test case for Empty creation timestamp that is translated to + name: "ResourceClaim with Pending State and Empty creation timestamp", + resourceClaim: resourceapis.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaim", + CreationTimestamp: metav1.Time{}, + }, + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{ + { + Name: "deviceRequest", + DeviceClassName: "deviceClass", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }, + }, + }, + }, + }, + // Columns: Name, State, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaim", "pending", ""}}}, + }, + { + name: "ResourceClaim with Allocated State and Deallocation State", + resourceClaim: resourceapis.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaim", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{ + { + Name: "deviceRequest", + DeviceClassName: "deviceClass", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }, + }, + }, + }, + Status: resourceapis.ResourceClaimStatus{ + Allocation: &resourceapis.AllocationResult{ + Controller: "dra.example.com", + }, + DeallocationRequested: true, + }, + }, + // Columns: Name, State, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaim", "allocated,deallocating", "5m"}}}, + }, + { + name: "ResourceClaim with Allocated and Reserved State", + resourceClaim: resourceapis.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaim", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{ + { + Name: "deviceRequest", + DeviceClassName: "deviceClass", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }, + }, + }, + }, + Status: resourceapis.ResourceClaimStatus{ + Allocation: &resourceapis.AllocationResult{ + Controller: "dra.example.com", + }, + ReservedFor: []resourceapis.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "pod-test", + UID: types.UID("pod-test"), + }, + }, + DeallocationRequested: true, + }, + }, + // Columns: Name, State, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaim", "allocated,reserved", "5m"}}}, + }, + { + name: "ResourceClaim with Deleted State", + resourceClaim: resourceapis.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaim", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + DeletionTimestamp: &metav1.Time{Time: time.Now()}, + }, + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{ + { + Name: "deviceRequest", + DeviceClassName: "deviceClass", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }, + }, + }, + }, + }, + // Columns: Name, State, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaim", "deleted", "5m"}}}, + }, + } + + for i, test := range tests { + rows, err := printResourceClaim(&test.resourceClaim, printers.GenerateOptions{}) + if err != nil { + t.Fatal(err) + } + for i := range rows { + rows[i].Object.Object = nil + } + if !reflect.DeepEqual(test.expected, rows) { + t.Errorf("%d mismatch: %s", i, cmp.Diff(test.expected, rows)) + } + } +} + +func TestPrintResourceClaimTemplate(t *testing.T) { + + tests := []struct { + resourceClaimTemplate resourceapis.ResourceClaimTemplate + expected []metav1.TableRow + }{ + { + resourceClaimTemplate: resourceapis.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaimtemplate", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.ResourceClaimTemplateSpec{ + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{{ + Name: "test-deviceRequest", + DeviceClassName: "deviceClassName", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }}, + }, + }, + }, + }, + // Columns: Name, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaimtemplate", "5m"}}}, + }, + { + // test case for Empty creation timestamp that is translated to + resourceClaimTemplate: resourceapis.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceclaimtemplate", + CreationTimestamp: metav1.Time{}, + }, + Spec: resourceapis.ResourceClaimTemplateSpec{ + Spec: resourceapis.ResourceClaimSpec{ + Devices: resourceapis.DeviceClaim{ + Requests: []resourceapis.DeviceRequest{{ + Name: "test-deviceRequest", + DeviceClassName: "deviceClassName", + AllocationMode: resourceapis.DeviceAllocationModeExactCount, + Count: 1, + }}, + }, + }, + }, + }, + // Columns: Name, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceclaimtemplate", ""}}}, + }, + } + + for i, test := range tests { + rows, err := printResourceClaimTemplate(&test.resourceClaimTemplate, printers.GenerateOptions{}) + if err != nil { + t.Fatal(err) + } + for i := range rows { + rows[i].Object.Object = nil + } + if !reflect.DeepEqual(test.expected, rows) { + t.Errorf("%d mismatch: %s", i, cmp.Diff(test.expected, rows)) + } + } +} + +func TestPrintPodSchedulingContext(t *testing.T) { + + tests := []struct { + name string + podSchedulingContext resourceapis.PodSchedulingContext + expected []metav1.TableRow + }{ + { + name: "PodSchedulingContext with SelectedNode", + podSchedulingContext: resourceapis.PodSchedulingContext{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-podschedulercontext", + Namespace: "default", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.PodSchedulingContextSpec{ + SelectedNode: "worker", + }, + Status: resourceapis.PodSchedulingContextStatus{}, + }, + + // Columns: Name, SelectedNode, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-podschedulercontext", "worker", "5m"}}}, + }, + { + // test case for Empty creation timestamp that is translated to + name: "PodSchedulingContext with SelectedNode and Empty creation timestamp", + podSchedulingContext: resourceapis.PodSchedulingContext{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-podschedulercontext", + Namespace: "default", + CreationTimestamp: metav1.Time{}, + }, + Spec: resourceapis.PodSchedulingContextSpec{ + SelectedNode: "worker", + }, + Status: resourceapis.PodSchedulingContextStatus{}, + }, + + // Columns: Name, SelectedNode, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-podschedulercontext", "worker", ""}}}, + }, + { + name: "PodSchedulingContext without SelectedNode", + podSchedulingContext: resourceapis.PodSchedulingContext{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-podschedulercontext", + Namespace: "default", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.PodSchedulingContextSpec{}, + Status: resourceapis.PodSchedulingContextStatus{}, + }, + + // Columns: Name, SelectedNode, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-podschedulercontext", "", "5m"}}}, + }, + } + + for i, test := range tests { + rows, err := printPodSchedulingContext(&test.podSchedulingContext, printers.GenerateOptions{}) + if err != nil { + t.Fatal(err) + } + for i := range rows { + rows[i].Object.Object = nil + } + if !reflect.DeepEqual(test.expected, rows) { + t.Errorf("%d mismatch: %s", i, cmp.Diff(test.expected, rows)) + } + } +} + +func TestPrintResourceSlice(t *testing.T) { + + tests := []struct { + resourceSlice resourceapis.ResourceSlice + expected []metav1.TableRow + }{ + { + resourceSlice: resourceapis.ResourceSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceslice", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)}, + }, + Spec: resourceapis.ResourceSliceSpec{ + NodeName: "nodeName", + Driver: "driverName", + Pool: resourceapis.ResourcePool{ + Name: "poolName", + ResourceSliceCount: 1, + }, + }, + }, + // Columns: Name, Node, Driver, Pool, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceslice", "nodeName", "driverName", "poolName", "5m"}}}, + }, + { + resourceSlice: resourceapis.ResourceSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-resourceslice", + CreationTimestamp: metav1.Time{}, + }, + Spec: resourceapis.ResourceSliceSpec{ + NodeName: "nodeName", + Driver: "driverName", + Pool: resourceapis.ResourcePool{ + Name: "poolName", + ResourceSliceCount: 1, + }, + }, + }, + // Columns: Name, Node, Driver, Pool, Age + expected: []metav1.TableRow{{Cells: []interface{}{"test-resourceslice", "nodeName", "driverName", "poolName", ""}}}, + }, + } + + for i, test := range tests { + rows, err := printResourceSlice(&test.resourceSlice, printers.GenerateOptions{}) + if err != nil { + t.Fatal(err) + } + for i := range rows { + rows[i].Object.Object = nil + } + if !reflect.DeepEqual(test.expected, rows) { + t.Errorf("%d mismatch: %s", i, cmp.Diff(test.expected, rows)) + } + } +} + func TestPrintPriorityLevelConfiguration(t *testing.T) { tests := []struct { pl flowcontrol.PriorityLevelConfiguration @@ -6735,6 +7157,36 @@ func TestTableRowDeepCopyShouldNotPanic(t *testing.T) { return printStatus(&metav1.Status{}, printers.GenerateOptions{}) }, }, + { + name: "DeviceClass", + printer: func() ([]metav1.TableRow, error) { + return printDeviceClass(&resourceapis.DeviceClass{}, printers.GenerateOptions{}) + }, + }, + { + name: "ResourceClaim", + printer: func() ([]metav1.TableRow, error) { + return printResourceClaim(&resourceapis.ResourceClaim{}, printers.GenerateOptions{}) + }, + }, + { + name: "ResourceClaimTemplate", + printer: func() ([]metav1.TableRow, error) { + return printResourceClaimTemplate(&resourceapis.ResourceClaimTemplate{}, printers.GenerateOptions{}) + }, + }, + { + name: "PodSchedulingContext", + printer: func() ([]metav1.TableRow, error) { + return printPodSchedulingContext(&resourceapis.PodSchedulingContext{}, printers.GenerateOptions{}) + }, + }, + { + name: "ResourceSlice", + printer: func() ([]metav1.TableRow, error) { + return printResourceSlice(&resourceapis.ResourceSlice{}, printers.GenerateOptions{}) + }, + }, } for _, test := range tests {