From bb5e1acc6651ce15b4202a28086c77ad0c08b4c5 Mon Sep 17 00:00:00 2001 From: Fred Rolland Date: Mon, 23 Oct 2023 11:55:06 +0300 Subject: [PATCH] fix: validate resourcePrefix in NCP DP In the admission controller, the "resourcePrefix" field in Device Plugins configuration is now validated to be a valid FQDN. Signed-off-by: Fred Rolland --- api/v1alpha1/nicclusterpolicy_webhook.go | 60 +++- api/v1alpha1/nicclusterpolicy_webhook_test.go | 340 +++++------------- 2 files changed, 130 insertions(+), 270 deletions(-) diff --git a/api/v1alpha1/nicclusterpolicy_webhook.go b/api/v1alpha1/nicclusterpolicy_webhook.go index 1cc16c49e..2040c6daf 100644 --- a/api/v1alpha1/nicclusterpolicy_webhook.go +++ b/api/v1alpha1/nicclusterpolicy_webhook.go @@ -34,6 +34,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" ) +const ( + fqdnRegex = `^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z]{2,})+$` + sriovResourceNameRegex = `^([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]$` + rdmaResourceNameRegex = `^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$` +) + // log is for logging in this package. var nicClusterPolicyLog = logf.Log.WithName("nicclusterpolicy-resource") @@ -198,12 +204,9 @@ func (dp *DevicePluginSpec) validateSriovNetworkDevicePlugin(fldPath *field.Path resourceJSONLoader := gojsonschema.NewStringLoader(string(resourceJSONString)) var selectorResult *gojsonschema.Result var selectorErr error - resourceName := resource["resourceName"].(string) - if !isValidSriovNetworkDevicePluginResourceName(resourceName) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config, - "Invalid Resource name, it must consist of alphanumeric characters, '_' or '.', "+ - "and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', "+ - "or '123_abc', regex used for validation is '([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]')")) + var ok bool + ok, allErrs = validateResourceNamePrefix(resource, allErrs, fldPath, dp) + if !ok { return allErrs } deviceType := resource["deviceType"] @@ -229,6 +232,28 @@ func (dp *DevicePluginSpec) validateSriovNetworkDevicePlugin(fldPath *field.Path return allErrs } +func validateResourceNamePrefix(resource map[string]interface{}, + allErrs field.ErrorList, fldPath *field.Path, dp *DevicePluginSpec) (bool, field.ErrorList) { + resourceName := resource["resourceName"].(string) + if !isValidSriovNetworkDevicePluginResourceName(resourceName) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config, + "Invalid Resource name, it must consist of alphanumeric characters, '_' or '.', "+ + "and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', "+ + "or '123_abc', regex used for validation is "+sriovResourceNameRegex)) + return false, allErrs + } + resourcePrefix, ok := resource["resourcePrefix"] + if ok { + if !isValidFQDN(resourcePrefix.(string)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config, + "Invalid Resource prefix, it must be a valid FQDN"+ + "regex used for validation is "+fqdnRegex)) + return false, allErrs + } + } + return true, allErrs +} + func (dp *DevicePluginSpec) validateRdmaSharedDevicePlugin(fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList var rdmaSharedDevicePluginConfigJSON map[string]interface{} @@ -263,8 +288,16 @@ func (dp *DevicePluginSpec) validateRdmaSharedDevicePlugin(fldPath *field.Path) allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config, "Invalid Resource name, it must consist of alphanumeric characters, "+ "'-', '_' or '.', and must start and end with an alphanumeric character "+ - "(e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0"+ - "-9_.]*)?[A-Za-z0-9]')")) + "(e.g. 'MyName', or 'my.name', or '123-abc') regex used for validation is "+rdmaResourceNameRegex)) + } + resourcePrefix, ok := config["resourcePrefix"] + if ok { + if !isValidFQDN(resourcePrefix.(string)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config, + "Invalid Resource prefix, it must be a valid FQDN "+ + "regex used for validation is "+fqdnRegex)) + return allErrs + } } } } else { @@ -336,17 +369,20 @@ func isValidOFEDVersion(version string) bool { } func isValidSriovNetworkDevicePluginResourceName(resourceName string) bool { - resourceNamePattern := `^([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]$` - resourceNameRegex := regexp.MustCompile(resourceNamePattern) + resourceNameRegex := regexp.MustCompile(sriovResourceNameRegex) return resourceNameRegex.MatchString(resourceName) } func isValidRdmaSharedDevicePluginResourceName(resourceName string) bool { - resourceNamePattern := `^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$` - resourceNameRegex := regexp.MustCompile(resourceNamePattern) + resourceNameRegex := regexp.MustCompile(rdmaResourceNameRegex) return resourceNameRegex.MatchString(resourceName) } +func isValidFQDN(input string) bool { + regex := regexp.MustCompile(fqdnRegex) + return regex.MatchString(input) +} + // +kubebuilder:object:generate=false type schemaValidator struct { schemas map[string]*gojsonschema.Schema diff --git a/api/v1alpha1/nicclusterpolicy_webhook_test.go b/api/v1alpha1/nicclusterpolicy_webhook_test.go index d203669a0..d9ab47a38 100644 --- a/api/v1alpha1/nicclusterpolicy_webhook_test.go +++ b/api/v1alpha1/nicclusterpolicy_webhook_test.go @@ -121,22 +121,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &rdmaConfig, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(rdmaConfig) Expect(nicClusterPolicy.ValidateCreate()).NotTo(HaveOccurred()) }) It("Valid RDMA config JSON", func() { @@ -147,22 +132,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &rdmaConfig, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(rdmaConfig) Expect(nicClusterPolicy.ValidateCreate()).NotTo(HaveOccurred()) }) It("Invalid RDMA config JSON, missing starting {", func() { @@ -173,22 +143,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid json of RdmaSharedDevicePluginConfig")) }) @@ -200,22 +155,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("Invalid Resource name")) }) It("Invalid RDMA config JSON schema, no configList provided", func() { @@ -226,22 +166,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("configList is required")) }) It("Invalid RDMA config JSON schema, none of the selectors are provided", func() { @@ -250,22 +175,7 @@ var _ = Describe("Validate", func() { "resourceName": "rdma_shared_device_a", "rdmaHcaMax": 63, "selectors": {}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("vendors is required")) }) It("Invalid RDMA config JSON, vendors must be list of strings", func() { @@ -276,22 +186,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": [15], "deviceIDs": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid type. Expected: string, given: integer")) }) @@ -303,25 +198,23 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "deviceIDs": [1010]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - RdmaSharedDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidRdmaConfigJSON, - ImageSpec: ImageSpec{ - Image: "k8s-rdma-shared-dev-plugin", - Repository: "ghcr.io/mellanox", - Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid type. Expected: string, given: integer")) }) + It("Invalid RDMA config JSON resourcePrefix is not FQDN", func() { + invalidRdmaConfigJSON := `{ + "configList": [{ + "resourceName": "rdma_shared_device_a", + "resourcePrefix": "nvidia.com#$&&@", + "rdmaHcaMax": 63, + "selectors": { + "vendors": ["15b3"], + "deviceIDs": ["101b"]}}]}` + nicClusterPolicy := rdmaDPNicClusterPolicy(invalidRdmaConfigJSON) + Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( + "Invalid Resource prefix, it must be a valid FQDN")) + }) It("Valid SriovDevicePlugin config JSON", func() { sriovConfig := `{ "resourceList": [{ @@ -329,22 +222,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "devices": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &sriovConfig, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(sriovConfig) Expect(nicClusterPolicy.ValidateCreate()).NotTo(HaveOccurred()) }) It("Valid SriovDevicePlugin config JSON, selectors object is a list ", func() { @@ -354,22 +232,7 @@ var _ = Describe("Validate", func() { "selectors": [{ "vendors": ["15b3"], "devices": ["101b"]}]}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &sriovConfig, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(sriovConfig) Expect(nicClusterPolicy.ValidateCreate()).NotTo(HaveOccurred()) }) It("Invalid SriovDevicePlugin config JSON, missing starting {", func() { @@ -379,22 +242,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "devices": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidSriovConfigJSON, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid json of SriovNetworkDevicePluginConfig")) }) @@ -405,22 +253,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "devices": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidSriovConfigJSON, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("Invalid Resource name")) }) It("Invalid SriovDevicePlugin config JSON schema, no resourceList provided", func() { @@ -430,22 +263,7 @@ var _ = Describe("Validate", func() { "selectors": { "vendors": ["15b3"], "devices": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidSriovConfigJSON, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("resourceList is required")) }) It("Invalid SriovDevicePlugin config JSON schema, none of the selectors are provided", func() { @@ -453,75 +271,81 @@ var _ = Describe("Validate", func() { "resourceList": [{ "resourceName": "sriov_network_device_plugin", "selectors": {}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &invalidSriovConfigJSON, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring("vendors is required")) }) It("Invalid SriovDevicePlugin config JSON, vendors must be list of strings", func() { - sriovConfig := `{ + invalidSriovConfigJSON := `{ "resourceList": [{ "resourceName": "hostdev", "selectors": { "vendors": [15], "devices": ["101b"]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &sriovConfig, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid type. Expected: string, given: integer")) }) It("Invalid SriovDevicePlugin config JSON, devices must be list of strings", func() { - sriovConfig := `{ + invalidSriovConfigJSON := `{ "resourceList": [{ "resourceName": "hostdev", "selectors": { "vendors": ["15b3"], "devices": [1020]}}]}` - nicClusterPolicy := NicClusterPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "test"}, - Spec: NicClusterPolicySpec{ - SriovDevicePlugin: &DevicePluginSpec{ - ImageSpecWithConfig: ImageSpecWithConfig{ - Config: &sriovConfig, - ImageSpec: ImageSpec{ - Image: "sriov-network-device-plugin", - Repository: "nvcr.io/nvstaging/mellanox", - Version: "network-operator-23.10.0-beta.1", - ImagePullSecrets: []string{}, - }, - }, - }, - }, - } + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) + Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( "Invalid type. Expected: string, given: integer")) }) + It("Invalid SriovDevicePlugin resourcePrefix is not FQDN", func() { + invalidSriovConfigJSON := `{ + "resourceList": [{ + "resourceName": "hostdev", + "resourcePrefix": "nvidia.com#$&&@", + "selectors": { + "vendors": ["15b3"], + "devices": ["101b"]}}]}` + nicClusterPolicy := sriovDPNicClusterPolicy(invalidSriovConfigJSON) + Expect(nicClusterPolicy.ValidateCreate().Error()).To(ContainSubstring( + "Invalid Resource prefix, it must be a valid FQDN")) + }) }) }) + +func rdmaDPNicClusterPolicy(config string) NicClusterPolicy { + return NicClusterPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "test"}, + Spec: NicClusterPolicySpec{ + RdmaSharedDevicePlugin: &DevicePluginSpec{ + ImageSpecWithConfig: ImageSpecWithConfig{ + Config: &config, + ImageSpec: ImageSpec{ + Image: "k8s-rdma-shared-dev-plugin", + Repository: "ghcr.io/mellanox", + Version: "sha-fe7f371c7e1b8315bf900f71cd25cfc1251dc775", + ImagePullSecrets: []string{}, + }, + }, + }, + }, + } +} + +func sriovDPNicClusterPolicy(config string) NicClusterPolicy { + return NicClusterPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "test"}, + Spec: NicClusterPolicySpec{ + SriovDevicePlugin: &DevicePluginSpec{ + ImageSpecWithConfig: ImageSpecWithConfig{ + Config: &config, + ImageSpec: ImageSpec{ + Image: "sriov-network-device-plugin", + Repository: "nvcr.io/nvstaging/mellanox", + Version: "network-operator-23.10.0-beta.1", + ImagePullSecrets: []string{}, + }, + }, + }, + }, + } +}