Skip to content

Commit

Permalink
Switch controller-manager to logr (4) (gardener#5488)
Browse files Browse the repository at this point in the history
* Switch project controller to logr

* Switch project stale controller to logr

* Switch project activity controller to logr

* Switch quota controller to logr

* Switch secretbinding controller to logr

* Switch seed controller to logr

* Switch seed secrets reconciler to logr

* Switch seed lifecycle reconciler to logr

* Switch seed backupbucket reconciler to logr
  • Loading branch information
timebertt authored and Kristiyan Gostev committed Apr 21, 2022
1 parent caa015a commit 9fffad8
Show file tree
Hide file tree
Showing 24 changed files with 335 additions and 342 deletions.
8 changes: 4 additions & 4 deletions pkg/controllermanager/controller/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,22 @@ func (f *GardenControllerFactory) Run(ctx context.Context) error {
return fmt.Errorf("failed initializing Plant controller: %w", err)
}

projectController, err := projectcontroller.NewProjectController(ctx, f.clientMap, f.cfg, f.recorder)
projectController, err := projectcontroller.NewProjectController(ctx, log, f.clientMap, f.cfg, f.recorder)
if err != nil {
return fmt.Errorf("failed initializing Project controller: %w", err)
}

quotaController, err := quotacontroller.NewQuotaController(ctx, f.clientMap, f.recorder)
quotaController, err := quotacontroller.NewQuotaController(ctx, log, f.clientMap, f.recorder)
if err != nil {
return fmt.Errorf("failed initializing Quota controller: %w", err)
}

secretBindingController, err := secretbindingcontroller.NewSecretBindingController(ctx, f.clientMap, f.recorder)
secretBindingController, err := secretbindingcontroller.NewSecretBindingController(ctx, log, f.clientMap, f.recorder)
if err != nil {
return fmt.Errorf("failed initializing SecretBinding controller: %w", err)
}

seedController, err := seedcontroller.NewSeedController(ctx, f.clientMap, f.cfg)
seedController, err := seedcontroller.NewSeedController(ctx, log, f.clientMap, f.cfg)
if err != nil {
return fmt.Errorf("failed initializing Seed controller: %w", err)
}
Expand Down
35 changes: 22 additions & 13 deletions pkg/controllermanager/controller/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import (
"sync"
"time"

"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/util/wait"

gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/client/kubernetes/clientmap"
"github.com/gardener/gardener/pkg/client/kubernetes/clientmap/keys"
"github.com/gardener/gardener/pkg/controllermanager/apis/config"
"github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/logger"

rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/client-go/tools/cache"
Expand All @@ -35,9 +37,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

// ControllerName is the name of this controller.
const ControllerName = "project"

// Controller controls Projects.
type Controller struct {
gardenClient client.Client
log logr.Logger

projectReconciler reconcile.Reconciler
projectStaleReconciler reconcile.Reconciler
Expand All @@ -56,13 +62,16 @@ type Controller struct {
// event recording. It creates a new Gardener controller.
func NewProjectController(
ctx context.Context,
log logr.Logger,
clientMap clientmap.ClientMap,
config *config.ControllerManagerConfiguration,
recorder record.EventRecorder,
) (
*Controller,
error,
) {
log = log.WithName(ControllerName)

gardenClient, err := clientMap.GetClient(ctx, keys.ForGarden())
if err != nil {
return nil, err
Expand All @@ -83,9 +92,10 @@ func NewProjectController(

projectController := &Controller{
gardenClient: gardenClient.Client(),
projectReconciler: NewProjectReconciler(logger.Logger, config.Controllers.Project, gardenClient, recorder),
projectStaleReconciler: NewProjectStaleReconciler(logger.Logger, config.Controllers.Project, gardenClient.Client()),
projectShootActivityReconciler: NewActivityReconciler(logger.Logger, gardenClient.Client()),
log: log,
projectReconciler: NewProjectReconciler(config.Controllers.Project, gardenClient, recorder),
projectStaleReconciler: NewProjectStaleReconciler(config.Controllers.Project, gardenClient.Client()),
projectShootActivityReconciler: NewActivityReconciler(gardenClient.Client()),
projectQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Project"),
projectStaleQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Project Stale"),
projectShootActivityQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Project Activity"),
Expand Down Expand Up @@ -121,24 +131,23 @@ func (c *Controller) Run(ctx context.Context, workers int) {
var waitGroup sync.WaitGroup

if !cache.WaitForCacheSync(ctx.Done(), c.hasSyncedFuncs...) {
logger.Logger.Error("Timed out waiting for caches to sync")
c.log.Error(wait.ErrWaitTimeout, "Timed out waiting for caches to sync")
return
}

// Count number of running workers.
go func() {
for res := range c.workerCh {
c.numberOfRunningWorkers += res
logger.Logger.Debugf("Current number of running Project workers is %d", c.numberOfRunningWorkers)
}
}()

logger.Logger.Info("Project controller initialized.")
c.log.Info("Project controller initialized")

for i := 0; i < workers; i++ {
controllerutils.CreateWorker(ctx, c.projectQueue, "Project", c.projectReconciler, &waitGroup, c.workerCh)
controllerutils.CreateWorker(ctx, c.projectStaleQueue, "Project Stale", c.projectStaleReconciler, &waitGroup, c.workerCh)
controllerutils.CreateWorker(ctx, c.projectShootActivityQueue, "Project Activity", c.projectShootActivityReconciler, &waitGroup, c.workerCh)
controllerutils.CreateWorker(ctx, c.projectQueue, "Project", c.projectReconciler, &waitGroup, c.workerCh, controllerutils.WithLogger(c.log.WithName(projectReconcilerName)))
controllerutils.CreateWorker(ctx, c.projectStaleQueue, "Project Stale", c.projectStaleReconciler, &waitGroup, c.workerCh, controllerutils.WithLogger(c.log.WithName(staleReconcilerName)))
controllerutils.CreateWorker(ctx, c.projectShootActivityQueue, "Project Activity", c.projectShootActivityReconciler, &waitGroup, c.workerCh, controllerutils.WithLogger(c.log.WithName(activityReconcilerName)))
}

// Shutdown handling
Expand All @@ -148,11 +157,11 @@ func (c *Controller) Run(ctx context.Context, workers int) {
c.projectShootActivityQueue.ShutDown()

for {
if c.projectQueue.Len() == 0 && c.projectStaleQueue.Len() == 0 && c.numberOfRunningWorkers == 0 {
logger.Logger.Debug("No running Project worker and no items left in the queues. Terminated Project controller...")
if c.projectQueue.Len() == 0 && c.projectStaleQueue.Len() == 0 && c.projectShootActivityQueue.Len() == 0 && c.numberOfRunningWorkers == 0 {
c.log.V(1).Info("No running Project worker and no items left in the queues. Terminating Project controller")
break
}
logger.Logger.Debugf("Waiting for %d Project worker(s) to finish (%d item(s) left in the queues)...", c.numberOfRunningWorkers, c.projectQueue.Len()+c.projectStaleQueue.Len())
c.log.V(1).Info("Waiting for Project workers to finish", "numberOfRunningWorkers", c.numberOfRunningWorkers, "queueLength", c.projectQueue.Len()+c.projectStaleQueue.Len()+c.projectShootActivityQueue.Len())
time.Sleep(5 * time.Second)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,67 +16,68 @@ package project

import (
"context"
"fmt"

gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/logger"
gutil "github.com/gardener/gardener/pkg/utils/gardener"
"github.com/go-logr/logr"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/tools/cache"
logf "sigs.k8s.io/controller-runtime/pkg/log"

gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
gutil "github.com/gardener/gardener/pkg/utils/gardener"

"github.com/sirupsen/logrus"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

const activityReconcilerName = "activity"

// NewActivityReconciler creates a new instance of a reconciler which reconciles the LastActivityTimestamp of a project, then it calls the stale reconciler.
func NewActivityReconciler(
l logrus.FieldLogger,
gardenClient client.Client,
) reconcile.Reconciler {
func NewActivityReconciler(gardenClient client.Client) reconcile.Reconciler {
return &projectActivityReconciler{
logger: l,
gardenClient: gardenClient,
}
}

type projectActivityReconciler struct {
logger logrus.FieldLogger
gardenClient client.Client
}

func (r *projectActivityReconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)

shoot := &gardencorev1beta1.Shoot{}

if err := r.gardenClient.Get(ctx, client.ObjectKey{Namespace: request.Namespace, Name: request.Name}, shoot); err != nil {
logger.Logger.Errorf("Couldn't get Shoot due to: %v", err)
return reconcile.Result{}, err
if apierrors.IsNotFound(err) {
log.Info("Object is gone, stop reconciling")
return reconcile.Result{}, nil
}
return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err)
}

return r.reconcile(ctx, shoot)
return r.reconcile(ctx, log, shoot)
}

func (r *projectActivityReconciler) reconcile(ctx context.Context, obj client.Object) (reconcile.Result, error) {
func (r *projectActivityReconciler) reconcile(ctx context.Context, log logr.Logger, obj client.Object) (reconcile.Result, error) {
project, err := gutil.ProjectForNamespaceFromReader(ctx, r.gardenClient, obj.GetNamespace())
if err != nil {
if apierrors.IsNotFound(err) {
return reconcile.Result{Requeue: false}, nil
// project is gone, nothing to do here
return reconcile.Result{}, nil
}
logger.Logger.Errorf("Couldn't get project due to: %v", err)
return reconcile.Result{}, err
return reconcile.Result{}, fmt.Errorf("failed to get project for namespace %q: %w", obj.GetNamespace(), err)
}

if project.Status.LastActivityTimestamp != nil && obj.GetCreationTimestamp().UTC().Before(project.Status.LastActivityTimestamp.UTC()) {
// not the newest object in this project, nothing to do
return reconcile.Result{}, nil
}

timestamp := obj.GetCreationTimestamp()

if project.Status.LastActivityTimestamp == nil {
shoots := &gardencorev1beta1.ShootList{}
if err := r.gardenClient.List(ctx, shoots, client.InNamespace(*project.Spec.Namespace)); err != nil {
logger.Logger.Errorf("Couldn't list Shoots due to: %v", err)
return reconcile.Result{}, err
return reconcile.Result{}, fmt.Errorf("failed to list shoots in project namespace %q: %w", *project.Spec.Namespace, err)
}
for _, shoot := range shoots.Items {
if shoot.GetCreationTimestamp().UTC().After(timestamp.UTC()) {
Expand All @@ -85,19 +86,19 @@ func (r *projectActivityReconciler) reconcile(ctx context.Context, obj client.Ob
}
}

log.Info("Updating Project's lastActivityTimestamp", "lastActivityTimestamp", timestamp)
if err := updateStatus(ctx, r.gardenClient, project, func() {
project.Status.LastActivityTimestamp = &timestamp
}); err != nil {
logger.Logger.Errorf("Error while updating project: %v", err)
return reconcile.Result{}, err
return reconcile.Result{}, fmt.Errorf("failed updating Project's lastActivityTimestamp: %w", err)
}
return reconcile.Result{}, nil
}

func (c *Controller) updateShootActivity(obj interface{}) {
key, err := cache.MetaNamespaceKeyFunc(obj)
if err != nil {
logger.Logger.Errorf("Couldn't get key for object %+v: %v", obj, err)
c.log.Error(err, "Couldn't get key for object", "object", obj)
return
}
c.projectShootActivityQueue.Add(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import (
"reflect"
"time"

"github.com/golang/mock/gomock"

"github.com/gardener/gardener/pkg/apis/core"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/logger"
mockclient "github.com/gardener/gardener/pkg/mock/controller-runtime/client"
"github.com/golang/mock/gomock"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -95,10 +95,9 @@ var _ = Describe("Project Activity Reconcile", func() {
},
}

logger.Logger = logger.NewLogger("info", "")
ctrl := gomock.NewController(GinkgoT())
k8sGardenRuntimeClient = mockclient.NewMockClient(ctrl)
reconciler = NewActivityReconciler(logger.NewNopLogger(), k8sGardenRuntimeClient)
reconciler = NewActivityReconciler(k8sGardenRuntimeClient)
request = reconcile.Request{NamespacedName: types.NamespacedName{Name: shoot.Name, Namespace: shoot.Namespace}}
k8sGardenRuntimeClient.EXPECT().List(ctx, gomock.AssignableToTypeOf(&gardencorev1beta1.ProjectList{}), gomock.Any()).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ProjectList, opts client.MatchingFields) error {
if reflect.DeepEqual(opts[core.ProjectNamespace], *project.Spec.Namespace) {
Expand All @@ -108,7 +107,6 @@ var _ = Describe("Project Activity Reconcile", func() {
if reflect.DeepEqual(opts[core.ProjectNamespace], "error") {
return errors.New("API ERROR")
}
logger.Logger.Infof("Project %s not found returning empty", opts[core.ProjectNamespace])
*obj = gardencorev1beta1.ProjectList{}
return nil
}).AnyTimes()
Expand Down Expand Up @@ -172,7 +170,7 @@ var _ = Describe("Project Activity Reconcile", func() {

It("should not update the creation timestamp since the shoot does not exist", func() {
reconcileResult, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: shoot.Name, Namespace: "empty"}})
Expect(err).To(HaveOccurred())
Expect(err).NotTo(HaveOccurred())
Expect(reconcileResult).To(Equal(reconcile.Result{}))
})

Expand Down
Loading

0 comments on commit 9fffad8

Please sign in to comment.