From d663ec029884928d9d4e046240518921d5c1ad24 Mon Sep 17 00:00:00 2001 From: Brandon Palm Date: Mon, 22 Sep 2025 14:42:12 -0500 Subject: [PATCH] Consolidate around klog/v2 --- go.mod | 2 +- pkg/controller/istiocsr/certificates.go | 7 +- pkg/controller/istiocsr/controller.go | 32 +-- pkg/controller/istiocsr/deployments.go | 11 +- pkg/controller/istiocsr/install_istiocsr.go | 13 +- pkg/controller/istiocsr/rbacs.go | 53 ++--- pkg/controller/istiocsr/serviceaccounts.go | 5 +- pkg/controller/istiocsr/services.go | 7 +- pkg/controller/istiocsr/test_utils.go | 3 - pkg/controller/istiocsr/utils.go | 5 +- pkg/operator/setup_manager.go | 5 +- vendor/github.com/go-logr/logr/testr/testr.go | 167 -------------- vendor/k8s.io/klog/v2/klogr/README.md | 19 ++ vendor/k8s.io/klog/v2/klogr/klogr.go | 208 ++++++++++++++++++ vendor/modules.txt | 2 +- 15 files changed, 302 insertions(+), 237 deletions(-) delete mode 100644 vendor/github.com/go-logr/logr/testr/testr.go create mode 100644 vendor/k8s.io/klog/v2/klogr/README.md create mode 100644 vendor/k8s.io/klog/v2/klogr/klogr.go diff --git a/go.mod b/go.mod index fef1554ec..6f88b62e8 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.25.0 require ( github.com/cert-manager/cert-manager v1.19.2 github.com/go-bindata/go-bindata v3.1.2+incompatible - github.com/go-logr/logr v1.4.3 github.com/google/go-cmp v0.7.0 github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee @@ -48,6 +47,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.22.1 // indirect github.com/go-openapi/jsonreference v0.21.2 // indirect diff --git a/pkg/controller/istiocsr/certificates.go b/pkg/controller/istiocsr/certificates.go index dabec165c..1d528e714 100644 --- a/pkg/controller/istiocsr/certificates.go +++ b/pkg/controller/istiocsr/certificates.go @@ -6,6 +6,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" @@ -22,7 +23,7 @@ func (r *Reconciler) createOrApplyCertificates(istiocsr *v1alpha1.IstioCSR, reso } certificateName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling certificate resource", "name", certificateName) + klog.V(4).InfoS("reconciling certificate resource", "name", certificateName) fetched := &certmanagerv1.Certificate{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -33,13 +34,13 @@ func (r *Reconciler) createOrApplyCertificates(istiocsr *v1alpha1.IstioCSR, reso r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s certificate resource already exists, maybe from previous installation", certificateName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("certificate has been modified, updating to desired state", "name", certificateName) + klog.V(1).InfoS("certificate has been modified, updating to desired state", "name", certificateName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s certificate resource", certificateName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "certificate resource %s reconciled back to desired state", certificateName) } else { - r.log.V(4).Info("certificate resource already exists and is in expected state", "name", certificateName) + klog.V(4).InfoS("certificate resource already exists and is in expected state", "name", certificateName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { diff --git a/pkg/controller/istiocsr/controller.go b/pkg/controller/istiocsr/controller.go index cf151bc94..ec85cc898 100644 --- a/pkg/controller/istiocsr/controller.go +++ b/pkg/controller/istiocsr/controller.go @@ -18,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -27,8 +28,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/go-logr/logr" - certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" v1alpha1 "github.com/openshift/cert-manager-operator/api/operator/v1alpha1" @@ -50,7 +49,6 @@ type Reconciler struct { ctx context.Context eventRecorder record.EventRecorder - log logr.Logger scheme *runtime.Scheme } @@ -116,7 +114,6 @@ func New(mgr ctrl.Manager) (*Reconciler, error) { ctrlClient: c, ctx: context.Background(), eventRecorder: mgr.GetEventRecorderFor(ControllerName), - log: ctrl.Log.WithName(ControllerName), scheme: mgr.GetScheme(), }, nil } @@ -124,7 +121,7 @@ func New(mgr ctrl.Manager) (*Reconciler, error) { // SetupWithManager sets up the controller with the Manager. func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { mapFunc := func(ctx context.Context, obj client.Object) []reconcile.Request { - r.log.V(4).Info("received reconcile event", "object", fmt.Sprintf("%T", obj), "name", obj.GetName(), "namespace", obj.GetNamespace()) + klog.V(4).InfoS("received reconcile event", "object", fmt.Sprintf("%T", obj), "name", obj.GetName(), "namespace", obj.GetNamespace()) objLabels := obj.GetLabels() if objLabels != nil { @@ -146,7 +143,10 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { } key := strings.Split(value, "_") if len(key) != 2 { - r.log.Error(fmt.Errorf("invalid label format"), "%s label value(%s) not in expected format on %s resource", IstiocsrResourceWatchLabelName, value, obj.GetName()) + klog.ErrorS(fmt.Errorf("invalid label format"), "label value not in expected format", + "labelName", IstiocsrResourceWatchLabelName, + "labelValue", value, + "resource", obj.GetName()) return false } namespace = key[0] @@ -165,7 +165,7 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { } } - r.log.V(4).Info("object not of interest, ignoring reconcile event", "object", fmt.Sprintf("%T", obj), "name", obj.GetName(), "namespace", obj.GetNamespace()) + klog.V(4).InfoS("object not of interest, ignoring reconcile event", "object", fmt.Sprintf("%T", obj), "name", obj.GetName(), "namespace", obj.GetNamespace()) return []reconcile.Request{} } @@ -214,7 +214,7 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { // Reconcile function to compare the state specified by the IstioCSR object against the actual cluster state, // and to make the cluster state reflect the state specified by the user. func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - r.log.V(1).Info("reconciling", "request", req) + klog.V(1).InfoS("reconciling", "request", req) // Fetch the istiocsr.openshift.operator.io CR istiocsr := &v1alpha1.IstioCSR{} @@ -223,14 +223,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu // NotFound errors, since they can't be fixed by an immediate // requeue (have to wait for a new notification), and can be processed // on deleted requests. - r.log.V(1).Info("istiocsr.openshift.operator.io object not found, skipping reconciliation", "request", req) + klog.V(1).InfoS("istiocsr.openshift.operator.io object not found, skipping reconciliation", "request", req) return ctrl.Result{}, nil } return ctrl.Result{}, fmt.Errorf("failed to fetch istiocsr.openshift.operator.io %q during reconciliation: %w", req.NamespacedName, err) } if !istiocsr.DeletionTimestamp.IsZero() { - r.log.V(1).Info("istiocsr.openshift.operator.io is marked for deletion", "namespace", req.NamespacedName) + klog.V(1).InfoS("istiocsr.openshift.operator.io is marked for deletion", "namespace", req.NamespacedName) if requeue, err := r.cleanUp(istiocsr); err != nil { return ctrl.Result{}, fmt.Errorf("clean up failed for %q istiocsr.openshift.operator.io instance deletion: %w", req.NamespacedName, err) @@ -242,7 +242,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return ctrl.Result{}, err } - r.log.V(1).Info("removed finalizer, cleanup complete", "request", req.NamespacedName) + klog.V(1).InfoS("removed finalizer, cleanup complete", "request", req.NamespacedName) return ctrl.Result{}, nil } @@ -257,7 +257,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu func (r *Reconciler) processReconcileRequest(istiocsr *v1alpha1.IstioCSR, req types.NamespacedName) (ctrl.Result, error) { istioCSRCreateRecon := false if !containsProcessedAnnotation(istiocsr) && reflect.DeepEqual(istiocsr.Status, v1alpha1.IstioCSRStatus{}) { - r.log.V(1).Info("starting reconciliation of newly created istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) + klog.V(1).InfoS("starting reconciliation of newly created istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) istioCSRCreateRecon = true } @@ -271,14 +271,14 @@ func (r *Reconciler) processReconcileRequest(istiocsr *v1alpha1.IstioCSR, req ty var errUpdate error = nil if err := r.reconcileIstioCSRDeployment(istiocsr, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile IstioCSR deployment", "request", req) + klog.ErrorS(err, "failed to reconcile IstioCSR deployment", "request", req) if IsIrrecoverableError(err) { // Set both conditions atomically before updating status degradedChanged := istiocsr.Status.SetCondition(v1alpha1.Degraded, metav1.ConditionTrue, v1alpha1.ReasonFailed, fmt.Sprintf("reconciliation failed with irrecoverable error not retrying: %v", err)) readyChanged := istiocsr.Status.SetCondition(v1alpha1.Ready, metav1.ConditionFalse, v1alpha1.ReasonReady, "") if degradedChanged || readyChanged { - r.log.V(2).Info("updating istiocsr conditions on irrecoverable error", + klog.V(2).InfoS("updating istiocsr conditions on irrecoverable error", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName(), "degradedChanged", degradedChanged, @@ -293,7 +293,7 @@ func (r *Reconciler) processReconcileRequest(istiocsr *v1alpha1.IstioCSR, req ty readyChanged := istiocsr.Status.SetCondition(v1alpha1.Ready, metav1.ConditionFalse, v1alpha1.ReasonInProgress, fmt.Sprintf("reconciliation failed, retrying: %v", err)) if degradedChanged || readyChanged { - r.log.V(2).Info("updating istiocsr conditions on recoverable error", + klog.V(2).InfoS("updating istiocsr conditions on recoverable error", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName(), "degradedChanged", degradedChanged, @@ -315,7 +315,7 @@ func (r *Reconciler) processReconcileRequest(istiocsr *v1alpha1.IstioCSR, req ty readyChanged := istiocsr.Status.SetCondition(v1alpha1.Ready, metav1.ConditionTrue, v1alpha1.ReasonReady, "reconciliation successful") if degradedChanged || readyChanged { - r.log.V(2).Info("updating istiocsr conditions on successful reconciliation", + klog.V(2).InfoS("updating istiocsr conditions on successful reconciliation", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName(), "degradedChanged", degradedChanged, diff --git a/pkg/controller/istiocsr/deployments.go b/pkg/controller/istiocsr/deployments.go index 4c8f9fa78..cac0695d4 100644 --- a/pkg/controller/istiocsr/deployments.go +++ b/pkg/controller/istiocsr/deployments.go @@ -15,6 +15,7 @@ import ( metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/apis/core" corevalidation "k8s.io/kubernetes/pkg/apis/core/validation" "sigs.k8s.io/controller-runtime/pkg/client" @@ -38,7 +39,7 @@ func (r *Reconciler) createOrApplyDeployments(istiocsr *v1alpha1.IstioCSR, resou } deploymentName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling deployment resource", "name", deploymentName) + klog.V(4).InfoS("reconciling deployment resource", "name", deploymentName) fetched := &appsv1.Deployment{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -49,13 +50,13 @@ func (r *Reconciler) createOrApplyDeployments(istiocsr *v1alpha1.IstioCSR, resou r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s deployment resource already exists, maybe from previous installation", deploymentName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("deployment has been modified, updating to desired state", "name", deploymentName) + klog.V(1).InfoS("deployment has been modified, updating to desired state", "name", deploymentName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s deployment resource", deploymentName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "deployment resource %s reconciled back to desired state", deploymentName) } else { - r.log.V(4).Info("deployment resource already exists and is in expected state", "name", deploymentName) + klog.V(4).InfoS("deployment resource already exists and is in expected state", "name", deploymentName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -555,13 +556,13 @@ func (r *Reconciler) createOrUpdateCAConfigMap(istiocsr *v1alpha1.IstioCSR, cert } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("ca configmap need update", "name", configmapKey) + klog.V(1).InfoS("ca configmap need update", "name", configmapKey) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return fmt.Errorf("failed to update %s configmap resource: %w", configmapKey, err) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "configmap resource %s reconciled back to desired state", configmapKey) } else { - r.log.V(4).Info("configmap resource already exists and is in expected state", "name", configmapKey) + klog.V(4).InfoS("configmap resource already exists and is in expected state", "name", configmapKey) } if !exist { diff --git a/pkg/controller/istiocsr/install_istiocsr.go b/pkg/controller/istiocsr/install_istiocsr.go index cc7a82ec3..04d9150c5 100644 --- a/pkg/controller/istiocsr/install_istiocsr.go +++ b/pkg/controller/istiocsr/install_istiocsr.go @@ -5,6 +5,7 @@ import ( "maps" "github.com/openshift/cert-manager-operator/api/operator/v1alpha1" + "k8s.io/klog/v2" ) func (r *Reconciler) reconcileIstioCSRDeployment(istiocsr *v1alpha1.IstioCSR, istioCSRCreateRecon bool) error { @@ -26,27 +27,27 @@ func (r *Reconciler) reconcileIstioCSRDeployment(istiocsr *v1alpha1.IstioCSR, is } if err := r.createOrApplyServices(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile service resource") + klog.ErrorS(err, "failed to reconcile service resource") return err } if err := r.createOrApplyServiceAccounts(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile serviceaccount resource") + klog.ErrorS(err, "failed to reconcile serviceaccount resource") return err } if err := r.createOrApplyRBACResource(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile rbac resources") + klog.ErrorS(err, "failed to reconcile rbac resources") return err } if err := r.createOrApplyCertificates(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile certificate resource") + klog.ErrorS(err, "failed to reconcile certificate resource") return err } if err := r.createOrApplyDeployments(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile deployment resource") + klog.ErrorS(err, "failed to reconcile deployment resource") return err } @@ -56,6 +57,6 @@ func (r *Reconciler) reconcileIstioCSRDeployment(istiocsr *v1alpha1.IstioCSR, is } } - r.log.V(4).Info("finished reconciliation of istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) + klog.V(4).InfoS("finished reconciliation of istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) return nil } diff --git a/pkg/controller/istiocsr/rbacs.go b/pkg/controller/istiocsr/rbacs.go index 6e10bbf68..34f2306e7 100644 --- a/pkg/controller/istiocsr/rbacs.go +++ b/pkg/controller/istiocsr/rbacs.go @@ -5,6 +5,7 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/openshift/cert-manager-operator/api/operator/v1alpha1" @@ -20,32 +21,32 @@ func (r *Reconciler) createOrApplyRBACResource(istiocsr *v1alpha1.IstioCSR, reso clusterRoleName, err := r.createOrApplyClusterRoles(istiocsr, resourceLabels, istioCSRCreateRecon) if err != nil { - r.log.Error(err, "failed to reconcile clusterrole resource") + klog.ErrorS(err, "failed to reconcile clusterrole resource") return err } if err := r.createOrApplyClusterRoleBindings(istiocsr, clusterRoleName, serviceAccount, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile clusterrolebinding resource") + klog.ErrorS(err, "failed to reconcile clusterrolebinding resource") return err } if err := r.createOrApplyRoles(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile role resource") + klog.ErrorS(err, "failed to reconcile role resource") return err } if err := r.createOrApplyRoleBindings(istiocsr, serviceAccount, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile rolebinding resource") + klog.ErrorS(err, "failed to reconcile rolebinding resource") return err } if err := r.createOrApplyRoleForLeases(istiocsr, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile role for leases resource") + klog.ErrorS(err, "failed to reconcile role for leases resource") return err } if err := r.createOrApplyRoleBindingForLeases(istiocsr, serviceAccount, resourceLabels, istioCSRCreateRecon); err != nil { - r.log.Error(err, "failed to reconcile rolebinding for leases resource") + klog.ErrorS(err, "failed to reconcile rolebinding for leases resource") return err } @@ -62,7 +63,7 @@ func (r *Reconciler) createOrApplyClusterRoles(istiocsr *v1alpha1.IstioCSR, reso key client.ObjectKey fetched = &rbacv1.ClusterRole{} ) - r.log.V(4).Info("reconciling clusterrole resource created for istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) + klog.V(4).InfoS("reconciling clusterrole resource created for istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) if istiocsr.Status.ClusterRole != "" { roleName = fmt.Sprintf("%s/%s", desired.GetNamespace(), istiocsr.Status.ClusterRole) fetched = &rbacv1.ClusterRole{} @@ -99,13 +100,13 @@ func (r *Reconciler) createOrApplyClusterRoles(istiocsr *v1alpha1.IstioCSR, reso r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s clusterrole resource already exists, maybe from previous installation", roleName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("clusterrole has been modified, updating to desired state", "name", roleName) + klog.V(1).InfoS("clusterrole has been modified, updating to desired state", "name", roleName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return "", FromClientError(err, "failed to update %s clusterrole resource", roleName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "clusterrole resource %s reconciled back to desired state", roleName) } else { - r.log.V(4).Info("clusterrole resource already exists and is in expected state", "name", roleName) + klog.V(4).InfoS("clusterrole resource already exists and is in expected state", "name", roleName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -138,7 +139,7 @@ func (r *Reconciler) updateClusterRoleNameInStatus(istiocsr *v1alpha1.IstioCSR, if existing != nil && existing.GetName() != "" { name = existing.GetName() } else { - r.log.Error(fmt.Errorf("error updating clusterrole name in status"), "istiocsr", istiocsr.GetNamespace()) + klog.ErrorS(fmt.Errorf("error updating clusterrole name in status"), "status update error", "istiocsr", istiocsr.GetNamespace()) } } istiocsr.Status.ClusterRole = name @@ -155,7 +156,7 @@ func (r *Reconciler) createOrApplyClusterRoleBindings(istiocsr *v1alpha1.IstioCS key client.ObjectKey fetched = &rbacv1.ClusterRoleBinding{} ) - r.log.V(4).Info("reconciling clusterrolebinding resource created for istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) + klog.V(4).InfoS("reconciling clusterrolebinding resource created for istiocsr", "namespace", istiocsr.GetNamespace(), "name", istiocsr.GetName()) if istiocsr.Status.ClusterRoleBinding != "" { roleBindingName = fmt.Sprintf("%s/%s", desired.GetNamespace(), istiocsr.Status.ClusterRoleBinding) fetched = &rbacv1.ClusterRoleBinding{} @@ -192,13 +193,13 @@ func (r *Reconciler) createOrApplyClusterRoleBindings(istiocsr *v1alpha1.IstioCS r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s clusterrolebinding resource already exists, maybe from previous installation", roleBindingName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("clusterrolebinding has been modified, updating to desired state", "name", roleBindingName) + klog.V(1).InfoS("clusterrolebinding has been modified, updating to desired state", "name", roleBindingName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s clusterrolebinding resource", roleBindingName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "clusterrolebinding resource %s reconciled back to desired state", roleBindingName) } else { - r.log.V(4).Info("clusterrolebinding resource already exists and is in expected state", "name", roleBindingName) + klog.V(4).InfoS("clusterrolebinding resource already exists and is in expected state", "name", roleBindingName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -228,7 +229,7 @@ func (r *Reconciler) updateClusterRoleBindingNameInStatus(istiocsr *v1alpha1.Ist if existing != nil && existing.GetName() != "" { name = existing.GetName() } else { - r.log.Error(fmt.Errorf("error updating clusterrolebinding name in status"), "istiocsr", istiocsr.GetNamespace()) + klog.ErrorS(fmt.Errorf("error updating clusterrolebinding name in status"), "status update error", "istiocsr", istiocsr.GetNamespace()) } } istiocsr.Status.ClusterRoleBinding = name @@ -239,7 +240,7 @@ func (r *Reconciler) createOrApplyRoles(istiocsr *v1alpha1.IstioCSR, resourceLab desired := r.getRoleObject(istiocsr.GetNamespace(), istiocsr.Spec.IstioCSRConfig.Istio.Namespace, resourceLabels) roleName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling role resource", "name", roleName) + klog.V(4).InfoS("reconciling role resource", "name", roleName) fetched := &rbacv1.Role{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -250,13 +251,13 @@ func (r *Reconciler) createOrApplyRoles(istiocsr *v1alpha1.IstioCSR, resourceLab r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s role resource already exists, maybe from previous installation", roleName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("role has been modified, updating to desired state", "name", roleName) + klog.V(1).InfoS("role has been modified, updating to desired state", "name", roleName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s role resource", roleName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "role resource %s reconciled back to desired state", roleName) } else { - r.log.V(4).Info("role resource already exists and is in expected state", "name", roleName) + klog.V(4).InfoS("role resource already exists and is in expected state", "name", roleName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -279,7 +280,7 @@ func (r *Reconciler) createOrApplyRoleBindings(istiocsr *v1alpha1.IstioCSR, serv desired := r.getRoleBindingObject(serviceAccount, istiocsr.GetNamespace(), istiocsr.Spec.IstioCSRConfig.Istio.Namespace, resourceLabels) roleBindingName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling rolebinding resource", "name", roleBindingName) + klog.V(4).InfoS("reconciling rolebinding resource", "name", roleBindingName) fetched := &rbacv1.RoleBinding{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -290,13 +291,13 @@ func (r *Reconciler) createOrApplyRoleBindings(istiocsr *v1alpha1.IstioCSR, serv r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s rolebinding resource already exists, maybe from previous installation", roleBindingName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("rolebinding has been modified, updating to desired state", "name", roleBindingName) + klog.V(1).InfoS("rolebinding has been modified, updating to desired state", "name", roleBindingName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s rolebinding resource", roleBindingName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "rolebinding resource %s reconciled back to desired state", roleBindingName) } else { - r.log.V(4).Info("rolebinding resource already exists and is in expected state", "name", roleBindingName) + klog.V(4).InfoS("rolebinding resource already exists and is in expected state", "name", roleBindingName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -320,7 +321,7 @@ func (r *Reconciler) createOrApplyRoleForLeases(istiocsr *v1alpha1.IstioCSR, res desired := r.getRoleForLeasesObject(istiocsr.GetNamespace(), istiocsr.Spec.IstioCSRConfig.Istio.Namespace, resourceLabels) roleName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling role for lease resource", "name", roleName) + klog.V(4).InfoS("reconciling role for lease resource", "name", roleName) fetched := &rbacv1.Role{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -331,13 +332,13 @@ func (r *Reconciler) createOrApplyRoleForLeases(istiocsr *v1alpha1.IstioCSR, res r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s role resource already exists, maybe from previous installation", roleName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("role has been modified, updating to desired state", "name", roleName) + klog.V(1).InfoS("role has been modified, updating to desired state", "name", roleName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s role resource", roleName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "role resource %s reconciled back to desired state", roleName) } else { - r.log.V(4).Info("role resource already exists and is in expected state", "name", roleName) + klog.V(4).InfoS("role resource already exists and is in expected state", "name", roleName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { @@ -360,7 +361,7 @@ func (r *Reconciler) createOrApplyRoleBindingForLeases(istiocsr *v1alpha1.IstioC desired := r.getRoleBindingForLeasesObject(serviceAccount, istiocsr.GetNamespace(), istiocsr.Spec.IstioCSRConfig.Istio.Namespace, resourceLabels) roleBindingName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling rolebinding for lease resource", "name", roleBindingName) + klog.V(4).InfoS("reconciling rolebinding for lease resource", "name", roleBindingName) fetched := &rbacv1.RoleBinding{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -371,13 +372,13 @@ func (r *Reconciler) createOrApplyRoleBindingForLeases(istiocsr *v1alpha1.IstioC r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s rolebinding resource already exists, maybe from previous installation", roleBindingName) } if exist && hasObjectChanged(desired, fetched) { - r.log.V(1).Info("rolebinding has been modified, updating to desired state", "name", roleBindingName) + klog.V(1).InfoS("rolebinding has been modified, updating to desired state", "name", roleBindingName) if err := r.UpdateWithRetry(r.ctx, desired); err != nil { return FromClientError(err, "failed to update %s rolebinding resource", roleBindingName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "rolebinding resource %s reconciled back to desired state", roleBindingName) } else { - r.log.V(4).Info("rolebinding resource already exists and is in expected state", "name", roleBindingName) + klog.V(4).InfoS("rolebinding resource already exists and is in expected state", "name", roleBindingName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { diff --git a/pkg/controller/istiocsr/serviceaccounts.go b/pkg/controller/istiocsr/serviceaccounts.go index ed10ee237..018dda4ae 100644 --- a/pkg/controller/istiocsr/serviceaccounts.go +++ b/pkg/controller/istiocsr/serviceaccounts.go @@ -4,6 +4,7 @@ import ( "fmt" corev1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/openshift/cert-manager-operator/api/operator/v1alpha1" @@ -14,7 +15,7 @@ func (r *Reconciler) createOrApplyServiceAccounts(istiocsr *v1alpha1.IstioCSR, r desired := r.getServiceAccountObject(istiocsr, resourceLabels) serviceAccountName := fmt.Sprintf("%s/%s", desired.GetNamespace(), desired.GetName()) - r.log.V(4).Info("reconciling serviceaccount resource", "name", serviceAccountName) + klog.V(4).InfoS("reconciling serviceaccount resource", "name", serviceAccountName) fetched := &corev1.ServiceAccount{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(desired), fetched) if err != nil { @@ -25,7 +26,7 @@ func (r *Reconciler) createOrApplyServiceAccounts(istiocsr *v1alpha1.IstioCSR, r if istioCSRCreateRecon { r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s serviceaccount resource already exists, maybe from previous installation", serviceAccountName) } - r.log.V(4).Info("serviceaccount resource already exists and is in expected state", "name", serviceAccountName) + klog.V(4).InfoS("serviceaccount resource already exists and is in expected state", "name", serviceAccountName) } if !exist { if err := r.Create(r.ctx, desired); err != nil { diff --git a/pkg/controller/istiocsr/services.go b/pkg/controller/istiocsr/services.go index 24e8c6d68..3b494c388 100644 --- a/pkg/controller/istiocsr/services.go +++ b/pkg/controller/istiocsr/services.go @@ -4,6 +4,7 @@ import ( "fmt" corev1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/openshift/cert-manager-operator/api/operator/v1alpha1" @@ -33,7 +34,7 @@ func (r *Reconciler) createOrApplyServices(istiocsr *v1alpha1.IstioCSR, resource func (r *Reconciler) createOrApplyService(istiocsr *v1alpha1.IstioCSR, svc *corev1.Service, istioCSRCreateRecon bool) error { serviceName := fmt.Sprintf("%s/%s", svc.GetNamespace(), svc.GetName()) - r.log.V(4).Info("reconciling service resource", "name", serviceName) + klog.V(4).InfoS("reconciling service resource", "name", serviceName) fetched := &corev1.Service{} exist, err := r.Exists(r.ctx, client.ObjectKeyFromObject(svc), fetched) if err != nil { @@ -44,13 +45,13 @@ func (r *Reconciler) createOrApplyService(istiocsr *v1alpha1.IstioCSR, svc *core r.eventRecorder.Eventf(istiocsr, corev1.EventTypeWarning, "ResourceAlreadyExists", "%s service resource already exists, maybe from previous installation", serviceName) } if exist && hasObjectChanged(svc, fetched) { - r.log.V(1).Info("service has been modified, updating to desired state", "name", serviceName) + klog.V(1).InfoS("service has been modified, updating to desired state", "name", serviceName) if err := r.UpdateWithRetry(r.ctx, svc); err != nil { return FromClientError(err, "failed to update %s service resource", serviceName) } r.eventRecorder.Eventf(istiocsr, corev1.EventTypeNormal, "Reconciled", "service resource %s reconciled back to desired state", serviceName) } else { - r.log.V(4).Info("service resource already exists and is in expected state", "name", serviceName) + klog.V(4).InfoS("service resource already exists and is in expected state", "name", serviceName) } if !exist { if err := r.Create(r.ctx, svc); err != nil { diff --git a/pkg/controller/istiocsr/test_utils.go b/pkg/controller/istiocsr/test_utils.go index 7eb5457ae..ebe44a64c 100644 --- a/pkg/controller/istiocsr/test_utils.go +++ b/pkg/controller/istiocsr/test_utils.go @@ -18,8 +18,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" - "github.com/go-logr/logr/testr" - cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certmanagermetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" @@ -46,7 +44,6 @@ func testReconciler(t *testing.T) *Reconciler { return &Reconciler{ ctx: context.Background(), eventRecorder: record.NewFakeRecorder(100), - log: testr.New(t), scheme: testutil.Scheme, } } diff --git a/pkg/controller/istiocsr/utils.go b/pkg/controller/istiocsr/utils.go index 1dc388368..92d162920 100644 --- a/pkg/controller/istiocsr/utils.go +++ b/pkg/controller/istiocsr/utils.go @@ -15,6 +15,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/util/retry" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -50,7 +51,7 @@ func init() { func (r *Reconciler) updateStatus(ctx context.Context, changed *v1alpha1.IstioCSR) error { namespacedName := client.ObjectKeyFromObject(changed) if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - r.log.V(4).Info("updating istiocsr.openshift.operator.io status", "request", namespacedName) + klog.V(4).InfoS("updating istiocsr.openshift.operator.io status", "request", namespacedName) current := &v1alpha1.IstioCSR{} if err := r.Get(ctx, namespacedName, current); err != nil { return fmt.Errorf("failed to fetch istiocsr.openshift.operator.io %q for status update: %w", namespacedName, err) @@ -405,7 +406,7 @@ func (r *Reconciler) disallowMultipleIstioCSRInstances(istiocsr *v1alpha1.IstioC statusMessage := fmt.Sprintf("multiple instances of istiocsr exists, %s/%s will not be processed", istiocsr.GetNamespace(), istiocsr.GetName()) if containsProcessingRejectedAnnotation(istiocsr) { - r.log.V(4).Info("%s/%s istiocsr resource contains processing rejected annotation", istiocsr.Namespace, istiocsr.Name) + klog.V(4).InfoS("istiocsr resource contains processing rejected annotation", "namespace", istiocsr.Namespace, "name", istiocsr.Name) // ensure status is updated. var updateErr error if istiocsr.Status.SetCondition(v1alpha1.Ready, metav1.ConditionFalse, v1alpha1.ReasonFailed, statusMessage) { diff --git a/pkg/operator/setup_manager.go b/pkg/operator/setup_manager.go index e7c350b51..d3b732416 100644 --- a/pkg/operator/setup_manager.go +++ b/pkg/operator/setup_manager.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/klog/v2" + "k8s.io/klog/v2/klogr" ctrl "sigs.k8s.io/controller-runtime" ctrllog "sigs.k8s.io/controller-runtime/pkg/log" @@ -30,7 +30,8 @@ var ( ) func init() { - ctrllog.SetLogger(klog.NewKlogr()) + // Use klogr to provide a logr.Logger backed by klog/v2 for controller-runtime. + ctrllog.SetLogger(klogr.New()) utilruntime.Must(clientscheme.AddToScheme(scheme)) utilruntime.Must(appsv1.AddToScheme(scheme)) diff --git a/vendor/github.com/go-logr/logr/testr/testr.go b/vendor/github.com/go-logr/logr/testr/testr.go deleted file mode 100644 index 28168e0ae..000000000 --- a/vendor/github.com/go-logr/logr/testr/testr.go +++ /dev/null @@ -1,167 +0,0 @@ -/* -Copyright 2019 The logr Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package testr provides support for using logr in tests. -package testr - -import ( - "testing" - - "github.com/go-logr/logr" - "github.com/go-logr/logr/funcr" -) - -// New returns a logr.Logger that prints through a testing.T object. -// Info logs are only enabled at V(0). -func New(t *testing.T) logr.Logger { - return NewWithOptions(t, Options{}) -} - -// Options carries parameters which influence the way logs are generated. -type Options struct { - // LogTimestamp tells the logger to add a "ts" key to log - // lines. This has some overhead, so some users might not want - // it. - LogTimestamp bool - - // Verbosity tells the logger which V logs to be write. - // Higher values enable more logs. - Verbosity int -} - -// NewWithOptions returns a logr.Logger that prints through a testing.T object. -// In contrast to the simpler New, output formatting can be configured. -func NewWithOptions(t *testing.T, opts Options) logr.Logger { - l := &testlogger{ - testloggerInterface: newLoggerInterfaceWithOptions(t, opts), - } - return logr.New(l) -} - -// TestingT is an interface wrapper around testing.T, testing.B and testing.F. -type TestingT interface { - Helper() - Log(args ...any) -} - -// NewWithInterface returns a logr.Logger that prints through a -// TestingT object. -// In contrast to the simpler New, output formatting can be configured. -func NewWithInterface(t TestingT, opts Options) logr.Logger { - l := newLoggerInterfaceWithOptions(t, opts) - return logr.New(&l) -} - -func newLoggerInterfaceWithOptions(t TestingT, opts Options) testloggerInterface { - return testloggerInterface{ - t: t, - Formatter: funcr.NewFormatter(funcr.Options{ - LogTimestamp: opts.LogTimestamp, - Verbosity: opts.Verbosity, - }), - } -} - -// Underlier exposes access to the underlying testing.T instance. Since -// callers only have a logr.Logger, they have to know which -// implementation is in use, so this interface is less of an -// abstraction and more of a way to test type conversion. -type Underlier interface { - GetUnderlying() *testing.T -} - -// UnderlierInterface exposes access to the underlying TestingT instance. Since -// callers only have a logr.Logger, they have to know which -// implementation is in use, so this interface is less of an -// abstraction and more of a way to test type conversion. -type UnderlierInterface interface { - GetUnderlying() TestingT -} - -// Info logging implementation shared between testLogger and testLoggerInterface. -func logInfo(t TestingT, formatInfo func(int, string, []any) (string, string), level int, msg string, kvList ...any) { - prefix, args := formatInfo(level, msg, kvList) - t.Helper() - if prefix != "" { - args = prefix + ": " + args - } - t.Log(args) -} - -// Error logging implementation shared between testLogger and testLoggerInterface. -func logError(t TestingT, formatError func(error, string, []any) (string, string), err error, msg string, kvList ...any) { - prefix, args := formatError(err, msg, kvList) - t.Helper() - if prefix != "" { - args = prefix + ": " + args - } - t.Log(args) -} - -// This type exists to wrap and modify the method-set of testloggerInterface. -// In particular, it changes the GetUnderlying() method. -type testlogger struct { - testloggerInterface -} - -func (l testlogger) GetUnderlying() *testing.T { - // This method is defined on testlogger, so the only type this could - // possibly be is testing.T, even though that's not guaranteed by the type - // system itself. - return l.t.(*testing.T) //nolint:forcetypeassert -} - -type testloggerInterface struct { - funcr.Formatter - t TestingT -} - -func (l testloggerInterface) WithName(name string) logr.LogSink { - l.AddName(name) // via Formatter - return &l -} - -func (l testloggerInterface) WithValues(kvList ...any) logr.LogSink { - l.AddValues(kvList) // via Formatter - return &l -} - -func (l testloggerInterface) GetCallStackHelper() func() { - return l.t.Helper -} - -func (l testloggerInterface) Info(level int, msg string, kvList ...any) { - l.t.Helper() - logInfo(l.t, l.FormatInfo, level, msg, kvList...) -} - -func (l testloggerInterface) Error(err error, msg string, kvList ...any) { - l.t.Helper() - logError(l.t, l.FormatError, err, msg, kvList...) -} - -func (l testloggerInterface) GetUnderlying() TestingT { - return l.t -} - -// Assert conformance to the interfaces. -var _ logr.LogSink = &testlogger{} -var _ logr.CallStackHelperLogSink = &testlogger{} -var _ Underlier = &testlogger{} - -var _ logr.LogSink = &testloggerInterface{} -var _ logr.CallStackHelperLogSink = &testloggerInterface{} -var _ UnderlierInterface = &testloggerInterface{} diff --git a/vendor/k8s.io/klog/v2/klogr/README.md b/vendor/k8s.io/klog/v2/klogr/README.md new file mode 100644 index 000000000..c43fa81b1 --- /dev/null +++ b/vendor/k8s.io/klog/v2/klogr/README.md @@ -0,0 +1,19 @@ +# Minimal Go logging using klog + +This package implements the [logr interface](https://github.com/go-logr/logr) +in terms of Kubernetes' [klog](https://github.com/kubernetes/klog). This +provides a relatively minimalist API to logging in Go, backed by a well-proven +implementation. + +Because klogr was implemented before klog itself added supported for +structured logging, the default in klogr is to serialize key/value +pairs with JSON and log the result as text messages via klog. This +does not work well when klog itself forwards output to a structured +logger. + +Therefore the recommended approach is to let klogr pass all log +messages through to klog and deal with structured logging there. Just +beware that the output of klog without a structured logger is meant to +be human-readable, in contrast to the JSON-based traditional format. + +This is a BETA grade implementation. diff --git a/vendor/k8s.io/klog/v2/klogr/klogr.go b/vendor/k8s.io/klog/v2/klogr/klogr.go new file mode 100644 index 000000000..a154960cd --- /dev/null +++ b/vendor/k8s.io/klog/v2/klogr/klogr.go @@ -0,0 +1,208 @@ +// Package klogr implements github.com/go-logr/logr.Logger in terms of +// k8s.io/klog. +package klogr + +import ( + "bytes" + "encoding/json" + "fmt" + "sort" + "strings" + + "github.com/go-logr/logr" + + "k8s.io/klog/v2" + "k8s.io/klog/v2/internal/serialize" +) + +const ( + // nameKey is used to log the `WithName` values as an additional attribute. + nameKey = "logger" +) + +// Option is a functional option that reconfigures the logger created with New. +type Option func(*klogger) + +// Format defines how log output is produced. +type Format string + +const ( + // FormatSerialize tells klogr to turn key/value pairs into text itself + // before invoking klog. Key/value pairs are sorted by key. + FormatSerialize Format = "Serialize" + + // FormatKlog tells klogr to pass all text messages and key/value pairs + // directly to klog. Klog itself then serializes in a human-readable + // format and optionally passes on to a structure logging backend. + FormatKlog Format = "Klog" +) + +// WithFormat selects the output format. +func WithFormat(format Format) Option { + return func(l *klogger) { + l.format = format + } +} + +// New returns a logr.Logger which serializes output itself +// and writes it via klog. +// +// Deprecated: this uses a custom, out-dated output format. Use textlogger.NewLogger instead. +func New() logr.Logger { + return NewWithOptions(WithFormat(FormatSerialize)) +} + +// NewWithOptions returns a logr.Logger which serializes as determined +// by the WithFormat option and writes via klog. The default is +// FormatKlog. +// +// Deprecated: FormatSerialize is out-dated. For FormatKlog, use textlogger.NewLogger instead. +func NewWithOptions(options ...Option) logr.Logger { + l := klogger{ + level: 0, + values: nil, + format: FormatKlog, + } + for _, option := range options { + option(&l) + } + return logr.New(&l) +} + +type klogger struct { + level int + callDepth int + + // hasPrefix is true if the first entry in values is the special + // nameKey key/value. Such an entry gets added and later updated in + // WithName. + hasPrefix bool + + values []interface{} + format Format +} + +func (l *klogger) Init(info logr.RuntimeInfo) { + l.callDepth += info.CallDepth +} + +func flatten(kvList ...interface{}) string { + keys := make([]string, 0, len(kvList)) + vals := make(map[string]interface{}, len(kvList)) + for i := 0; i < len(kvList); i += 2 { + k, ok := kvList[i].(string) + if !ok { + panic(fmt.Sprintf("key is not a string: %s", pretty(kvList[i]))) + } + var v interface{} + if i+1 < len(kvList) { + v = kvList[i+1] + } + // Only print each key once... + if _, seen := vals[k]; !seen { + keys = append(keys, k) + } + // ... with the latest value. + vals[k] = v + } + sort.Strings(keys) + buf := bytes.Buffer{} + for i, k := range keys { + v := vals[k] + if i > 0 { + buf.WriteRune(' ') + } + buf.WriteString(pretty(k)) + buf.WriteString("=") + buf.WriteString(pretty(v)) + } + return buf.String() +} + +func pretty(value interface{}) string { + if err, ok := value.(error); ok { + if _, ok := value.(json.Marshaler); !ok { + value = err.Error() + } + } + buffer := &bytes.Buffer{} + encoder := json.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + if err := encoder.Encode(value); err != nil { + return fmt.Sprintf("<>", err) + } + return strings.TrimSpace(buffer.String()) +} + +func (l *klogger) Info(level int, msg string, kvList ...interface{}) { + switch l.format { + case FormatSerialize: + msgStr := flatten("msg", msg) + merged := serialize.MergeKVs(l.values, kvList) + kvStr := flatten(merged...) + klog.VDepth(l.callDepth+1, klog.Level(level)).InfoDepth(l.callDepth+1, msgStr, " ", kvStr) + case FormatKlog: + merged := serialize.MergeKVs(l.values, kvList) + klog.VDepth(l.callDepth+1, klog.Level(level)).InfoSDepth(l.callDepth+1, msg, merged...) + } +} + +func (l *klogger) Enabled(level int) bool { + return klog.VDepth(l.callDepth+1, klog.Level(level)).Enabled() +} + +func (l *klogger) Error(err error, msg string, kvList ...interface{}) { + msgStr := flatten("msg", msg) + var loggableErr interface{} + if err != nil { + loggableErr = serialize.ErrorToString(err) + } + switch l.format { + case FormatSerialize: + errStr := flatten("error", loggableErr) + merged := serialize.MergeKVs(l.values, kvList) + kvStr := flatten(merged...) + klog.ErrorDepth(l.callDepth+1, msgStr, " ", errStr, " ", kvStr) + case FormatKlog: + merged := serialize.MergeKVs(l.values, kvList) + klog.ErrorSDepth(l.callDepth+1, err, msg, merged...) + } +} + +// WithName returns a new logr.Logger with the specified name appended. klogr +// uses '.' characters to separate name elements. Callers should not pass '.' +// in the provided name string, but this library does not actually enforce that. +func (l klogger) WithName(name string) logr.LogSink { + if l.hasPrefix { + // Copy slice and modify value. No length checks and type + // assertions are needed because hasPrefix is only true if the + // first two elements exist and are key/value strings. + v := make([]interface{}, 0, len(l.values)) + v = append(v, l.values...) + prefix, _ := v[1].(string) + prefix = prefix + "." + name + v[1] = prefix + l.values = v + } else { + // Preprend new key/value pair. + v := make([]interface{}, 0, 2+len(l.values)) + v = append(v, nameKey, name) + v = append(v, l.values...) + l.values = v + l.hasPrefix = true + } + return &l +} + +func (l klogger) WithValues(kvList ...interface{}) logr.LogSink { + l.values = serialize.WithValues(l.values, kvList) + return &l +} + +func (l klogger) WithCallDepth(depth int) logr.LogSink { + l.callDepth += depth + return &l +} + +var _ logr.LogSink = &klogger{} +var _ logr.CallDepthLogSink = &klogger{} diff --git a/vendor/modules.txt b/vendor/modules.txt index 3be07dd6b..aaa7d05d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -406,7 +406,6 @@ github.com/go-errors/errors github.com/go-logr/logr github.com/go-logr/logr/funcr github.com/go-logr/logr/slogr -github.com/go-logr/logr/testr # github.com/go-logr/stdr v1.2.2 ## explicit; go 1.16 github.com/go-logr/stdr @@ -2948,6 +2947,7 @@ k8s.io/klog/v2/internal/serialize k8s.io/klog/v2/internal/severity k8s.io/klog/v2/internal/sloghandler k8s.io/klog/v2/internal/verbosity +k8s.io/klog/v2/klogr k8s.io/klog/v2/textlogger # k8s.io/kms v0.34.1 ## explicit; go 1.24.0