diff --git a/Makefile b/Makefile index b5296ffe..d02dabb2 100644 --- a/Makefile +++ b/Makefile @@ -27,12 +27,17 @@ LD_FLAGS := "-w $(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/vend # Rules for local development scenarios # ######################################### +ZAP_DEVEL := true +ZAP_LOG_LEVEL := debug + .PHONY: start start: @GO111MODULE=on go run \ -mod=vendor \ -ldflags $(LD_FLAGS) \ ./cmd/gardener-resource-manager \ + --zap-devel=$(ZAP_DEVEL) \ + --zap-log-level=$(ZAP_LOG_LEVEL) \ --leader-election=false \ --sync-period=60s \ --max-concurrent-workers=10 \ diff --git a/cmd/gardener-resource-manager/app/app.go b/cmd/gardener-resource-manager/app/app.go index 36295cd5..e1dc8f1e 100644 --- a/cmd/gardener-resource-manager/app/app.go +++ b/cmd/gardener-resource-manager/app/app.go @@ -16,12 +16,17 @@ package app import ( "context" + "flag" "fmt" "sync" + "github.com/go-logr/logr" "github.com/spf13/cobra" "github.com/spf13/pflag" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" runtimelog "sigs.k8s.io/controller-runtime/pkg/log" + logzap "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" resourcemanagercmd "github.com/gardener/gardener-resource-manager/pkg/cmd" @@ -29,38 +34,61 @@ import ( resourcecontroller "github.com/gardener/gardener-resource-manager/pkg/controller/managedresource" secretcontroller "github.com/gardener/gardener-resource-manager/pkg/controller/secret" "github.com/gardener/gardener-resource-manager/pkg/healthz" - logpkg "github.com/gardener/gardener-resource-manager/pkg/log" "github.com/gardener/gardener-resource-manager/pkg/version" ) -var log = runtimelog.Log.WithName("gardener-resource-manager") - // NewResourceManagerCommand creates a new command for running a gardener resource manager controllers. func NewResourceManagerCommand() *cobra.Command { - runtimelog.SetLogger(logpkg.ZapLogger(false)) - entryLog := log.WithName("entrypoint") + var ( + zapOpts = &logzap.Options{} + + managerOpts = &resourcemanagercmd.ManagerOptions{} + sourceClientOpts = &resourcemanagercmd.SourceClientOptions{} + targetClientOpts = &resourcemanagercmd.TargetClientOptions{} - managerOpts := &resourcemanagercmd.ManagerOptions{} - sourceClientOpts := &resourcemanagercmd.SourceClientOptions{} - targetClientOpts := &resourcemanagercmd.TargetClientOptions{} + resourceControllerOpts = &resourcecontroller.ControllerOptions{} + secretControllerOpts = &secretcontroller.ControllerOptions{} + healthControllerOpts = &healthcontroller.ControllerOptions{} - resourceControllerOpts := &resourcecontroller.ControllerOptions{} - secretControllerOpts := &secretcontroller.ControllerOptions{} - healthControllerOpts := &healthcontroller.ControllerOptions{} + log logr.Logger + ) cmd := &cobra.Command{ Use: "gardener-resource-manager", Version: version.Get().GitVersion, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + runtimelog.SetLogger(logzap.New( + // use configuration passed via flags + logzap.UseFlagOptions(zapOpts), + // and overwrite some stuff + func(o *logzap.Options) { + if !o.Development { + encCfg := zap.NewProductionEncoderConfig() + // overwrite time encoding to human readable format for production logs + encCfg.EncodeTime = zapcore.ISO8601TimeEncoder + o.Encoder = zapcore.NewJSONEncoder(encCfg) + } + + // don't print stacktrace for warning level logs + o.StacktraceLevel = zapcore.ErrorLevel + }, + )) + + log = runtimelog.Log + log.Info("Starting gardener-resource-manager...", "version", version.Get().GitVersion) + cmd.Flags().VisitAll(func(flag *pflag.Flag) { + log.Info(fmt.Sprintf("FLAG: --%s=%s", flag.Name, flag.Value)) + }) + + cmd.SilenceUsage = true + cmd.SilenceErrors = true + }, + RunE: func(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() - entryLog.Info("Starting gardener-resource-manager...", "version", version.Get().GitVersion) - cmd.Flags().VisitAll(func(flag *pflag.Flag) { - entryLog.Info(fmt.Sprintf("FLAG: --%s=%s", flag.Name, flag.Value)) - }) - if err := resourcemanagercmd.CompleteAll( managerOpts, sourceClientOpts, @@ -133,7 +161,7 @@ func NewResourceManagerCommand() *cobra.Command { return err case <-cmd.Context().Done(): - entryLog.Info("Stop signal received, shutting down.") + log.Info("Stop signal received, shutting down.") wg.Wait() return nil } @@ -150,5 +178,8 @@ func NewResourceManagerCommand() *cobra.Command { healthControllerOpts, ) + zapOpts.BindFlags(flag.CommandLine) + cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine) + return cmd } diff --git a/cmd/gardener-resource-manager/main.go b/cmd/gardener-resource-manager/main.go index fc1446ad..b5b4e77d 100644 --- a/cmd/gardener-resource-manager/main.go +++ b/cmd/gardener-resource-manager/main.go @@ -16,28 +16,28 @@ package main import ( "context" + "fmt" "os" - "github.com/gardener/gardener-resource-manager/cmd/gardener-resource-manager/app" - "github.com/gardener/gardener-resource-manager/pkg/log" - runtimelog "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager/signals" + + "github.com/gardener/gardener-resource-manager/cmd/gardener-resource-manager/app" ) func main() { - runtimelog.SetLogger(log.ZapLogger(false)) - ctx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() <-signals.SetupSignalHandler() }() - cmd := app.NewResourceManagerCommand() - - if err := cmd.ExecuteContext(ctx); err != nil { - runtimelog.Log.Error(err, "error executing the main controller command") + if err := app.NewResourceManagerCommand().ExecuteContext(ctx); err != nil { + if log := runtimelog.Log; log.Enabled() { + log.Error(err, "error running gardener-resource-manager") + } else { + fmt.Printf("error running gardener-resource-manager: %v", err) + } os.Exit(1) } } diff --git a/pkg/controller/health/reconciler.go b/pkg/controller/health/reconciler.go index 66c01e4b..9bf14aa8 100644 --- a/pkg/controller/health/reconciler.go +++ b/pkg/controller/health/reconciler.go @@ -66,7 +66,7 @@ func (r *Reconciler) InjectLogger(l logr.Logger) error { // Reconcile performs health checks. func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - log := r.log.WithValues("object", req) + log := r.log.WithValues("managedresource", req) log.Info("Starting ManagedResource health checks") mr := &resourcesv1alpha1.ManagedResource{} @@ -116,8 +116,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { // objects, so we create a new object of the object's type to use the caching client obj, err := r.targetScheme.New(ref.GroupVersionKind()) if err != nil { - log.Info("could not create new object of kind for health checks (probably not registered in the used scheme), falling back to unstructured request", - "GroupVersionKind", ref.GroupVersionKind().String(), "error", err.Error()) + log.V(1).Info("could not create new object of kind for health checks (probably not registered in the used scheme), falling back to unstructured request", + "GroupVersionKind", ref.GroupVersionKind().String(), "err", err.Error()) // fallback to unstructured requests if the object's type is not registered in the scheme unstructuredObj := &unstructured.Unstructured{} @@ -126,9 +126,10 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { obj = unstructuredObj } + resourceLog := log.WithValues("resource", utils.ObjectReferceLogWrapper{ObjectReference: ref.ObjectReference}) if err := r.targetClient.Get(r.ctx, client.ObjectKey{Namespace: ref.Namespace, Name: ref.Name}, obj); err != nil { if apierrors.IsNotFound(err) { - log.Info("Could not get object", "namespace", ref.Namespace, "name", ref.Name) + resourceLog.Info("Health check failed: resource is missing") var ( reason = ref.Kind + "Missing" @@ -147,6 +148,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } if err := CheckHealth(r.targetScheme, obj); err != nil { + resourceLog.Info("Health check failed: resource is unhealthy") + var ( reason = ref.Kind + "Unhealthy" message = fmt.Sprintf("Required %s %q in namespace %q is unhealthy: %v", ref.Kind, ref.Name, ref.Namespace, err.Error()) diff --git a/pkg/controller/managedresource/reconciler.go b/pkg/controller/managedresource/reconciler.go index cc50346a..65589f30 100644 --- a/pkg/controller/managedresource/reconciler.go +++ b/pkg/controller/managedresource/reconciler.go @@ -24,11 +24,6 @@ import ( "sync" "time" - resourcesv1alpha1 "github.com/gardener/gardener-resource-manager/api/resources/v1alpha1" - resourcesv1alpha1helper "github.com/gardener/gardener-resource-manager/api/resources/v1alpha1/helper" - "github.com/gardener/gardener-resource-manager/pkg/controller/utils" - "github.com/gardener/gardener-resource-manager/pkg/filter" - hvpav1alpha1 "github.com/gardener/hvpa-controller/api/v1alpha1" "github.com/go-logr/logr" "github.com/hashicorp/go-multierror" @@ -51,6 +46,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/reconcile" + + resourcesv1alpha1 "github.com/gardener/gardener-resource-manager/api/resources/v1alpha1" + resourcesv1alpha1helper "github.com/gardener/gardener-resource-manager/api/resources/v1alpha1/helper" + "github.com/gardener/gardener-resource-manager/pkg/controller/utils" + "github.com/gardener/gardener-resource-manager/pkg/filter" ) var ( @@ -93,7 +93,7 @@ func (r *Reconciler) InjectLogger(l logr.Logger) error { // Reconcile implements `reconcile.Reconciler`. func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - log := r.log.WithValues("object", req) + log := r.log.WithValues("managedresource", req) mr := &resourcesv1alpha1.ManagedResource{} if err := r.client.Get(r.ctx, req.NamespacedName, mr); err != nil { @@ -105,7 +105,7 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } action, responsible := r.class.Active(mr) - log.Info(fmt.Sprintf("reconcile: action required: %t, responsible: %t", action, responsible)) + log.V(1).Info("reconcile request received", "action_required", action, "responsible", responsible) // If the object should be deleted or the responsibility changed // the actual deployments have to be deleted @@ -139,7 +139,9 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L forceOverwriteLabels bool forceOverwriteAnnotations bool - decodingErrors []*decodingError + decodingErrors = &multierror.Error{ + ErrorFormat: utils.NewErrorFormatFuncWithPrefix("Could not decode all resources"), + } ) if v := mr.Spec.ForceOverwriteLabels; v != nil { @@ -175,14 +177,9 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L break } if err != nil { - decodingError := &decodingError{ - err: err, - secret: fmt.Sprintf("%s/%s", secret.Namespace, secret.Name), - secretKey: key, - objectIndexInFile: i, - } - decodingErrors = append(decodingErrors, decodingError) - log.Error(decodingError.err, decodingError.StringShort()) + msg := fmt.Sprintf("resource at index %d in key %q in secret %q", i, key, keyFromObject(secret)) + decodingErrors = multierror.Append(decodingErrors, fmt.Errorf("%s: %w", msg, err)) + log.Error(err, "error decoding resource", "secret", keyFromObject(secret), "secretKey", key, "indexInFile", i) continue } @@ -197,8 +194,7 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L if err != nil || mapping == nil { // Cache miss most probably indicates, that the corresponding CRD is not yet applied. // CRD might be applied later as part of the ManagedResource reconciliation - log.Info(fmt.Sprintf("could not get rest mapping for %s '%s/%s': %v", obj.GetKind(), obj.GetNamespace(), obj.GetName(), err), - "secret", fmt.Sprintf("%s/%s", secret.Namespace, secret.Name), "secretKey", key, "objectIndexInFile", i) + log.Info("could not get rest mapping for object", "resource", obj, "err", err, "secret", keyFromObject(secret), "secretKey", key, "indexInFile", i) // default namespace on a best effort basis if obj.GetKind() != "Namespace" && obj.GetNamespace() == "" { @@ -216,29 +212,27 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L } } - var ( - newObj = object{ - obj: obj, - forceOverwriteLabels: forceOverwriteLabels, - forceOverwriteAnnotations: forceOverwriteAnnotations, - } - objectReference = resourcesv1alpha1.ObjectReference{ - ObjectReference: corev1.ObjectReference{ - APIVersion: newObj.obj.GetAPIVersion(), - Kind: newObj.obj.GetKind(), - Name: newObj.obj.GetName(), - Namespace: newObj.obj.GetNamespace(), - }, - Labels: mergeMaps(newObj.obj.GetLabels(), mr.Spec.InjectLabels), - Annotations: newObj.obj.GetAnnotations(), - } - ) + newObj := object{ + obj: obj, + forceOverwriteLabels: forceOverwriteLabels, + forceOverwriteAnnotations: forceOverwriteAnnotations, + } + newObj.ref = resourcesv1alpha1.ObjectReference{ + ObjectReference: corev1.ObjectReference{ + APIVersion: newObj.obj.GetAPIVersion(), + Kind: newObj.obj.GetKind(), + Name: newObj.obj.GetName(), + Namespace: newObj.obj.GetNamespace(), + }, + Labels: mergeMaps(newObj.obj.GetLabels(), mr.Spec.InjectLabels), + Annotations: newObj.obj.GetAnnotations(), + } - newObj.oldInformation, _ = existingResourcesIndex.Lookup(objectReference) + newObj.oldInformation, _ = existingResourcesIndex.Lookup(newObj.ref) decodedObj = nil newResourcesObjects = append(newResourcesObjects, newObj) - newResourcesObjectReferences = append(newResourcesObjectReferences, objectReference) + newResourcesObjectReferences = append(newResourcesObjectReferences, newObj.ref) } } } @@ -268,7 +262,7 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L } } - if deletionPending, err := r.cleanOldResources(existingResourcesIndex, mr); err != nil { + if deletionPending, err := r.cleanOldResources(log, existingResourcesIndex, mr); err != nil { var ( reason string status resourcesv1alpha1.ConditionStatus @@ -295,7 +289,7 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L } } - if err := r.applyNewResources(newResourcesObjects, mr.Spec.InjectLabels, equivalences); err != nil { + if err := r.applyNewResources(log, newResourcesObjects, mr.Spec.InjectLabels, equivalences); err != nil { conditionResourcesApplied = resourcesv1alpha1helper.UpdatedCondition(conditionResourcesApplied, resourcesv1alpha1.ConditionFalse, resourcesv1alpha1.ConditionApplyFailed, err.Error()) if err := tryUpdateManagedResourceConditions(r.ctx, r.client, mr, conditionResourcesApplied); err != nil { return ctrl.Result{}, fmt.Errorf("could not update the ManagedResource status: %+v", err) @@ -304,8 +298,8 @@ func (r *Reconciler) reconcile(mr *resourcesv1alpha1.ManagedResource, log logr.L return ctrl.Result{}, fmt.Errorf("could not apply all new resources: %+v", err) } - if len(decodingErrors) != 0 { - conditionResourcesApplied = resourcesv1alpha1helper.UpdatedCondition(conditionResourcesApplied, resourcesv1alpha1.ConditionFalse, resourcesv1alpha1.ConditionDecodingFailed, fmt.Sprintf("Could not decode all new resources: %v", decodingErrors)) + if decodingErrors.Len() > 0 { + conditionResourcesApplied = resourcesv1alpha1helper.UpdatedCondition(conditionResourcesApplied, resourcesv1alpha1.ConditionFalse, resourcesv1alpha1.ConditionDecodingFailed, decodingErrors.Error()) } else { conditionResourcesApplied = resourcesv1alpha1helper.UpdatedCondition(conditionResourcesApplied, resourcesv1alpha1.ConditionTrue, resourcesv1alpha1.ConditionApplySucceeded, "All resources are applied.") } @@ -337,7 +331,7 @@ func (r *Reconciler) delete(mr *resourcesv1alpha1.ManagedResource, log logr.Logg return ctrl.Result{}, fmt.Errorf("could not update the ManagedResource status: %+v", err) } - if deletionPending, err := r.cleanOldResources(existingResourcesIndex, mr); err != nil { + if deletionPending, err := r.cleanOldResources(log, existingResourcesIndex, mr); err != nil { var ( reason string status resourcesv1alpha1.ConditionStatus @@ -364,7 +358,7 @@ func (r *Reconciler) delete(mr *resourcesv1alpha1.ManagedResource, log logr.Logg } } } else { - log.Info(fmt.Sprintf("Do not delete any resources of %s because .spec.keepObjects=true", mr.Name)) + log.Info("Not deleting any resources of because .spec.keepObjects=true") } log.Info("All resources have been deleted, removing finalizers from ManagedResource") @@ -377,7 +371,7 @@ func (r *Reconciler) delete(mr *resourcesv1alpha1.ManagedResource, log logr.Logg return ctrl.Result{}, nil } -func (r *Reconciler) applyNewResources(newResourcesObjects []object, labelsToInject map[string]string, equivalences Equivalences) error { +func (r *Reconciler) applyNewResources(logger logr.Logger, newResourcesObjects []object, labelsToInject map[string]string, equivalences Equivalences) error { var ( results = make(chan error) wg sync.WaitGroup @@ -407,7 +401,8 @@ func (r *Reconciler) applyNewResources(newResourcesObjects []object, labelsToInj scaledVertically = isScaled(obj.obj, verticallyScaledObjects, equivalences) ) - r.log.Info("Applying", "resource", resource) + log := logger.WithValues("resource", utils.ObjectReferceLogWrapper{ObjectReference: obj.ref.ObjectReference}) + log.V(1).Info("Applying resource") results <- retry.RetryOnConflict(retry.DefaultBackoff, func() error { if operationResult, err := utils.TypedCreateOrUpdate(r.ctx, r.targetClient, r.targetScheme, current, r.alwaysUpdate, func() error { @@ -431,7 +426,7 @@ func (r *Reconciler) applyNewResources(newResourcesObjects []object, labelsToInj return merge(obj.obj, current, obj.forceOverwriteLabels, obj.oldInformation.Labels, obj.forceOverwriteAnnotations, obj.oldInformation.Annotations, scaledHorizontally, scaledVertically) }); err != nil { if apierrors.IsConflict(err) { - r.log.Info(fmt.Sprintf("conflict during apply of object %q: %s", resource, err)) + log.V(1).Info("conflict while applying resource", "err", err) // return conflict error directly, so that the update will be retried return err } @@ -575,7 +570,7 @@ func annotationExistsAndValueTrue(meta metav1.Object, key string) bool { return annotationExists && valueTrue } -func (r *Reconciler) cleanOldResources(index *ObjectIndex, mr *resourcesv1alpha1.ManagedResource) (bool, error) { +func (r *Reconciler) cleanOldResources(logger logr.Logger, index *ObjectIndex, mr *resourcesv1alpha1.ManagedResource) (bool, error) { type output struct { resource string deletionPending bool @@ -605,12 +600,14 @@ func (r *Reconciler) cleanOldResources(index *ObjectIndex, mr *resourcesv1alpha1 obj.SetName(ref.Name) resource := unstructuredToString(obj) - r.log.Info("Deleting", "resource", resource) + + log := logger.WithValues("resource", utils.ObjectReferceLogWrapper{ObjectReference: ref.ObjectReference}) + log.V(1).Info("Deleting resource") // get object before deleting to be able to do cleanup work for it if err := r.targetClient.Get(r.ctx, client.ObjectKey{Namespace: ref.Namespace, Name: ref.Name}, obj); err != nil { if !apierrors.IsNotFound(err) && !meta.IsNoMatchError(err) { - r.log.Error(err, "Error during deletion", "resource", resource) + log.Error(err, "Error during deletion") results <- &output{resource, true, err} return } @@ -621,13 +618,13 @@ func (r *Reconciler) cleanOldResources(index *ObjectIndex, mr *resourcesv1alpha1 } if keepObject(obj) { - r.log.Info("Keeping object in the system as "+resourcesv1alpha1.KeepObject+" annotation found", "resource", unstructuredToString(obj)) + log.Info("Keeping object in the system as " + resourcesv1alpha1.KeepObject + " annotation found") results <- &output{resource, false, nil} return } if err := cleanup(r.ctx, r.targetClient, r.targetScheme, obj, deletePVCs); err != nil { - r.log.Error(err, "Error during cleanup", "resource", resource) + log.Error(err, "Error during cleanup") results <- &output{resource: resource, deletionPending: true, err: err} return } @@ -646,7 +643,7 @@ func (r *Reconciler) cleanOldResources(index *ObjectIndex, mr *resourcesv1alpha1 if err := r.targetClient.Delete(r.ctx, obj, deleteOptions); err != nil { if !apierrors.IsNotFound(err) && !meta.IsNoMatchError(err) { - r.log.Error(err, "Error during deletion", "resource", resource) + log.Error(err, "Error during deletion") results <- &output{resource, true, err} return } @@ -704,6 +701,10 @@ func tryUpdateManagedResourceConditions(ctx context.Context, c client.Client, mr }) } +func keyFromObject(o metav1.Object) client.ObjectKey { + return client.ObjectKey{Namespace: o.GetNamespace(), Name: o.GetName()} +} + func unstructuredToString(o *unstructured.Unstructured) string { // return no key, but an description including the version return objectKey(o.GetAPIVersion(), o.GetKind(), o.GetNamespace(), o.GetName()) @@ -806,22 +807,8 @@ func mergeMaps(one, two map[string]string) map[string]string { type object struct { obj *unstructured.Unstructured + ref resourcesv1alpha1.ObjectReference oldInformation resourcesv1alpha1.ObjectReference forceOverwriteLabels bool forceOverwriteAnnotations bool } - -type decodingError struct { - err error - secret string - secretKey string - objectIndexInFile int -} - -func (d *decodingError) StringShort() string { - return fmt.Sprintf("Could not decode resource at index %d in '%s' in secret '%s'", d.objectIndexInFile, d.secretKey, d.secret) -} - -func (d *decodingError) String() string { - return fmt.Sprintf("%s: %s.", d.StringShort(), d.err) -} diff --git a/pkg/controller/utils/log.go b/pkg/controller/utils/log.go new file mode 100644 index 00000000..d19ed3d4 --- /dev/null +++ b/pkg/controller/utils/log.go @@ -0,0 +1,43 @@ +// Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// 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 utils + +import ( + "go.uber.org/zap/zapcore" + corev1 "k8s.io/api/core/v1" +) + +var _ zapcore.ObjectMarshaler = ObjectReferceLogWrapper{} + +// ObjectReferceLogWrapper implements zapcore.ObjectMarshaler which can be used to add a brief description of an +// ObjectReference as a log field. +// Workaround for https://github.com/kubernetes-sigs/controller-runtime/issues/1290 +type ObjectReferceLogWrapper struct { + corev1.ObjectReference +} + +// MarshalLogObject marshals the object reference as a log field. +func (o ObjectReferceLogWrapper) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddString("apiVersion", o.APIVersion) + enc.AddString("kind", o.Kind) + + ns := o.Namespace + if ns != "" { + enc.AddString("namespace", ns) + } + enc.AddString("name", o.Name) + + return nil +} diff --git a/pkg/log/log.go b/pkg/log/log.go deleted file mode 100644 index 6913610b..00000000 --- a/pkg/log/log.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file -// -// 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 log - -import ( - "github.com/go-logr/logr" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - logzap "sigs.k8s.io/controller-runtime/pkg/log/zap" -) - -// ZapLogger is a Logger implementation. -// If development is true, a Zap development config will be used -// (stacktraces on warnings, no sampling), otherwise a Zap production -// config will be used (stacktraces on errors, sampling). -// Additionally, the time encoding is adjusted to `zapcore.ISO8601TimeEncoder`. -func ZapLogger(development bool) logr.Logger { - return logzap.New(func(o *logzap.Options) { - var encCfg zapcore.EncoderConfig - if development { - encCfg = zap.NewDevelopmentEncoderConfig() - } else { - encCfg = zap.NewProductionEncoderConfig() - } - encCfg.EncodeTime = zapcore.ISO8601TimeEncoder - - o.Encoder = zapcore.NewJSONEncoder(encCfg) - o.Development = development - }) -}