diff --git a/debian_stable_docker_images.inc b/debian_stable_docker_images.inc new file mode 100644 index 0000000..a612077 --- /dev/null +++ b/debian_stable_docker_images.inc @@ -0,0 +1 @@ +intel-device-plugins-images \ No newline at end of file diff --git a/intel-device-plugins-images/debian/build-intel-device-plugins-image.sh b/intel-device-plugins-images/debian/build-intel-device-plugins-image.sh new file mode 100644 index 0000000..b8e9598 --- /dev/null +++ b/intel-device-plugins-images/debian/build-intel-device-plugins-image.sh @@ -0,0 +1,167 @@ +#!/bin/sh +# +# Copyright (c) 2025 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +IMAGE=$1 +IMAGE_TAG=$2 +export CONTAINER_TOOL=docker +BUILD_TAG=dev-debian-stable-build +INTEL=intel +INTEL_OPERATOR=intel-deviceplugin-operator +INTEL_QAT=intel-qat-plugin +INTEL_GPU=intel-gpu-plugin +INTEL_GPU_INIT=intel-gpu-initcontainer +INTEL_DSA=intel-dsa-plugin +INTEL_IDXD_INIT=intel-idxd-config-initcontainer +echo "=============== build script ================" +echo image: "${IMAGE}" +echo image_tag: "${IMAGE_TAG}" +pwd + +if [ -z "${IMAGE_TAG}" ]; then + echo "Image tag must be specified. build ${IMAGE} Aborting..." >&2 + exit 1 +fi + +build_intel_operator_image() { + export INTEL_OPERATOR_IMAGE=$1 + + echo "intel_operator_image: ${INTEL_OPERATOR_IMAGE}" + + pwd + make $INTEL_OPERATOR TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_OPERATOR:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_OPERATOR:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_OPERATOR_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_OPERATOR_IMAGE} image build done" + return 0 +} + +build_intel_qat_image() { + export INTEL_QAT_IMAGE=$1 + + echo "intel_qat_image: ${INTEL_QAT_IMAGE}" + + pwd + make $INTEL_QAT TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_QAT:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_QAT:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_QAT_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_QAT_IMAGE} image build done" + return 0 +} + +build_intel_gpu_image() { + + export INTEL_GPU_IMAGE=$1 + + echo "intel_gpu_image: ${INTEL_GPU_IMAGE}" + pwd + make $INTEL_GPU TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_GPU:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_GPU:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_GPU_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_GPU_IMAGE} image build done" + return 0 +} + +build_intel_gpu_init_image() { + export INTEL_GPU_INIT_IMAGE=$1 + + echo "intel_gpu_init_image: ${INTEL_GPU_INIT_IMAGE}" + pwd + make $INTEL_GPU_INIT TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_GPU_INIT:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_GPU_INIT:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_GPU_INIT_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_GPU_INIT_IMAGE} image build done" + return 0 +} + +build_intel_dsa_image() { + + export INTEL_DSA_IMAGE=$1 + + echo "intel_dsa_image: ${INTEL_DSA_IMAGE}" + pwd + make $INTEL_DSA TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_DSA:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_DSA:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_DSA_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_DSA_IMAGE} image build done" + return 0 +} + +build_intel_idxd_config_init_image() { + + export INTEL_IDXD_IMAGE=$1 + + echo "intel_idxd_config_init_image: ${INTEL_IDXD_IMAGE}" + pwd + make $INTEL_IDXD_INIT TAG=$BUILD_TAG + docker tag $INTEL/$INTEL_IDXD_INIT:$BUILD_TAG $IMAGE_TAG + docker rmi $INTEL/$INTEL_IDXD_INIT:$BUILD_TAG + if [ $? -ne 0 ]; then + echo "${INTEL_IDXD_IMAGE} image build failed" + exit 1 + fi + + echo "${INTEL_IDXD_IMAGE} image build done" + return 0 +} + +case ${IMAGE} in + intel_operator) + echo "Build image: ${INTEL_OPERATOR}" + build_intel_operator_image "${IMAGE_TAG}" + ;; + intel_qat) + echo "build image: ${INTEL_QAT}" + build_intel_qat_image "${IMAGE_TAG}" + ;; + intel_gpu) + echo "build image: ${INTEL_GPU}" + build_intel_gpu_image "${IMAGE_TAG}" + ;; + intel_gpu_init) + echo "build image: ${INTEL_GPU_INIT}" + build_intel_gpu_init_image "${IMAGE_TAG}" + ;; + intel_dsa) + echo "build image: ${INTEL_DSA}" + build_intel_dsa_image "${IMAGE_TAG}" + ;; + intel_idxd_config_init) + echo "build image: ${INTEL_IDXD_INIT}" + build_intel_idxd_config_init_image "${IMAGE_TAG}" + ;; + *) + echo "Unsupported ARGS in ${image_build_file}: ${IMAGE}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/intel-device-plugins-images/debian/intel-deviceplugin-operator.stable_docker_image b/intel-device-plugins-images/debian/intel-deviceplugin-operator.stable_docker_image new file mode 100644 index 0000000..fa6ee4c --- /dev/null +++ b/intel-device-plugins-images/debian/intel-deviceplugin-operator.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-deviceplugin-operator +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_operator diff --git a/intel-device-plugins-images/debian/intel-dsa-plugin.stable_docker_image b/intel-device-plugins-images/debian/intel-dsa-plugin.stable_docker_image new file mode 100644 index 0000000..37d67a8 --- /dev/null +++ b/intel-device-plugins-images/debian/intel-dsa-plugin.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-dsa-plugin +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_dsa diff --git a/intel-device-plugins-images/debian/intel-gpu-initcontainer.stable_docker_image b/intel-device-plugins-images/debian/intel-gpu-initcontainer.stable_docker_image new file mode 100644 index 0000000..36dcf1e --- /dev/null +++ b/intel-device-plugins-images/debian/intel-gpu-initcontainer.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-gpu-initcontainer +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_gpu_init diff --git a/intel-device-plugins-images/debian/intel-gpu-plugin.stable_docker_image b/intel-device-plugins-images/debian/intel-gpu-plugin.stable_docker_image new file mode 100644 index 0000000..551b046 --- /dev/null +++ b/intel-device-plugins-images/debian/intel-gpu-plugin.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-gpu-plugin +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_gpu diff --git a/intel-device-plugins-images/debian/intel-idxd-config-initcontainer.stable_docker_image b/intel-device-plugins-images/debian/intel-idxd-config-initcontainer.stable_docker_image new file mode 100644 index 0000000..a14370d --- /dev/null +++ b/intel-device-plugins-images/debian/intel-idxd-config-initcontainer.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-idxd-config-initcontainer +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_idxd_config_init diff --git a/intel-device-plugins-images/debian/intel-qat-plugin.stable_docker_image b/intel-device-plugins-images/debian/intel-qat-plugin.stable_docker_image new file mode 100644 index 0000000..9057705 --- /dev/null +++ b/intel-device-plugins-images/debian/intel-qat-plugin.stable_docker_image @@ -0,0 +1,8 @@ +BUILDER=script +LABEL=intel-qat-plugin +SOURCE_REPO=https://github.com/intel/intel-device-plugins-for-kubernetes.git +SOURCE_REF=v0.32.1 +SOURCE_PATCHES="../files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch" +COMMAND=bash +SCRIPT=build-intel-device-plugins-image.sh +ARGS=intel_qat diff --git a/intel-device-plugins-images/files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch b/intel-device-plugins-images/files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch new file mode 100644 index 0000000..8adcfa5 --- /dev/null +++ b/intel-device-plugins-images/files/0001-operator-add-possibility-to-use-a-secret-for-plugin.patch @@ -0,0 +1,803 @@ +From edafd4d1265921ad001a9cff22a58dfcb6b9c6ae Mon Sep 17 00:00:00 2001 +From: Tuomas Katila +Date: Mon, 16 Jun 2025 09:11:05 +0300 +Subject: [PATCH] operator: add possibility to use a secret for plugin images + +Also, pack controller options into a struct. + +Signed-off-by: Tuomas Katila +--- + cmd/operator/main.go | 15 ++++++++------ + pkg/controllers/dlb/controller.go | 16 ++++++++++----- + pkg/controllers/dlb/controller_test.go | 16 ++++++++++++++- + pkg/controllers/dsa/controller.go | 16 ++++++++++----- + pkg/controllers/dsa/controller_test.go | 16 ++++++++++++++- + pkg/controllers/fpga/controller.go | 17 +++++++++++----- + pkg/controllers/fpga/controller_test.go | 20 ++++++++++++++++-- + pkg/controllers/gpu/controller.go | 22 ++++++++++++-------- + pkg/controllers/gpu/controller_test.go | 27 ++++++++++++++++++++++++- + pkg/controllers/iaa/controller.go | 16 ++++++++++----- + pkg/controllers/iaa/controller_test.go | 17 +++++++++++++++- + pkg/controllers/qat/controller.go | 16 ++++++++++----- + pkg/controllers/qat/controller_test.go | 17 +++++++++++++++- + pkg/controllers/reconciler.go | 6 ++++++ + pkg/controllers/sgx/controller.go | 16 ++++++++++----- + pkg/controllers/sgx/controller_test.go | 17 +++++++++++++++- + test/envtest/suite_test.go | 16 +++++++-------- + 17 files changed, 226 insertions(+), 60 deletions(-) + +diff --git a/cmd/operator/main.go b/cmd/operator/main.go +index 2fca03da..7c5ac2a7 100644 +--- a/cmd/operator/main.go ++++ b/cmd/operator/main.go +@@ -34,6 +34,7 @@ import ( + + devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1" + fpgav2 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/fpga/v2" ++ "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers" + "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dlb" + "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dsa" + "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/fpga" +@@ -61,7 +62,7 @@ func init() { + // +kubebuilder:scaffold:scheme + } + +-type devicePluginControllerAndWebhook map[string](func(ctrl.Manager, string, bool) error) ++type devicePluginControllerAndWebhook map[string](func(ctrl.Manager, controllers.ControllerOptions) error) + + type flagList []string + +@@ -208,15 +209,17 @@ func main() { + os.Exit(1) + } + +- ns := os.Getenv("DEVICEPLUGIN_NAMESPACE") +- if ns == "" { +- ns = devicePluginNamespace ++ cargs := controllers.ControllerOptions{WithWebhook: true} ++ ++ cargs.Namespace = os.Getenv("DEVICEPLUGIN_NAMESPACE") ++ if cargs.Namespace == "" { ++ cargs.Namespace = devicePluginNamespace + } + +- withWebhook := true ++ cargs.ImagePullSecretName = os.Getenv("DEVICEPLUGIN_SECRET") + + for _, device := range devices { +- if err = setupControllerAndWebhook[device](mgr, ns, withWebhook); err != nil { ++ if err = setupControllerAndWebhook[device](mgr, cargs); err != nil { + setupLog.Error(err, "unable to initialize controller", "controller", device) + os.Exit(1) + } +diff --git a/pkg/controllers/dlb/controller.go b/pkg/controllers/dlb/controller.go +index ba770a52..27b6461b 100644 +--- a/pkg/controllers/dlb/controller.go ++++ b/pkg/controllers/dlb/controller.go +@@ -43,13 +43,13 @@ var defaultNodeSelector map[string]string = deployments.DLBPluginDaemonSet().Spe + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=dlbdeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for DlbDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "DlbDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.DlbDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -59,7 +59,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -92,7 +92,13 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + setInitContainer(&ds.Spec.Template.Spec, devicePlugin.Spec) + } + +- ds.ObjectMeta.Namespace = c.ns ++ ds.ObjectMeta.Namespace = c.args.Namespace ++ ++ if len(c.args.ImagePullSecretName) > 0 { ++ ds.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } + + ds.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + ds.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image +diff --git a/pkg/controllers/dlb/controller_test.go b/pkg/controllers/dlb/controller_test.go +index 34770861..af1cdb23 100644 +--- a/pkg/controllers/dlb/controller_test.go ++++ b/pkg/controllers/dlb/controller_test.go +@@ -45,7 +45,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -155,6 +155,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + }, + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -171,4 +177,12 @@ func TestNewDaemonSetDLB(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/pkg/controllers/dsa/controller.go b/pkg/controllers/dsa/controller.go +index fd7f6078..19f6b61f 100644 +--- a/pkg/controllers/dsa/controller.go ++++ b/pkg/controllers/dsa/controller.go +@@ -47,13 +47,13 @@ var defaultNodeSelector = deployments.DSAPluginDaemonSet().Spec.Template.Spec.No + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=dsadeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for DsaDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "DsaDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.DsaDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -63,7 +63,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -200,7 +200,7 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + daemonSet.Spec.Template.Spec.Tolerations = devicePlugin.Spec.Tolerations + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image + +@@ -208,6 +208,12 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + addInitContainer(daemonSet, devicePlugin) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return daemonSet + } + +diff --git a/pkg/controllers/dsa/controller_test.go b/pkg/controllers/dsa/controller_test.go +index 4181e42b..46872f60 100644 +--- a/pkg/controllers/dsa/controller_test.go ++++ b/pkg/controllers/dsa/controller_test.go +@@ -47,7 +47,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -177,6 +177,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + addInitContainer(&daemonSet, devicePlugin) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -193,4 +199,12 @@ func TestNewDaemonSetDSA(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/pkg/controllers/fpga/controller.go b/pkg/controllers/fpga/controller.go +index 3614fb16..3a96032e 100644 +--- a/pkg/controllers/fpga/controller.go ++++ b/pkg/controllers/fpga/controller.go +@@ -22,6 +22,7 @@ import ( + "strings" + + apps "k8s.io/api/apps/v1" ++ v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/reference" + ctrl "sigs.k8s.io/controller-runtime" +@@ -42,13 +43,13 @@ var defaultNodeSelector = deployments.FPGAPluginDaemonSet().Spec.Template.Spec.N + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=fpgadeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for FpgaDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "FpgaDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.FpgaDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -58,7 +59,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -84,7 +85,13 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + daemonSet.Spec.Template.Spec.Tolerations = devicePlugin.Spec.Tolerations + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace ++ ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } + + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image +diff --git a/pkg/controllers/fpga/controller_test.go b/pkg/controllers/fpga/controller_test.go +index b0ca45b8..5a389833 100644 +--- a/pkg/controllers/fpga/controller_test.go ++++ b/pkg/controllers/fpga/controller_test.go +@@ -42,13 +42,13 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + maxUnavailable := intstr.FromInt(1) + maxSurge := intstr.FromInt(0) + +- return &apps.DaemonSet{ ++ ds := &apps.DaemonSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "DaemonSet", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -198,6 +198,14 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + }, + }, + } ++ ++ if len(c.args.ImagePullSecretName) > 0 { ++ ds.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ ++ return ds + } + + // Test that FPGA daemonset created by using go:embed is +@@ -218,4 +226,12 @@ func TestNewDaemonSetFPGA(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/pkg/controllers/gpu/controller.go b/pkg/controllers/gpu/controller.go +index 3c943f52..09e52675 100644 +--- a/pkg/controllers/gpu/controller.go ++++ b/pkg/controllers/gpu/controller.go +@@ -49,13 +49,13 @@ var defaultNodeSelector = deployments.GPUPluginDaemonSet().Spec.Template.Spec.No + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=gpudeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for GpuDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "GpuDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.GpuDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -64,7 +64,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + + type controller struct { + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -80,7 +80,7 @@ func (c *controller) NewSharedServiceAccount() *v1.ServiceAccount { + return &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceAccountName, +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + }, + } + } +@@ -89,13 +89,13 @@ func (c *controller) NewSharedClusterRoleBinding() *rbacv1.ClusterRoleBinding { + return &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleBindingName, +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: serviceAccountName, +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + }, + }, + RoleRef: rbacv1.RoleRef{ +@@ -140,10 +140,16 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + daemonSet.Spec.Template.Spec.Tolerations = devicePlugin.Spec.Tolerations + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + if devicePlugin.Spec.InitImage == "" { + daemonSet.Spec.Template.Spec.InitContainers = nil + daemonSet.Spec.Template.Spec.Volumes = removeVolume(daemonSet.Spec.Template.Spec.Volumes, "nfd-features") +diff --git a/pkg/controllers/gpu/controller_test.go b/pkg/controllers/gpu/controller_test.go +index 994f0d88..aad31697 100644 +--- a/pkg/controllers/gpu/controller_test.go ++++ b/pkg/controllers/gpu/controller_test.go +@@ -29,6 +29,7 @@ import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1" ++ "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers" + ) + + const appLabel = "intel-gpu-plugin" +@@ -50,7 +51,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -196,6 +197,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + addVolumeMountIfMissing(&daemonSet.Spec.Template.Spec, "sysfsdevices", "/sys/devices", true) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -272,6 +279,24 @@ func TestNewDamonSetGPU(t *testing.T) { + } + } + ++func TestNewDamonSetGPUWithSecret(t *testing.T) { ++ c := &controller{ ++ args: controllers.ControllerOptions{ ++ ImagePullSecretName: "mysecret", ++ }, ++ } ++ ++ plugin := &devicepluginv1.GpuDevicePlugin{} ++ plugin.Name = "new-gpu-cr-testing" ++ ++ expected := c.newDaemonSetExpected(plugin) ++ actual := c.NewDaemonSet(plugin) ++ ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } ++} ++ + func TestUpdateDamonSetGPU(t *testing.T) { + tcases := []struct { + name string +diff --git a/pkg/controllers/iaa/controller.go b/pkg/controllers/iaa/controller.go +index bf2ce865..0fe99678 100644 +--- a/pkg/controllers/iaa/controller.go ++++ b/pkg/controllers/iaa/controller.go +@@ -45,13 +45,13 @@ const ( + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=iaadeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for IaaDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "IaaDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.IaaDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -61,7 +61,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -199,7 +199,7 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + daemonSet.Spec.Template.Spec.Tolerations = devicePlugin.Spec.Tolerations + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace + + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image +@@ -208,6 +208,12 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + addInitContainer(daemonSet, devicePlugin) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return daemonSet + } + +diff --git a/pkg/controllers/iaa/controller_test.go b/pkg/controllers/iaa/controller_test.go +index e74ae955..73b7f04c 100644 +--- a/pkg/controllers/iaa/controller_test.go ++++ b/pkg/controllers/iaa/controller_test.go +@@ -47,7 +47,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -177,6 +177,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + addInitContainer(&daemonSet, devicePlugin) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -193,4 +199,13 @@ func TestNewDaemonSetIAA(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/pkg/controllers/qat/controller.go b/pkg/controllers/qat/controller.go +index 36153d86..bcc45a95 100644 +--- a/pkg/controllers/qat/controller.go ++++ b/pkg/controllers/qat/controller.go +@@ -47,13 +47,13 @@ var defaultNodeSelector = deployments.QATPluginDaemonSet().Spec.Template.Spec.No + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=qatdeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for QatDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "QatDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.QatDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -63,7 +63,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) CreateEmptyObject() client.Object { +@@ -93,7 +93,13 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec) + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image + +diff --git a/pkg/controllers/qat/controller_test.go b/pkg/controllers/qat/controller_test.go +index 4d81ca61..3b12647d 100644 +--- a/pkg/controllers/qat/controller_test.go ++++ b/pkg/controllers/qat/controller_test.go +@@ -48,7 +48,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -176,6 +176,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -194,4 +200,13 @@ func TestNewDaemonSetQAT(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/pkg/controllers/reconciler.go b/pkg/controllers/reconciler.go +index 86879cb3..ded2b7f0 100644 +--- a/pkg/controllers/reconciler.go ++++ b/pkg/controllers/reconciler.go +@@ -94,6 +94,12 @@ type DevicePluginController interface { + Upgrade(ctx context.Context, obj client.Object) (upgrade bool) + } + ++type ControllerOptions struct { ++ Namespace string ++ ImagePullSecretName string ++ WithWebhook bool ++} ++ + type reconciler struct { + controller DevicePluginController + client.Client +diff --git a/pkg/controllers/sgx/controller.go b/pkg/controllers/sgx/controller.go +index 05a7f163..2804ceac 100644 +--- a/pkg/controllers/sgx/controller.go ++++ b/pkg/controllers/sgx/controller.go +@@ -43,13 +43,13 @@ var defaultNodeSelector = deployments.SGXPluginDaemonSet().Spec.Template.Spec.No + // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=sgxdeviceplugins/finalizers,verbs=update + + // SetupReconciler creates a new reconciler for SgxDevicePlugin objects. +-func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error { +- c := &controller{scheme: mgr.GetScheme(), ns: namespace} ++func SetupReconciler(mgr ctrl.Manager, args controllers.ControllerOptions) error { ++ c := &controller{scheme: mgr.GetScheme(), args: args} + if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "SgxDevicePlugin", ownerKey); err != nil { + return err + } + +- if withWebhook { ++ if args.WithWebhook { + return (&devicepluginv1.SgxDevicePlugin{}).SetupWebhookWithManager(mgr) + } + +@@ -59,7 +59,7 @@ func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error + type controller struct { + controllers.DefaultServiceAccountFactory + scheme *runtime.Scheme +- ns string ++ args controllers.ControllerOptions + } + + func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool { +@@ -126,7 +126,7 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + daemonSet.Spec.Template.Spec.NodeSelector = devicePlugin.Spec.NodeSelector + } + +- daemonSet.ObjectMeta.Namespace = c.ns ++ daemonSet.ObjectMeta.Namespace = c.args.Namespace + + daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin) + daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image +@@ -136,6 +136,12 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet { + setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec.InitImage) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return daemonSet + } + +diff --git a/pkg/controllers/sgx/controller_test.go b/pkg/controllers/sgx/controller_test.go +index 47f653ed..78c9f4d0 100644 +--- a/pkg/controllers/sgx/controller_test.go ++++ b/pkg/controllers/sgx/controller_test.go +@@ -49,7 +49,7 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ +- Namespace: c.ns, ++ Namespace: c.args.Namespace, + Name: appLabel + "-" + devicePlugin.Name, + Labels: map[string]string{ + "app": appLabel, +@@ -157,6 +157,12 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet + setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec.InitImage) + } + ++ if len(c.args.ImagePullSecretName) > 0 { ++ daemonSet.Spec.Template.Spec.ImagePullSecrets = []v1.LocalObjectReference{ ++ {Name: c.args.ImagePullSecretName}, ++ } ++ } ++ + return &daemonSet + } + +@@ -173,4 +179,13 @@ func TestNewDaemonSetSGX(t *testing.T) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("expected and actuall daemonsets differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) + } ++ ++ c.args.ImagePullSecretName = "mysecret" ++ ++ expected = c.newDaemonSetExpected(plugin) ++ actual = c.NewDaemonSet(plugin) ++ ++ if !reflect.DeepEqual(expected, actual) { ++ t.Errorf("expected and actual daemonsets with secret differ: %+s", diff.ObjectGoPrintDiff(expected, actual)) ++ } + } +diff --git a/test/envtest/suite_test.go b/test/envtest/suite_test.go +index 44e4e090..f2c6d904 100644 +--- a/test/envtest/suite_test.go ++++ b/test/envtest/suite_test.go +@@ -113,21 +113,21 @@ func up() { + k8sManager, managerErr := ctrl.NewManager(cfg, ctrl.Options{Scheme: scheme.Scheme, Metrics: metricsserver.Options{BindAddress: "0"}, Controller: config.Controller{SkipNameValidation: &yes}}) + Expect(managerErr).To(BeNil()) + +- withWebhook := true ++ args := ctr.ControllerOptions{Namespace: ns, WithWebhook: false} + +- Expect(dlbctr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(dlbctr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(dsactr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(dsactr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(fpgactr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(fpgactr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(gpuctr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(gpuctr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(iaactr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(iaactr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(qatctr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(qatctr.SetupReconciler(k8sManager, args)).To(BeNil()) + +- Expect(sgxctr.SetupReconciler(k8sManager, ns, !withWebhook)).To(BeNil()) ++ Expect(sgxctr.SetupReconciler(k8sManager, args)).To(BeNil()) + + ctx, cancel = context.WithCancel(context.TODO()) + +-- +2.34.1 +