diff --git a/README.md b/README.md index cd537e7..f2d8f8b 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ The driver features an advanced resource filtering system that enables administr ## Features - **Dynamic Resource Allocation**: Leverages Kubernetes DRA framework for SR-IOV VF management -- **Advanced Resource Filtering**: Fine-grained filtering of Virtual Functions based on hardware attributes -- **Custom Resource Definitions**: SriovResourceFilter CRD for configuring device filtering policies -- **Controller-based Management**: Kubernetes controller pattern for resource filter lifecycle management +- **Opt-In Device Advertisement**: Devices are only advertised when explicitly defined in a policy +- **Custom Resource Definitions**: SriovResourcePolicy CRD for configuring device advertisement policies +- **Controller-based Management**: Kubernetes controller pattern for resource policy lifecycle management - **Multiple Resource Types**: Support for exposing different VF pools as distinct resource types -- **Node-targeted Filtering**: Per-node resource filtering with node selector support +- **Node-targeted Policies**: Per-node resource policies with node selector support - **CDI Integration**: Uses Container Device Interface for device injection into containers - **NRI Integration**: Node Resource Interface support for advanced container runtime interaction - **Kubernetes Native**: Integrates seamlessly with standard Kubernetes resource request/limit model @@ -79,7 +79,7 @@ The Helm chart supports various configuration options through `values.yaml`: - **Image Configuration**: Customize image repository, tag, and pull policy - **Resource Limits**: Set resource requests and limits for driver components - **Node Selection**: Configure node selectors and tolerations -- **Namespace Configuration**: Configure the namespace where SriovResourceFilter resources are watched +- **Namespace Configuration**: Configure the namespace where SriovResourcePolicy resources are watched - **Default Interface Prefix**: Set the default interface prefix for virtual functions - **CDI Root**: Configure the directory for CDI file generation - **Logging**: Adjust log verbosity and format @@ -137,17 +137,19 @@ spec: ## Resource Filtering System -The DRA driver includes an advanced resource filtering system that allows administrators to define fine-grained policies for how SR-IOV Virtual Functions are exposed and allocated. This system uses Custom Resource Definitions (CRDs) and a Kubernetes controller to manage device filtering based on hardware characteristics. +The DRA driver uses an opt-in model where administrators explicitly define which SR-IOV Virtual Functions should be advertised as Kubernetes resources. This system uses Custom Resource Definitions (CRDs) and a Kubernetes controller to manage device advertisement policies based on hardware characteristics. -### SriovResourceFilter CRD +**Important**: Without a matching `SriovResourcePolicy`, no devices will be advertised. -The `SriovResourceFilter` custom resource allows you to define filtering policies for SR-IOV devices: +### SriovResourcePolicy CRD + +The `SriovResourcePolicy` custom resource defines which SR-IOV devices should be advertised as allocatable resources: ```yaml apiVersion: sriovnetwork.k8snetworkplumbingwg.io/v1alpha1 -kind: SriovResourceFilter +kind: SriovResourcePolicy metadata: - name: example-filter + name: example-policy namespace: dra-sriov-driver spec: nodeSelector: @@ -207,9 +209,9 @@ spec: pfNames: ["eth1"] ``` -### Using Filtered Resources +### Using Policy-Defined Resources -Once a `SriovResourceFilter` is applied, pods can request specific resource types using CEL expressions: +Once a `SriovResourcePolicy` is applied, devices matching the policy are advertised and pods can request specific resource types using CEL expressions: ```yaml apiVersion: resource.k8s.io/v1 @@ -302,11 +304,11 @@ Demonstrates requesting multiple Virtual Functions in a single resource claim: - VfConfig applies to all allocated VFs in the claim - Automatic interface naming (typically net1, net2, etc.) -#### Resource Filtering (`demo/resource-filtering/`) -Shows how to use SriovResourceFilter for advanced device management: -- Filter VFs based on vendor ID, Physical Function names, and hardware attributes +#### Resource Policies (`demo/resource-policies/`) +Shows how to use SriovResourcePolicy for controlling device advertisement: +- Advertise VFs based on vendor ID, Physical Function names, and hardware attributes - Multiple resource configurations for different network interfaces -- Node-targeted filtering with selector support +- Node-targeted policies with selector support #### VFIO Driver Configuration (`demo/vfio-driver/`) Illustrates VFIO-PCI driver configuration for userspace applications: @@ -326,10 +328,10 @@ Illustrates VFIO-PCI driver configuration for userspace applications: │ └── dra-driver-sriov/ # Main driver executable ├── pkg/ │ ├── driver/ # Core driver implementation -│ ├── controller/ # Kubernetes controller for resource filtering +│ ├── controller/ # Kubernetes controller for resource policies │ ├── devicestate/ # Device state management and discovery │ ├── api/ # API definitions -│ │ ├── sriovdra/v1alpha1/ # SriovResourceFilter CRD definitions +│ │ ├── sriovdra/v1alpha1/ # SriovResourcePolicy CRD definitions │ │ └── virtualfunction/v1alpha1/ # Virtual Function API types │ ├── cdi/ # CDI integration │ ├── cni/ # CNI plugin integration @@ -345,7 +347,7 @@ Illustrates VFIO-PCI driver configuration for userspace applications: ├── demo/ # Example workload configurations │ ├── single-vf-claim/ # Single VF allocation example │ ├── multiple-vf-claim/ # Multiple VF allocation example -│ ├── resource-filtering/ # Resource filtering configuration example +│ ├── resource-policies/ # Resource policy configuration example │ └── vfio-driver/ # VFIO-PCI driver configuration example ├── hack/ # Build and development scripts ├── test/ # Test suites @@ -355,9 +357,9 @@ Illustrates VFIO-PCI driver configuration for userspace applications: ### Key Components - **Driver**: Main gRPC service implementing DRA kubelet plugin interface -- **Resource Filter Controller**: Kubernetes controller managing SriovResourceFilter lifecycle and device filtering -- **Device State Manager**: Tracks available and allocated SR-IOV virtual functions with filtering support -- **SriovResourceFilter CRD**: Custom resource for defining device filtering policies +- **Resource Policy Controller**: Kubernetes controller managing SriovResourcePolicy lifecycle and device advertisement +- **Device State Manager**: Tracks available and allocated SR-IOV virtual functions +- **SriovResourcePolicy CRD**: Custom resource for defining device advertisement policies (opt-in model) - **CDI Generator**: Creates Container Device Interface specifications for VFs - **NRI Plugin**: Node Resource Interface integration for container runtime interaction - **Pod Manager**: Manages pod lifecycle and resource allocation diff --git a/cmd/dra-driver-sriov/main.go b/cmd/dra-driver-sriov/main.go index 111c51f..d06ad5d 100644 --- a/cmd/dra-driver-sriov/main.go +++ b/cmd/dra-driver-sriov/main.go @@ -86,7 +86,7 @@ func newApp() *cli.App { }, &cli.StringFlag{ Name: "namespace", - Usage: "Namespace where the driver should watch for SriovResourceFilter resources.", + Usage: "Namespace where the driver should watch for SriovResourcePolicy resources.", Value: "dra-sriov-driver", Destination: &flagsOptions.Namespace, EnvVars: []string{"NAMESPACE"}, @@ -188,11 +188,11 @@ func RunPlugin(ctx context.Context, config *types.Config) error { logger.Info("Configuring controller manager", "namespace", config.Flags.Namespace) - // Configure cache to only watch resources in the specified namespace for SriovResourceFilter + // Configure cache to only watch resources in the specified namespace for SriovResourcePolicy // while allowing cluster-wide access for other resources like Nodes cacheOpts := cache.Options{ ByObject: map[client.Object]cache.ByObject{ - &sriovdrav1alpha1.SriovResourceFilter{}: { + &sriovdrav1alpha1.SriovResourcePolicy{}: { Namespaces: map[string]cache.Config{ config.Flags.Namespace: {}, }, @@ -209,10 +209,10 @@ func RunPlugin(ctx context.Context, config *types.Config) error { return fmt.Errorf("failed to create controller manager: %w", err) } - // create and setup resource filter controller - resourceFilterController := controller.NewSriovResourceFilterReconciler(config.K8sClient.Client, config.Flags.NodeName, config.Flags.Namespace, deviceStateManager) - if err := resourceFilterController.SetupWithManager(mgr); err != nil { - return fmt.Errorf("failed to setup resource filter controller: %w", err) + // create and setup resource policy controller + resourcePolicyController := controller.NewSriovResourcePolicyReconciler(config.K8sClient.Client, config.Flags.NodeName, config.Flags.Namespace, deviceStateManager) + if err := resourcePolicyController.SetupWithManager(mgr); err != nil { + return fmt.Errorf("failed to setup resource policy controller: %w", err) } // start controller manager diff --git a/demo/resource-filtering/README.md b/demo/resource-policies/README.md similarity index 65% rename from demo/resource-filtering/README.md rename to demo/resource-policies/README.md index 0cf352b..1025b00 100644 --- a/demo/resource-filtering/README.md +++ b/demo/resource-policies/README.md @@ -1,18 +1,18 @@ -# Resource Filtering Demo +# Resource Policy Demo -This demo showcases how to use `SriovResourceFilter` to filter and manage SR-IOV Virtual Functions based on various hardware and configuration criteria. +This demo showcases how to use `SriovResourcePolicy` to control which SR-IOV Virtual Functions are advertised as Kubernetes resources based on various hardware and configuration criteria. ## Overview This scenario demonstrates: -- Creating resource filters based on vendor IDs, Physical Function names, and other hardware attributes +- Creating resource policies based on vendor IDs, Physical Function names, and other hardware attributes - Setting up multiple resource configurations for different network interfaces -- Deploying a pod that uses filtered SR-IOV resources with specific network requirements +- Deploying a pod that uses policy-filtered SR-IOV resources with specific network requirements ## Components -### 1. SriovResourceFilter -The `SriovResourceFilter` resource defines how to filter available SR-IOV devices: +### 1. SriovResourcePolicy +The `SriovResourcePolicy` resource defines which SR-IOV devices should be advertised as allocatable resources: - **nodeSelector**: Targets specific nodes (`dra-ctlplane-0.dra.lab` in this example) - **configs**: Defines multiple resource configurations: - `eth0_resource`: Filters devices connected to eth0 Physical Function @@ -39,17 +39,20 @@ The `SriovResourceFilter` resource defines how to filter available SR-IOV device ## Usage -1. Apply the resource filter to make filtered resources available: +1. Apply the resource policy to advertise SR-IOV resources: ```bash - kubectl apply -f resource-filter.yaml + kubectl apply -f resource-policy.yaml ``` -2. The DRA driver will discover and filter SR-IOV devices based on the criteria -3. Pods can then claim resources using the filtered resource names +2. The DRA driver will discover SR-IOV devices and advertise only those matching the policy criteria +3. Pods can then claim resources using the advertised resource names 4. The pod will be scheduled on nodes where matching resources are available +**Note**: Without a matching `SriovResourcePolicy`, no devices will be advertised (opt-in model). + ## Key Features +- **Opt-In Model**: Devices are only advertised when explicitly defined in a policy - **Granular Filtering**: Filter by vendor, device ID, PCI address, PF name, NUMA node, or driver - **Multi-Resource Support**: Configure multiple resource types on the same node - **CEL Integration**: Use Common Expression Language for advanced resource selection diff --git a/demo/resource-filtering/resource-filter.yaml b/demo/resource-policies/resource-policy.yaml similarity index 98% rename from demo/resource-filtering/resource-filter.yaml rename to demo/resource-policies/resource-policy.yaml index 088d15a..f167e95 100644 --- a/demo/resource-filtering/resource-filter.yaml +++ b/demo/resource-policies/resource-policy.yaml @@ -1,7 +1,7 @@ apiVersion: sriovnetwork.k8snetworkplumbingwg.io/v1alpha1 -kind: SriovResourceFilter +kind: SriovResourcePolicy metadata: - name: example-resource-filter + name: example-resource-policy namespace: dra-sriov-driver spec: # NodeSelector to match specific nodes diff --git a/deployments/helm/dra-driver-sriov/templates/clusterrole.yaml b/deployments/helm/dra-driver-sriov/templates/clusterrole.yaml index db7f2ed..f1cc3b1 100644 --- a/deployments/helm/dra-driver-sriov/templates/clusterrole.yaml +++ b/deployments/helm/dra-driver-sriov/templates/clusterrole.yaml @@ -21,5 +21,5 @@ rules: resources: ["network-attachment-definitions"] verbs: ["get"] - apiGroups: ["sriovnetwork.k8snetworkplumbingwg.io"] - resources: ["sriovresourcefilters"] - verbs: ["get", "list", "watch"] # SriovResourceFilter resources + resources: ["sriovresourcepolicies"] + verbs: ["get", "list", "watch"] # SriovResourcePolicy resources diff --git a/deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcefilters.yaml b/deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcepolicies.yaml similarity index 87% rename from deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcefilters.yaml rename to deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcepolicies.yaml index 4689011..72ebffd 100644 --- a/deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcefilters.yaml +++ b/deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcepolicies.yaml @@ -4,20 +4,21 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.20.0 - name: sriovresourcefilters.sriovnetwork.k8snetworkplumbingwg.io + name: sriovresourcepolicies.sriovnetwork.k8snetworkplumbingwg.io spec: group: sriovnetwork.k8snetworkplumbingwg.io names: - kind: SriovResourceFilter - listKind: SriovResourceFilterList - plural: sriovresourcefilters - singular: sriovresourcefilter + kind: SriovResourcePolicy + listKind: SriovResourcePolicyList + plural: sriovresourcepolicies + singular: sriovresourcepolicy scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: - description: SriovResourceFilter is a filter for SR-IOV resources + description: SriovResourcePolicy defines a policy for advertising SR-IOV devices + as Kubernetes resources properties: apiVersion: description: |- @@ -37,7 +38,7 @@ spec: metadata: type: object spec: - description: SriovResourceFilterSpec is the spec for a SriovResourceFilter + description: SriovResourcePolicySpec is the spec for a SriovResourcePolicy properties: configs: items: diff --git a/pkg/api/sriovdra/v1alpha1/api.go b/pkg/api/sriovdra/v1alpha1/api.go index 87cff3c..05b99d5 100644 --- a/pkg/api/sriovdra/v1alpha1/api.go +++ b/pkg/api/sriovdra/v1alpha1/api.go @@ -22,21 +22,21 @@ import ( //nolint:gochecknoinits // Required for Kubernetes scheme registration func init() { - SchemeBuilder.Register(&SriovResourceFilter{}, &SriovResourceFilterList{}) + SchemeBuilder.Register(&SriovResourcePolicy{}, &SriovResourcePolicyList{}) } // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// SriovResourceFilter is a filter for SR-IOV resources -type SriovResourceFilter struct { +// SriovResourcePolicy defines a policy for advertising SR-IOV devices as Kubernetes resources +type SriovResourcePolicy struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec SriovResourceFilterSpec `json:"spec"` + Spec SriovResourcePolicySpec `json:"spec"` } -// SriovResourceFilterSpec is the spec for a SriovResourceFilter -type SriovResourceFilterSpec struct { +// SriovResourcePolicySpec is the spec for a SriovResourcePolicy +type SriovResourcePolicySpec struct { NodeSelector map[string]string `json:"nodeSelector,omitempty"` Configs []Config `json:"configs,omitempty"` } @@ -60,9 +60,9 @@ type ResourceFilter struct { // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// SriovResourceFilterList contains a list of SriovResourceFilter -type SriovResourceFilterList struct { +// SriovResourcePolicyList contains a list of SriovResourcePolicy +type SriovResourcePolicyList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []SriovResourceFilter `json:"items"` + Items []SriovResourcePolicy `json:"items"` } diff --git a/pkg/api/sriovdra/v1alpha1/zz_generated.deepcopy.go b/pkg/api/sriovdra/v1alpha1/zz_generated.deepcopy.go index 295e5a2..18ee75a 100644 --- a/pkg/api/sriovdra/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/sriovdra/v1alpha1/zz_generated.deepcopy.go @@ -97,25 +97,25 @@ func (in *ResourceFilter) DeepCopy() *ResourceFilter { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SriovResourceFilter) DeepCopyInto(out *SriovResourceFilter) { +func (in *SriovResourcePolicy) DeepCopyInto(out *SriovResourcePolicy) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourceFilter. -func (in *SriovResourceFilter) DeepCopy() *SriovResourceFilter { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourcePolicy. +func (in *SriovResourcePolicy) DeepCopy() *SriovResourcePolicy { if in == nil { return nil } - out := new(SriovResourceFilter) + out := new(SriovResourcePolicy) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SriovResourceFilter) DeepCopyObject() runtime.Object { +func (in *SriovResourcePolicy) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -123,31 +123,31 @@ func (in *SriovResourceFilter) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SriovResourceFilterList) DeepCopyInto(out *SriovResourceFilterList) { +func (in *SriovResourcePolicyList) DeepCopyInto(out *SriovResourcePolicyList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]SriovResourceFilter, len(*in)) + *out = make([]SriovResourcePolicy, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourceFilterList. -func (in *SriovResourceFilterList) DeepCopy() *SriovResourceFilterList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourcePolicyList. +func (in *SriovResourcePolicyList) DeepCopy() *SriovResourcePolicyList { if in == nil { return nil } - out := new(SriovResourceFilterList) + out := new(SriovResourcePolicyList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SriovResourceFilterList) DeepCopyObject() runtime.Object { +func (in *SriovResourcePolicyList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -155,7 +155,7 @@ func (in *SriovResourceFilterList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SriovResourceFilterSpec) DeepCopyInto(out *SriovResourceFilterSpec) { +func (in *SriovResourcePolicySpec) DeepCopyInto(out *SriovResourcePolicySpec) { *out = *in if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector @@ -173,12 +173,12 @@ func (in *SriovResourceFilterSpec) DeepCopyInto(out *SriovResourceFilterSpec) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourceFilterSpec. -func (in *SriovResourceFilterSpec) DeepCopy() *SriovResourceFilterSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SriovResourcePolicySpec. +func (in *SriovResourcePolicySpec) DeepCopy() *SriovResourcePolicySpec { if in == nil { return nil } - out := new(SriovResourceFilterSpec) + out := new(SriovResourcePolicySpec) in.DeepCopyInto(out) return out } diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go index 7c9e12c..db961cb 100644 --- a/pkg/controller/controller_test.go +++ b/pkg/controller/controller_test.go @@ -41,7 +41,7 @@ var ( mgr ctrl.Manager cancelFunc context.CancelFunc - reconciler *controller.SriovResourceFilterReconciler + reconciler *controller.SriovResourcePolicyReconciler applied map[string]string ) @@ -53,7 +53,7 @@ var _ = BeforeSuite(func(ctx SpecContext) { testEnv = &envtest.Environment{ CRDInstallOptions: envtest.CRDInstallOptions{ Paths: []string{ - "../../deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcefilters.yaml", + "../../deployments/helm/dra-driver-sriov/templates/sriovnetwork.k8snetworkplumbingwg.io_sriovresourcepolicies.yaml", }, }, ErrorIfCRDPathMissing: true, @@ -89,7 +89,7 @@ var _ = BeforeSuite(func(ctx SpecContext) { func(_ context.Context, m map[string]string) error { applied = m; return nil }, ) - reconciler = controller.NewSriovResourceFilterReconciler(mgr.GetClient(), "test-node", "dra-sriov-driver", devState) + reconciler = controller.NewSriovResourcePolicyReconciler(mgr.GetClient(), "test-node", "dra-sriov-driver", devState) Expect(reconciler.SetupWithManager(mgr)).To(Succeed()) var startCtx context.Context @@ -147,18 +147,18 @@ func defaultAllocatableDevices() drasriovtypes.AllocatableDevices { } } -var _ = Describe("SriovResourceFilterReconciler (envtest)", func() { - It("should handle no filters in namespace", func(ctx SpecContext) { +var _ = Describe("SriovResourcePolicyReconciler (envtest)", func() { + It("should handle no policies in namespace", func(ctx SpecContext) { Consistently(func() bool { - return reconciler.GetCurrentResourceFilter() == nil + return reconciler.GetCurrentResourcePolicy() == nil }, 500*time.Millisecond, 100*time.Millisecond).Should(BeTrue()) Expect(applied).To(HaveLen(0)) }) - It("should select filter with empty nodeSelector and apply to devices", func(ctx SpecContext) { - filter := &sriovdrav1alpha1.SriovResourceFilter{ - ObjectMeta: metav1.ObjectMeta{Name: "rf-empty-selector", Namespace: "dra-sriov-driver"}, - Spec: sriovdrav1alpha1.SriovResourceFilterSpec{ + It("should select policy with empty nodeSelector and apply to devices", func(ctx SpecContext) { + policy := &sriovdrav1alpha1.SriovResourcePolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "rp-empty-selector", Namespace: "dra-sriov-driver"}, + Spec: sriovdrav1alpha1.SriovResourcePolicySpec{ NodeSelector: map[string]string{}, Configs: []sriovdrav1alpha1.Config{{ ResourceName: "example.com/resA", @@ -166,12 +166,12 @@ var _ = Describe("SriovResourceFilterReconciler (envtest)", func() { }}, }, } - Expect(k8sClient.Create(ctx, filter)).To(Succeed()) + Expect(k8sClient.Create(ctx, policy)).To(Succeed()) - Eventually(func() *sriovdrav1alpha1.SriovResourceFilter { - return reconciler.GetCurrentResourceFilter() + Eventually(func() *sriovdrav1alpha1.SriovResourcePolicy { + return reconciler.GetCurrentResourcePolicy() }, 5*time.Second, 200*time.Millisecond).ShouldNot(BeNil()) - Expect(reconciler.HasResourceFilter()).To(BeTrue()) + Expect(reconciler.HasResourcePolicy()).To(BeTrue()) Expect(reconciler.GetResourceNames()).To(ContainElement("example.com/resA")) Eventually(func() int { return len(applied) }, 2*time.Second, 100*time.Millisecond).Should(BeNumerically(">=", 1)) @@ -181,26 +181,26 @@ var _ = Describe("SriovResourceFilterReconciler (envtest)", func() { otherNS := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "other-ns"}} Expect(k8sClient.Create(ctx, otherNS)).To(Succeed()) - filter := &sriovdrav1alpha1.SriovResourceFilter{ - ObjectMeta: metav1.ObjectMeta{Name: "rf-other-ns", Namespace: "other-ns"}, - Spec: sriovdrav1alpha1.SriovResourceFilterSpec{Configs: []sriovdrav1alpha1.Config{{ResourceName: "example.com/ignored"}}}, + policy := &sriovdrav1alpha1.SriovResourcePolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "rp-other-ns", Namespace: "other-ns"}, + Spec: sriovdrav1alpha1.SriovResourcePolicySpec{Configs: []sriovdrav1alpha1.Config{{ResourceName: "example.com/ignored"}}}, } - Expect(k8sClient.Create(ctx, filter)).To(Succeed()) + Expect(k8sClient.Create(ctx, policy)).To(Succeed()) Consistently(func() []string { return reconciler.GetResourceNames() }, 1*time.Second, 200*time.Millisecond).Should(ContainElement("example.com/resA")) }) - It("should handle multiple matching filters by clearing current filter", func(ctx SpecContext) { - filter := &sriovdrav1alpha1.SriovResourceFilter{ - ObjectMeta: metav1.ObjectMeta{Name: "rf-duplicate", Namespace: "dra-sriov-driver"}, - Spec: sriovdrav1alpha1.SriovResourceFilterSpec{ + It("should handle multiple matching policies by clearing current policy", func(ctx SpecContext) { + policy := &sriovdrav1alpha1.SriovResourcePolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "rp-duplicate", Namespace: "dra-sriov-driver"}, + Spec: sriovdrav1alpha1.SriovResourcePolicySpec{ NodeSelector: map[string]string{}, Configs: []sriovdrav1alpha1.Config{{ResourceName: "example.com/resB"}}, }, } - Expect(k8sClient.Create(ctx, filter)).To(Succeed()) + Expect(k8sClient.Create(ctx, policy)).To(Succeed()) - Eventually(func() bool { return reconciler.GetCurrentResourceFilter() == nil }, 5*time.Second, 200*time.Millisecond).Should(BeTrue()) + Eventually(func() bool { return reconciler.GetCurrentResourcePolicy() == nil }, 5*time.Second, 200*time.Millisecond).Should(BeTrue()) }) It("should reselect when node labels change", func(ctx SpecContext) { @@ -212,27 +212,27 @@ var _ = Describe("SriovResourceFilterReconciler (envtest)", func() { node.Labels["role"] = "dpdk" Expect(k8sClient.Update(ctx, node)).To(Succeed()) - for _, name := range []string{"rf-empty-selector", "rf-duplicate"} { - rf := &sriovdrav1alpha1.SriovResourceFilter{} - if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "dra-sriov-driver", Name: name}, rf); err == nil { - _ = k8sClient.Delete(ctx, rf) + for _, name := range []string{"rp-empty-selector", "rp-duplicate"} { + rp := &sriovdrav1alpha1.SriovResourcePolicy{} + if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "dra-sriov-driver", Name: name}, rp); err == nil { + _ = k8sClient.Delete(ctx, rp) } } - filter := &sriovdrav1alpha1.SriovResourceFilter{ - ObjectMeta: metav1.ObjectMeta{Name: "rf-node-select", Namespace: "dra-sriov-driver"}, - Spec: sriovdrav1alpha1.SriovResourceFilterSpec{ + policy := &sriovdrav1alpha1.SriovResourcePolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "rp-node-select", Namespace: "dra-sriov-driver"}, + Spec: sriovdrav1alpha1.SriovResourcePolicySpec{ NodeSelector: map[string]string{"role": "dpdk"}, Configs: []sriovdrav1alpha1.Config{{ResourceName: "example.com/resC"}}, }, } - Expect(k8sClient.Create(ctx, filter)).To(Succeed()) + Expect(k8sClient.Create(ctx, policy)).To(Succeed()) Eventually(func() []string { return reconciler.GetResourceNames() }, 5*time.Second, 200*time.Millisecond).Should(ContainElement("example.com/resC")) }) It("should requeue when node is missing (direct Reconcile call)", func(ctx SpecContext) { - bogus := controller.NewSriovResourceFilterReconciler(k8sClient, "missing-node", "dra-sriov-driver", nil) + bogus := controller.NewSriovResourcePolicyReconciler(k8sClient, "missing-node", "dra-sriov-driver", nil) result, err := bogus.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{Name: "irrelevant", Namespace: "dra-sriov-driver"}}) Expect(err).To(BeNil()) Expect(result.RequeueAfter).NotTo(BeZero()) diff --git a/pkg/controller/resourcefiltercontroller.go b/pkg/controller/resourcepolicycontroller.go similarity index 71% rename from pkg/controller/resourcefiltercontroller.go rename to pkg/controller/resourcepolicycontroller.go index 415f020..33922c6 100644 --- a/pkg/controller/resourcefiltercontroller.go +++ b/pkg/controller/resourcepolicycontroller.go @@ -45,32 +45,32 @@ import ( ) const ( - resourceFilterSyncEventName = "resource-filter-sync" + resourcePolicySyncEventName = "resource-policy-sync" ) -// SriovResourceFilterReconciler reconciles SriovResourceFilter objects -type SriovResourceFilterReconciler struct { +// SriovResourcePolicyReconciler reconciles SriovResourcePolicy objects +type SriovResourcePolicyReconciler struct { client.Client nodeName string namespace string - currentResourceFilter *sriovdrav1alpha1.SriovResourceFilter + currentResourcePolicy *sriovdrav1alpha1.SriovResourcePolicy log klog.Logger deviceStateManager devicestate.DeviceState } -// NewSriovResourceFilterReconciler creates a new SriovResourceFilterReconciler -func NewSriovResourceFilterReconciler(client client.Client, nodeName, namespace string, deviceStateManager devicestate.DeviceState) *SriovResourceFilterReconciler { - return &SriovResourceFilterReconciler{ +// NewSriovResourcePolicyReconciler creates a new SriovResourcePolicyReconciler +func NewSriovResourcePolicyReconciler(client client.Client, nodeName, namespace string, deviceStateManager devicestate.DeviceState) *SriovResourcePolicyReconciler { + return &SriovResourcePolicyReconciler{ Client: client, deviceStateManager: deviceStateManager, nodeName: nodeName, namespace: namespace, - log: klog.Background().WithName("SriovResourceFilter"), + log: klog.Background().WithName("SriovResourcePolicy"), } } -// Reconcile handles the reconciliation of SriovResourceFilter resources -func (r *SriovResourceFilterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +// Reconcile handles the reconciliation of SriovResourcePolicy resources +func (r *SriovResourcePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { r.log.Info("Starting reconcile", "request", req.NamespacedName, "watchedNamespace", r.namespace) // Get the current node to check its labels @@ -85,98 +85,98 @@ func (r *SriovResourceFilterReconciler) Reconcile(ctx context.Context, req ctrl. return ctrl.Result{}, err } - // List all SriovResourceFilter objects in the operator namespace - resourceFilterList := &sriovdrav1alpha1.SriovResourceFilterList{} - if err := r.List(ctx, resourceFilterList, client.InNamespace(r.namespace)); err != nil { - r.log.Error(err, "Failed to list SriovResourceFilter objects", "namespace", r.namespace) + // List all SriovResourcePolicy objects in the operator namespace + resourcePolicyList := &sriovdrav1alpha1.SriovResourcePolicyList{} + if err := r.List(ctx, resourcePolicyList, client.InNamespace(r.namespace)); err != nil { + r.log.Error(err, "Failed to list SriovResourcePolicy objects", "namespace", r.namespace) return ctrl.Result{}, err } - // Find matching resource filters for this node - var matchingFilters []*sriovdrav1alpha1.SriovResourceFilter - for i := range resourceFilterList.Items { - filter := &resourceFilterList.Items[i] - if r.matchesNodeSelector(node.Labels, filter.Spec.NodeSelector) { - matchingFilters = append(matchingFilters, filter) + // Find matching resource policies for this node + var matchingPolicies []*sriovdrav1alpha1.SriovResourcePolicy + for i := range resourcePolicyList.Items { + policy := &resourcePolicyList.Items[i] + if r.matchesNodeSelector(node.Labels, policy.Spec.NodeSelector) { + matchingPolicies = append(matchingPolicies, policy) } } // Handle the results - switch len(matchingFilters) { + switch len(matchingPolicies) { case 0: - r.log.Info("No matching SriovResourceFilter found for node", "nodeName", r.nodeName) - r.currentResourceFilter = nil - // Clear resource filter from devices since no filter matches - if err := r.applyResourceFilterToDevices(ctx); err != nil { - r.log.Error(err, "Failed to clear resource filter from devices") + r.log.Info("No matching SriovResourcePolicy found for node", "nodeName", r.nodeName) + r.currentResourcePolicy = nil + // Clear resource policy from devices since no policy matches + if err := r.applyResourcePolicyToDevices(ctx); err != nil { + r.log.Error(err, "Failed to clear resource policy from devices") return ctrl.Result{}, err } case 1: - r.log.Info("Found matching SriovResourceFilter for node", "nodeName", r.nodeName, "filter", matchingFilters[0].Name) - r.currentResourceFilter = matchingFilters[0] - // Apply resource filter to devices - if err := r.applyResourceFilterToDevices(ctx); err != nil { - r.log.Error(err, "Failed to apply resource filter to devices") + r.log.Info("Found matching SriovResourcePolicy for node", "nodeName", r.nodeName, "policy", matchingPolicies[0].Name) + r.currentResourcePolicy = matchingPolicies[0] + // Apply resource policy to devices + if err := r.applyResourcePolicyToDevices(ctx); err != nil { + r.log.Error(err, "Failed to apply resource policy to devices") return ctrl.Result{}, err } default: // Multiple matches - log error and don't use any - filterNames := make([]string, len(matchingFilters)) - for i, filter := range matchingFilters { - filterNames[i] = filter.Name + policyNames := make([]string, len(matchingPolicies)) + for i, policy := range matchingPolicies { + policyNames[i] = policy.Name } - r.log.Error(fmt.Errorf("multiple SriovResourceFilter objects match node"), - "Multiple resource filters match node, ignoring all", + r.log.Error(fmt.Errorf("multiple SriovResourcePolicy objects match node"), + "Multiple resource policies match node, ignoring all", "nodeName", r.nodeName, - "matchingFilters", filterNames) - r.currentResourceFilter = nil + "matchingPolicies", policyNames) + r.currentResourcePolicy = nil } return ctrl.Result{}, nil } -// GetCurrentResourceFilter returns the currently active SriovResourceFilter for the node -func (r *SriovResourceFilterReconciler) GetCurrentResourceFilter() *sriovdrav1alpha1.SriovResourceFilter { - return r.currentResourceFilter +// GetCurrentResourcePolicy returns the currently active SriovResourcePolicy for the node +func (r *SriovResourcePolicyReconciler) GetCurrentResourcePolicy() *sriovdrav1alpha1.SriovResourcePolicy { + return r.currentResourcePolicy } -// HasResourceFilter returns true if there is currently an active SriovResourceFilter for the node -func (r *SriovResourceFilterReconciler) HasResourceFilter() bool { - return r.currentResourceFilter != nil +// HasResourcePolicy returns true if there is currently an active SriovResourcePolicy for the node +func (r *SriovResourcePolicyReconciler) HasResourcePolicy() bool { + return r.currentResourcePolicy != nil } -// GetConfigs returns the configs from the currently active SriovResourceFilter -// Returns nil if no resource filter is active -func (r *SriovResourceFilterReconciler) GetConfigs() []sriovdrav1alpha1.Config { - if r.currentResourceFilter == nil { +// GetConfigs returns the configs from the currently active SriovResourcePolicy +// Returns nil if no resource policy is active +func (r *SriovResourcePolicyReconciler) GetConfigs() []sriovdrav1alpha1.Config { + if r.currentResourcePolicy == nil { return nil } - return r.currentResourceFilter.Spec.Configs + return r.currentResourcePolicy.Spec.Configs } -// GetResourceFilters returns all resource filters from all configs in the currently active SriovResourceFilter -// Returns nil if no resource filter is active +// GetResourceFilters returns all resource filters from all configs in the currently active SriovResourcePolicy +// Returns nil if no resource policy is active // // Deprecated: Use GetConfigs() instead for better resource name handling -func (r *SriovResourceFilterReconciler) GetResourceFilters() []sriovdrav1alpha1.ResourceFilter { - if r.currentResourceFilter == nil { +func (r *SriovResourcePolicyReconciler) GetResourceFilters() []sriovdrav1alpha1.ResourceFilter { + if r.currentResourcePolicy == nil { return nil } var allFilters []sriovdrav1alpha1.ResourceFilter - for _, config := range r.currentResourceFilter.Spec.Configs { + for _, config := range r.currentResourcePolicy.Spec.Configs { allFilters = append(allFilters, config.ResourceFilters...) } return allFilters } -// GetResourceNames returns all resource names from the currently active SriovResourceFilter -// Returns nil if no resource filter is active -func (r *SriovResourceFilterReconciler) GetResourceNames() []string { - if r.currentResourceFilter == nil { +// GetResourceNames returns all resource names from the currently active SriovResourcePolicy +// Returns nil if no resource policy is active +func (r *SriovResourcePolicyReconciler) GetResourceNames() []string { + if r.currentResourcePolicy == nil { return nil } var resourceNames []string - for _, config := range r.currentResourceFilter.Spec.Configs { + for _, config := range r.currentResourcePolicy.Spec.Configs { if config.ResourceName != "" { resourceNames = append(resourceNames, config.ResourceName) } @@ -185,7 +185,7 @@ func (r *SriovResourceFilterReconciler) GetResourceNames() []string { } // matchesNodeSelector checks if node labels match the given selector -func (r *SriovResourceFilterReconciler) matchesNodeSelector(nodeLabels map[string]string, nodeSelector map[string]string) bool { +func (r *SriovResourcePolicyReconciler) matchesNodeSelector(nodeLabels map[string]string, nodeSelector map[string]string) bool { if len(nodeSelector) == 0 { // Empty selector matches all nodes return true @@ -195,39 +195,39 @@ func (r *SriovResourceFilterReconciler) matchesNodeSelector(nodeLabels map[strin return selector.Matches(labels.Set(nodeLabels)) } -// applyResourceFilterToDevices applies the current resource filter to devices -func (r *SriovResourceFilterReconciler) applyResourceFilterToDevices(ctx context.Context) error { +// applyResourcePolicyToDevices applies the current resource policy to devices +func (r *SriovResourcePolicyReconciler) applyResourcePolicyToDevices(ctx context.Context) error { deviceResourceMap := r.getFilteredDeviceResourceMap() return r.deviceStateManager.UpdateDeviceResourceNames(ctx, deviceResourceMap) } -// getFilteredDeviceResourceMap returns a map of device name to resource name based on the current resource filter -func (r *SriovResourceFilterReconciler) getFilteredDeviceResourceMap() map[string]string { +// getFilteredDeviceResourceMap returns a map of device name to resource name based on the current resource policy +func (r *SriovResourcePolicyReconciler) getFilteredDeviceResourceMap() map[string]string { deviceResourceMap := make(map[string]string) - // If no resource filter is active, return empty map (clears resource names) - if r.currentResourceFilter == nil { - r.log.V(2).Info("No active resource filter, clearing all resource names") + // If no resource policy is active, return empty map (clears resource names) + if r.currentResourcePolicy == nil { + r.log.V(2).Info("No active resource policy, clearing all resource names") return deviceResourceMap } // Get all allocatable devices from device state manager allocatableDevices := r.deviceStateManager.GetAllocatableDevices() - r.log.V(2).Info("Applying resource filter to devices", - "filterName", r.currentResourceFilter.Name, - "totalConfigs", len(r.currentResourceFilter.Spec.Configs), + r.log.V(2).Info("Applying resource policy to devices", + "policyName", r.currentResourcePolicy.Name, + "totalConfigs", len(r.currentResourcePolicy.Spec.Configs), "totalDevices", len(allocatableDevices)) // Iterate through each config and apply its resource filters to devices - for _, config := range r.currentResourceFilter.Spec.Configs { + for _, config := range r.currentResourcePolicy.Spec.Configs { if config.ResourceName == "" { - r.log.V(2).Info("Skipping config with empty resource name", "filterName", r.currentResourceFilter.Name) + r.log.V(2).Info("Skipping config with empty resource name", "policyName", r.currentResourcePolicy.Name) continue } r.log.V(3).Info("Processing config", - "filterName", r.currentResourceFilter.Name, + "policyName", r.currentResourcePolicy.Name, "resourceName", config.ResourceName, "filtersCount", len(config.ResourceFilters)) @@ -243,13 +243,13 @@ func (r *SriovResourceFilterReconciler) getFilteredDeviceResourceMap() map[strin r.log.V(3).Info("Device matches config filter", "deviceName", deviceName, "resourceName", config.ResourceName, - "filterName", r.currentResourceFilter.Name) + "policyName", r.currentResourcePolicy.Name) } } } - r.log.Info("Resource filter applied", - "filterName", r.currentResourceFilter.Name, + r.log.Info("Resource policy applied", + "policyName", r.currentResourcePolicy.Name, "matchingDevices", len(deviceResourceMap), "totalDevices", len(allocatableDevices)) @@ -257,7 +257,7 @@ func (r *SriovResourceFilterReconciler) getFilteredDeviceResourceMap() map[strin } // deviceMatchesFilters checks if a device matches any of the provided resource filters -func (r *SriovResourceFilterReconciler) deviceMatchesFilters(device resourceapi.Device, filters []sriovdrav1alpha1.ResourceFilter) bool { +func (r *SriovResourcePolicyReconciler) deviceMatchesFilters(device resourceapi.Device, filters []sriovdrav1alpha1.ResourceFilter) bool { // If no filters are specified, match all devices if len(filters) == 0 { return true @@ -274,7 +274,7 @@ func (r *SriovResourceFilterReconciler) deviceMatchesFilters(device resourceapi. } // deviceMatchesFilter checks if a device matches a specific resource filter -func (r *SriovResourceFilterReconciler) deviceMatchesFilter(device resourceapi.Device, filter sriovdrav1alpha1.ResourceFilter) bool { +func (r *SriovResourcePolicyReconciler) deviceMatchesFilter(device resourceapi.Device, filter sriovdrav1alpha1.ResourceFilter) bool { // Check vendor IDs if len(filter.Vendors) > 0 { vendorAttr, exists := device.Attributes[consts.AttributeVendorID] @@ -355,7 +355,7 @@ func (r *SriovResourceFilterReconciler) deviceMatchesFilter(device resourceapi.D } // stringSliceContains checks if a slice contains a specific string -func (r *SriovResourceFilterReconciler) stringSliceContains(slice []string, item string) bool { +func (r *SriovResourcePolicyReconciler) stringSliceContains(slice []string, item string) bool { for _, s := range slice { if s == item { return true @@ -365,11 +365,11 @@ func (r *SriovResourceFilterReconciler) stringSliceContains(slice []string, item } // SetupWithManager sets up the controller with the Manager. -func (r *SriovResourceFilterReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *SriovResourcePolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { qHandler := func(q workqueue.TypedRateLimitingInterface[reconcile.Request]) { q.AddAfter(reconcile.Request{NamespacedName: types.NamespacedName{ Namespace: r.namespace, - Name: resourceFilterSyncEventName, + Name: resourcePolicySyncEventName, }}, time.Second) } @@ -431,11 +431,11 @@ func (r *SriovResourceFilterReconciler) SetupWithManager(mgr ctrl.Manager) error // Send initial sync event to trigger reconcile when controller is started var eventChan = make(chan event.GenericEvent, 1) - eventChan <- event.GenericEvent{Object: &sriovdrav1alpha1.SriovResourceFilter{ - ObjectMeta: metav1.ObjectMeta{Name: resourceFilterSyncEventName, Namespace: r.namespace}}} + eventChan <- event.GenericEvent{Object: &sriovdrav1alpha1.SriovResourcePolicy{ + ObjectMeta: metav1.ObjectMeta{Name: resourcePolicySyncEventName, Namespace: r.namespace}}} close(eventChan) - // Create predicate to filter SriovResourceFilter events to only the operator namespace + // Create predicate to filter SriovResourcePolicy events to only the operator namespace namespacePredicate := predicate.NewPredicateFuncs(func(obj client.Object) bool { return obj.GetNamespace() == r.namespace }) @@ -445,9 +445,9 @@ func (r *SriovResourceFilterReconciler) SetupWithManager(mgr ctrl.Manager) error nodeMetadata.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Node")) return ctrl.NewControllerManagedBy(mgr). - For(&sriovdrav1alpha1.SriovResourceFilter{}). + For(&sriovdrav1alpha1.SriovResourcePolicy{}). Watches(nodeMetadata, nodeEventHandler). - Watches(&sriovdrav1alpha1.SriovResourceFilter{}, delayedEventHandler). + Watches(&sriovdrav1alpha1.SriovResourcePolicy{}, delayedEventHandler). WithEventFilter(namespacePredicate). WatchesRawSource(source.Channel(eventChan, &handler.EnqueueRequestForObject{})). Complete(r) diff --git a/pkg/controller/resourcefiltercontroller_test.go b/pkg/controller/resourcepolicycontroller_test.go similarity index 94% rename from pkg/controller/resourcefiltercontroller_test.go rename to pkg/controller/resourcepolicycontroller_test.go index dfc4d07..33e7ea6 100644 --- a/pkg/controller/resourcefiltercontroller_test.go +++ b/pkg/controller/resourcepolicycontroller_test.go @@ -25,7 +25,7 @@ func (l *localFakeState) UpdateDeviceResourceNames(_ context.Context, _ map[stri var _ = Describe("matchesNodeSelector", func() { It("handles empty, subset, and mismatch correctly", func() { - r := &SriovResourceFilterReconciler{} + r := &SriovResourcePolicyReconciler{} node := map[string]string{"role": "dpdk", "zone": "a"} Expect(r.matchesNodeSelector(node, map[string]string{})).To(BeTrue()) Expect(r.matchesNodeSelector(node, map[string]string{"role": "dpdk"})).To(BeTrue()) @@ -35,7 +35,7 @@ var _ = Describe("matchesNodeSelector", func() { var _ = Describe("stringSliceContains", func() { It("returns expected presence results", func() { - r := &SriovResourceFilterReconciler{} + r := &SriovResourcePolicyReconciler{} Expect(r.stringSliceContains([]string{"a", "b"}, "c")).To(BeFalse()) Expect(r.stringSliceContains([]string{"a", "b"}, "b")).To(BeTrue()) }) @@ -43,7 +43,7 @@ var _ = Describe("stringSliceContains", func() { var _ = Describe("deviceMatchesFilter", func() { It("matches valid filters and rejects mismatches", func() { - r := &SriovResourceFilterReconciler{} + r := &SriovResourcePolicyReconciler{} vendor := "8086" dev := "154c" pf := "eth0" @@ -109,13 +109,13 @@ var _ = Describe("getFilteredDeviceResourceMap", func() { }, }, } - r := &SriovResourceFilterReconciler{deviceStateManager: &localFakeState{alloc: alloc}} + r := &SriovResourcePolicyReconciler{deviceStateManager: &localFakeState{alloc: alloc}} m := r.getFilteredDeviceResourceMap() Expect(m).To(BeEmpty()) - r.currentResourceFilter = &sriovdrav1alpha1.SriovResourceFilter{ - Spec: sriovdrav1alpha1.SriovResourceFilterSpec{ + r.currentResourcePolicy = &sriovdrav1alpha1.SriovResourcePolicy{ + Spec: sriovdrav1alpha1.SriovResourcePolicySpec{ Configs: []sriovdrav1alpha1.Config{ {ResourceName: "resA", ResourceFilters: []sriovdrav1alpha1.ResourceFilter{{Vendors: []string{"8086"}}}}, {ResourceName: "", ResourceFilters: []sriovdrav1alpha1.ResourceFilter{{Devices: []string{"154c"}}}},