From 3a12d655f34f855383a8fc4e7e7388d3e54dbf6d Mon Sep 17 00:00:00 2001 From: vbadrina Date: Thu, 21 Mar 2024 13:33:58 +0530 Subject: [PATCH] Changes due to upgrade of klogs and controller-runtime This commit includes several changes to webhook package due to bumping up controller runtime deps and also makes changes to logs lines to remove formatter wherever it is not required. Signed-off-by: vbadrina --- addons/agent_mirrorpeer_controller.go | 10 ++--- addons/blue_secret_controller.go | 7 ++-- addons/green_secret_controller.go | 7 ++-- addons/maintenance_mode_controller.go | 9 ++-- addons/manager.go | 8 ++-- addons/s3_controller.go | 9 ++-- addons/s3_secret_handler.go | 2 +- api/v1alpha1/mirrorpeer_webhook.go | 41 +++++++------------ ...er-orchestrator.clusterserviceversion.yaml | 2 +- controllers/drpolicy_controller.go | 2 +- controllers/manager.go | 14 +++++++ controllers/mirrorpeersecret_controller.go | 5 +-- 12 files changed, 56 insertions(+), 60 deletions(-) diff --git a/addons/agent_mirrorpeer_controller.go b/addons/agent_mirrorpeer_controller.go index 05754b9e..56ccdaec 100644 --- a/addons/agent_mirrorpeer_controller.go +++ b/addons/agent_mirrorpeer_controller.go @@ -117,7 +117,7 @@ func (r *MirrorPeerReconciler) Reconcile(ctx context.Context, req ctrl.Request) } klog.Infof("creating s3 buckets") - err = r.createS3(ctx, req, mirrorPeer, scr.Namespace) + err = r.createS3(ctx, mirrorPeer, scr.Namespace) if err != nil { klog.Error(err, "Failed to create ODR S3 resources") return ctrl.Result{}, err @@ -158,8 +158,8 @@ func (r *MirrorPeerReconciler) Reconcile(ctx context.Context, req ctrl.Request) // Trying this at last to allow bootstrapping to be completed if mirrorPeer.Spec.OverlappingCIDR { - klog.Infof("enabling multiclusterservice", "MirrorPeer", mirrorPeer.GetName(), "Peers", mirrorPeer.Spec.Items) - err := r.enableMulticlusterService(ctx, scr.Name, scr.Namespace, &mirrorPeer) + klog.Info("enabling multiclusterservice", "MirrorPeer", mirrorPeer.GetName(), "Peers", mirrorPeer.Spec.Items) + err := r.enableMulticlusterService(ctx, scr.Name, scr.Namespace) if err != nil { return ctrl.Result{}, fmt.Errorf("failed to enable multiclusterservice for storagecluster %q in namespace %q: %v", scr.Name, scr.Namespace, err) } @@ -258,7 +258,7 @@ func (r *MirrorPeerReconciler) labelRBDStorageClasses(ctx context.Context, stora return errs } -func (r *MirrorPeerReconciler) createS3(ctx context.Context, req ctrl.Request, mirrorPeer multiclusterv1alpha1.MirrorPeer, scNamespace string) error { +func (r *MirrorPeerReconciler) createS3(ctx context.Context, mirrorPeer multiclusterv1alpha1.MirrorPeer, scNamespace string) error { noobaaOBC, err := r.getS3bucket(ctx, mirrorPeer, scNamespace) if err != nil { if errors.IsNotFound(err) { @@ -303,7 +303,7 @@ func (r *MirrorPeerReconciler) getS3bucket(ctx context.Context, mirrorPeer multi } // enableMulticlusterService sets the multiclusterservice flag on StorageCluster if submariner globalnet is enabled -func (r *MirrorPeerReconciler) enableMulticlusterService(ctx context.Context, storageClusterName string, namespace string, mp *multiclusterv1alpha1.MirrorPeer) error { +func (r *MirrorPeerReconciler) enableMulticlusterService(ctx context.Context, storageClusterName string, namespace string) error { klog.Infof("Enabling MCS for StorageCluster %q in %q namespace.", storageClusterName, namespace) var sc ocsv1.StorageCluster err := r.SpokeClient.Get(ctx, types.NamespacedName{ diff --git a/addons/blue_secret_controller.go b/addons/blue_secret_controller.go index 9d77ec7a..816bbcd5 100644 --- a/addons/blue_secret_controller.go +++ b/addons/blue_secret_controller.go @@ -9,7 +9,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/source" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -48,7 +47,7 @@ func (r *BlueSecretReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). Named("bluesecret_controller"). - Watches(&source.Kind{Type: &corev1.Secret{}}, &handler.EnqueueRequestForObject{}, + Watches(&corev1.Secret{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(predicate.GenerationChangedPredicate{}, predicate.LabelChangedPredicate{}, blueSecretPredicate)). Complete(r) } @@ -57,14 +56,14 @@ func (r *BlueSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) var err error var secret corev1.Secret - klog.Infof("Reconciling blue secret", "secret", req.NamespacedName.String()) + klog.Info("Reconciling blue secret", "secret", req.NamespacedName.String()) err = r.SpokeClient.Get(ctx, req.NamespacedName, &secret) if err != nil { if errors.IsNotFound(err) { klog.Infof("Could not find secret. Ignoring since it must have been deleted") return ctrl.Result{}, nil } - klog.Errorf("Failed to get secret.", err) + klog.Error("Failed to get secret.", err) return ctrl.Result{}, err } diff --git a/addons/green_secret_controller.go b/addons/green_secret_controller.go index 7d414dc5..320269b3 100644 --- a/addons/green_secret_controller.go +++ b/addons/green_secret_controller.go @@ -16,7 +16,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/source" ) // GreenSecretReconciler reconciles a MirrorPeer object @@ -54,7 +53,7 @@ func (r *GreenSecretReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). Named("greensecret_controller"). - Watches(&source.Kind{Type: &corev1.Secret{}}, &handler.EnqueueRequestForObject{}, + Watches(&corev1.Secret{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(predicate.GenerationChangedPredicate{}, greenSecretPredicate)). Complete(r) } @@ -63,14 +62,14 @@ func (r *GreenSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) var err error var greenSecret corev1.Secret - klog.Infof("Reconciling green secret", "secret", req.NamespacedName.String()) + klog.Info("Reconciling green secret", "secret", req.NamespacedName.String()) err = r.HubClient.Get(ctx, req.NamespacedName, &greenSecret) if err != nil { if errors.IsNotFound(err) { klog.Infof("Could not find secret. Ignoring since it must have been deleted") return ctrl.Result{}, nil } - klog.Errorf("Failed to get secret.", err) + klog.Error("Failed to get secret.", err) return ctrl.Result{}, err } diff --git a/addons/maintenance_mode_controller.go b/addons/maintenance_mode_controller.go index a91c0e49..4f6fdfe4 100644 --- a/addons/maintenance_mode_controller.go +++ b/addons/maintenance_mode_controller.go @@ -22,7 +22,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/source" ) type MaintenanceModeReconciler struct { @@ -34,7 +33,7 @@ type MaintenanceModeReconciler struct { func (r *MaintenanceModeReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). Named("maintenancemode_controller"). - Watches(&source.Kind{Type: &ramenv1alpha1.MaintenanceMode{}}, &handler.EnqueueRequestForObject{}, + Watches(&ramenv1alpha1.MaintenanceMode{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Complete(r) } @@ -49,7 +48,7 @@ func (r *MaintenanceModeReconciler) Reconcile(ctx context.Context, req ctrl.Requ klog.Infof("Could not find MaintenanceMode. Ignoring since object must have been deleted.") return ctrl.Result{}, nil } - klog.Errorf("Failed to get MaintenanceMode.", err) + klog.Error("Failed to get MaintenanceMode.", err) return ctrl.Result{}, err } @@ -80,7 +79,7 @@ func (r *MaintenanceModeReconciler) Reconcile(ctx context.Context, req ctrl.Requ klog.Errorf("failed to complete maintenance actions on %s. err=%v", mmode.Name, err) return result, err } - if !result.Requeue && err == nil { + if !result.Requeue { mmode.Finalizers = utils.RemoveString(mmode.Finalizers, MaintenanceModeFinalizer) err = r.SpokeClient.Update(ctx, &mmode) if err != nil { @@ -136,7 +135,7 @@ func (r *MaintenanceModeReconciler) startMaintenanceActions(ctx context.Context, SetStatus(mmode, mode, ramenv1alpha1.MModeStateError, err) return result, err } - if !result.Requeue && err == nil { + if !result.Requeue { SetStatus(mmode, mode, ramenv1alpha1.MModeStateCompleted, nil) } return result, err diff --git a/addons/manager.go b/addons/manager.go index f311b123..aa08108c 100644 --- a/addons/manager.go +++ b/addons/manager.go @@ -222,12 +222,12 @@ func runSpokeManager(ctx context.Context, options AddonAgentOptions) { if err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { klog.Infof("Waiting for MaintenanceMode CRD to be created. MaintenanceMode controller is not running yet.") // Wait for 45s as it takes time for MaintenanceMode CRD to be created. - return runtimewait.PollUntilWithContext(ctx, 15*time.Second, + return runtimewait.PollUntilContextCancel(ctx, 15*time.Second, true, func(ctx context.Context) (done bool, err error) { var crd extv1.CustomResourceDefinition readErr := mgr.GetAPIReader().Get(ctx, types.NamespacedName{Name: "maintenancemodes.ramendr.openshift.io"}, &crd) if readErr != nil { - klog.Errorf("Unable to get MaintenanceMode CRD", readErr) + klog.Error("Unable to get MaintenanceMode CRD", readErr) // Do not initialize err as we want to retry. // err!=nil or done==true will end polling. done = false @@ -239,7 +239,7 @@ func runSpokeManager(ctx context.Context, options AddonAgentOptions) { SpokeClient: mgr.GetClient(), SpokeClusterName: options.SpokeClusterName, }).SetupWithManager(mgr); err != nil { - klog.Errorf("Unable to create MaintenanceMode controller.", err) + klog.Error("Unable to create MaintenanceMode controller.", err) return } klog.Infof("MaintenanceMode CRD exists. MaintenanceMode controller is now running.") @@ -250,7 +250,7 @@ func runSpokeManager(ctx context.Context, options AddonAgentOptions) { return }) })); err != nil { - klog.Errorf("unable to poll MaintenanceMode", err) + klog.Error("unable to poll MaintenanceMode", err) os.Exit(1) } diff --git a/addons/s3_controller.go b/addons/s3_controller.go index d6351b87..7c1e3a1f 100644 --- a/addons/s3_controller.go +++ b/addons/s3_controller.go @@ -18,7 +18,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/source" ) // S3SecretReconciler reconciles a MirrorPeer object @@ -59,7 +58,7 @@ func (r *S3SecretReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). Named("s3secret_controller"). - Watches(&source.Kind{Type: &obv1alpha1.ObjectBucketClaim{}}, &handler.EnqueueRequestForObject{}, + Watches(&obv1alpha1.ObjectBucketClaim{}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(predicate.GenerationChangedPredicate{}, s3BucketPredicate)). Complete(r) } @@ -68,14 +67,14 @@ func (r *S3SecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c var err error var obc obv1alpha1.ObjectBucketClaim - klog.Infof("Reconciling OBC", "OBC", req.NamespacedName.String()) + klog.Info("Reconciling OBC", "OBC", req.NamespacedName.String()) err = r.SpokeClient.Get(ctx, req.NamespacedName, &obc) if err != nil { if errors.IsNotFound(err) { - klog.Infof("Could not find OBC. Ignoring since object must have been deleted.") + klog.Info("Could not find OBC. Ignoring since object must have been deleted.") return ctrl.Result{}, nil } - klog.Errorf("Failed to get OBC.", err) + klog.Error("Failed to get OBC.", err) return ctrl.Result{}, err } diff --git a/addons/s3_secret_handler.go b/addons/s3_secret_handler.go index 5b68182f..1ced9a76 100644 --- a/addons/s3_secret_handler.go +++ b/addons/s3_secret_handler.go @@ -55,7 +55,7 @@ func (r *S3SecretReconciler) syncBlueSecretForS3(ctx context.Context, name strin } if storageClusterRef == nil { - klog.Error("failed to find storage cluster ref using spoke cluster name %s from mirrorpeers ", r.SpokeClusterName) + klog.Errorf("failed to find storage cluster ref using spoke cluster name %s from mirrorpeers ", r.SpokeClusterName) return err } diff --git a/api/v1alpha1/mirrorpeer_webhook.go b/api/v1alpha1/mirrorpeer_webhook.go index a9e19ee1..63dd4381 100644 --- a/api/v1alpha1/mirrorpeer_webhook.go +++ b/api/v1alpha1/mirrorpeer_webhook.go @@ -23,27 +23,15 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. var mirrorpeerlog = logf.Log.WithName("mirrorpeer-webhook") -const ( - WebhookCertDir = "/apiserver.local.config/certificates" - WebhookCertName = "apiserver.crt" - WebhookKeyName = "apiserver.key" -) - func (r *MirrorPeer) SetupWebhookWithManager(mgr ctrl.Manager) error { - bldr := ctrl.NewWebhookManagedBy(mgr). - For(r) - - srv := mgr.GetWebhookServer() - srv.CertDir = WebhookCertDir - srv.CertName = WebhookCertName - srv.KeyName = WebhookKeyName - - return bldr.Complete() + return ctrl.NewWebhookManagedBy(mgr). + For(r).Complete() } //+kubebuilder:webhook:path=/mutate-multicluster-odf-openshift-io-v1alpha1-mirrorpeer,mutating=true,failurePolicy=fail,sideEffects=None,groups=multicluster.odf.openshift.io,resources=mirrorpeers,verbs=create;update,versions=v1alpha1,name=mmirrorpeer.kb.io,admissionReviewVersions=v1;v1beta1 @@ -58,26 +46,25 @@ func (r *MirrorPeer) Default() {} var _ webhook.Validator = &MirrorPeer{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *MirrorPeer) ValidateCreate() error { +func (r *MirrorPeer) ValidateCreate() (warnings admission.Warnings, err error) { mirrorpeerlog.Info("validate create", "name", r.ObjectMeta.Name) - - return validateMirrorPeer(r) + return []string{}, validateMirrorPeer(r) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *MirrorPeer) ValidateUpdate(old runtime.Object) error { +func (r *MirrorPeer) ValidateUpdate(old runtime.Object) (warnings admission.Warnings, err error) { mirrorpeerlog.Info("validate update", "name", r.ObjectMeta.Name) oldMirrorPeer, ok := old.(*MirrorPeer) if !ok { - return fmt.Errorf("error casting old object to MirrorPeer") + return []string{}, fmt.Errorf("error casting old object to MirrorPeer") } if len(r.Spec.Items) != len(oldMirrorPeer.Spec.Items) { - return fmt.Errorf("error updating MirrorPeer, new and old spec.items have different lengths") + return []string{}, fmt.Errorf("error updating MirrorPeer, new and old spec.items have different lengths") } if r.Spec.Type != oldMirrorPeer.Spec.Type { - return fmt.Errorf("error updating MirrorPeer, the type cannot be changed from %s to %s", oldMirrorPeer.Spec.Type, r.Spec.Type) + return []string{}, fmt.Errorf("error updating MirrorPeer, the type cannot be changed from %s to %s", oldMirrorPeer.Spec.Type, r.Spec.Type) } refs := make(map[string]int) @@ -89,14 +76,14 @@ func (r *MirrorPeer) ValidateUpdate(old runtime.Object) error { for _, pr := range r.Spec.Items { key := fmt.Sprintf("%s-%s-%s", pr.ClusterName, pr.StorageClusterRef.Namespace, pr.StorageClusterRef.Name) if _, ok := refs[key]; !ok { - return fmt.Errorf("error validating update: new MirrorPeer %s references a StorageCluster %s/%s that is not in the old MirrorPeer", r.ObjectMeta.Name, pr.StorageClusterRef.Namespace, pr.StorageClusterRef.Name) + return []string{}, fmt.Errorf("error validating update: new MirrorPeer %s references a StorageCluster %s/%s that is not in the old MirrorPeer", r.ObjectMeta.Name, pr.StorageClusterRef.Namespace, pr.StorageClusterRef.Name) } } if oldMirrorPeer.Spec.OverlappingCIDR && !r.Spec.OverlappingCIDR { - return fmt.Errorf("error updating MirrorPeer: OverlappingCIDR value can not be changed from %t to %t. This is to prevent Disaster Recovery from being unusable between clusters that have overlapping IPs", oldMirrorPeer.Spec.OverlappingCIDR, r.Spec.OverlappingCIDR) + return []string{}, fmt.Errorf("error updating MirrorPeer: OverlappingCIDR value can not be changed from %t to %t. This is to prevent Disaster Recovery from being unusable between clusters that have overlapping IPs", oldMirrorPeer.Spec.OverlappingCIDR, r.Spec.OverlappingCIDR) } - return validateMirrorPeer(r) + return []string{}, validateMirrorPeer(r) } // validateMirrorPeer validates the MirrorPeer @@ -108,7 +95,7 @@ func validateMirrorPeer(instance *MirrorPeer) error { } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *MirrorPeer) ValidateDelete() error { +func (r *MirrorPeer) ValidateDelete() (warnings admission.Warnings, err error) { mirrorpeerlog.Info("validate delete", "name", r.ObjectMeta.Name) - return nil + return []string{}, nil } diff --git a/bundle/manifests/odf-multicluster-orchestrator.clusterserviceversion.yaml b/bundle/manifests/odf-multicluster-orchestrator.clusterserviceversion.yaml index fafb6d34..c234e516 100644 --- a/bundle/manifests/odf-multicluster-orchestrator.clusterserviceversion.yaml +++ b/bundle/manifests/odf-multicluster-orchestrator.clusterserviceversion.yaml @@ -36,7 +36,7 @@ metadata: ] capabilities: Basic Install console.openshift.io/plugins: '["odf-multicluster-console"]' - createdAt: "2024-03-20T12:51:52Z" + createdAt: "2024-03-21T07:54:52Z" olm.skipRange: "" operators.openshift.io/infrastructure-features: '["disconnected"]' operators.operatorframework.io/builder: operator-sdk-v1.34.1 diff --git a/controllers/drpolicy_controller.go b/controllers/drpolicy_controller.go index 5dc22ddd..619a6c19 100644 --- a/controllers/drpolicy_controller.go +++ b/controllers/drpolicy_controller.go @@ -218,7 +218,7 @@ func (r *DRPolicyReconciler) fetchClusterFSIDs(ctx context.Context, peer *multic hs, err := utils.FetchSecretWithName(ctx, r.HubClient, types.NamespacedName{Name: rookSecretName, Namespace: pr.ClusterName}) if err != nil { if errors.IsNotFound(err) { - klog.Info("could not find secret %q. will attempt to fetch it again after a delay", rookSecretName) + klog.Infof("could not find secret %q. will attempt to fetch it again after a delay", rookSecretName) } return err } diff --git a/controllers/manager.go b/controllers/manager.go index 24c641c9..029cc30e 100644 --- a/controllers/manager.go +++ b/controllers/manager.go @@ -25,6 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/webhook" ) var ( @@ -44,6 +45,12 @@ func init() { //+kubebuilder:scaffold:scheme } +const ( + WebhookCertDir = "/apiserver.local.config/certificates" + WebhookCertName = "apiserver.crt" + WebhookKeyName = "apiserver.key" +) + type ManagerOptions struct { MetricsAddr string EnableLeaderElection bool @@ -89,6 +96,12 @@ func (o *ManagerOptions) runManager() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&o.ZapOpts))) setupLog := ctrl.Log.WithName("setup") + srv := webhook.NewServer(webhook.Options{ + CertDir: WebhookCertDir, + CertName: WebhookCertName, + KeyName: WebhookKeyName, + }) + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: mgrScheme, MetricsBindAddress: o.MetricsAddr, @@ -96,6 +109,7 @@ func (o *ManagerOptions) runManager() { HealthProbeBindAddress: o.ProbeAddr, LeaderElection: o.EnableLeaderElection, LeaderElectionID: "1d19c724.odf.openshift.io", + WebhookServer: srv, }) if err != nil { setupLog.Error(err, "unable to start manager") diff --git a/controllers/mirrorpeersecret_controller.go b/controllers/mirrorpeersecret_controller.go index b587e537..df48f0d2 100644 --- a/controllers/mirrorpeersecret_controller.go +++ b/controllers/mirrorpeersecret_controller.go @@ -35,7 +35,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" "sigs.k8s.io/yaml" ) @@ -136,11 +135,11 @@ func mirrorPeerSecretReconcile(ctx context.Context, rc client.Client, req ctrl.R func (r *MirrorPeerSecretReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&corev1.Secret{}, builder.WithPredicates(utils.SourceOrDestinationPredicate)). - Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(r.secretConfigMapFunc)). + Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.secretConfigMapFunc)). Complete(r) } -func (r *MirrorPeerSecretReconciler) secretConfigMapFunc(obj client.Object) []reconcile.Request { +func (r *MirrorPeerSecretReconciler) secretConfigMapFunc(ctx context.Context, obj client.Object) []reconcile.Request { ConfigMapRamenConfigKeyName := "ramen_manager_config.yaml" var cm *corev1.ConfigMap cm, ok := obj.(*corev1.ConfigMap)