diff --git a/cmd/main.go b/cmd/main.go index 8b74982c..5fe32a0c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -50,6 +50,7 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/rest" + "k8s.io/client-go/util/flowcontrol" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -70,11 +71,20 @@ func init() { //+kubebuilder:scaffold:scheme } -const defaultMinimalRotationTimeRatio = 0.6 -const defaultExpirationTime = 24 * time.Hour -const defaultGardenerRequestTimeout = 60 * time.Second -const defaultControlPlaneRequeueDuration = 10 * time.Second -const defaultGardenerRequeueDuration = 15 * time.Second +// Default values for the Runtime controller configuration +const ( + defaultControlPlaneRequeueDuration = 10 * time.Second + defaultGardenerRequestTimeout = 3 * time.Second + defaultGardenerRateLimiterQPS = 5 + defaultGardenerRateLimiterBurst = 5 + defaultMinimalRotationTimeRatio = 0.6 + defaultExpirationTime = 24 * time.Hour + defaultGardenerReconciliationTimeout = 60 * time.Second + defaultGardenerRequeueDuration = 15 * time.Second + defaultShootCreateRequeueDuration = 60 * time.Second + defaultShootDeleteRequeueDuration = 90 * time.Second + defaultShootReconcileRequeueDuration = 30 * time.Second +) func main() { var metricsAddr string @@ -84,7 +94,10 @@ func main() { var gardenerProjectName string var minimalRotationTimeRatio float64 var expirationTime time.Duration - var gardenerRequestTimeout time.Duration + var gardenerCtrlReconciliationTimeout time.Duration + var runtimeCtrlGardenerRequestTimeout time.Duration + var runtimeCtrlGardenerRateLimiterQPS int + var runtimeCtrlGardenerRateLimiterBurst int var converterConfigFilepath string var shootSpecDumpEnabled bool var auditLogMandatory bool @@ -98,7 +111,10 @@ func main() { flag.StringVar(&gardenerProjectName, "gardener-project-name", "gardener-project", "Name of the Gardener project") flag.Float64Var(&minimalRotationTimeRatio, "minimal-rotation-time", defaultMinimalRotationTimeRatio, "The ratio determines what is the minimal time that needs to pass to rotate certificate.") flag.DurationVar(&expirationTime, "kubeconfig-expiration-time", defaultExpirationTime, "Dynamic kubeconfig expiration time") - flag.DurationVar(&gardenerRequestTimeout, "gardener-request-timeout", defaultGardenerRequestTimeout, "Timeout duration for requests to Gardener") + flag.DurationVar(&gardenerCtrlReconciliationTimeout, "gardener-ctrl-reconcilation-timeout", defaultGardenerReconciliationTimeout, "Timeout duration for reconlication for Gardener Cluster Controller") + flag.DurationVar(&runtimeCtrlGardenerRequestTimeout, "gardener-request-timeout", defaultGardenerRequestTimeout, "Timeout duration for Gardener client for Runtime Controller") + flag.IntVar(&runtimeCtrlGardenerRateLimiterQPS, "gardener-ratelimiter-qps", defaultGardenerRateLimiterQPS, "Gardener client rate limiter QPS for Runtime Controller") + flag.IntVar(&runtimeCtrlGardenerRateLimiterBurst, "gardener-ratelimiter-burst", defaultGardenerRateLimiterBurst, "Gardener client rate limiter burst for Runtime Controller") flag.StringVar(&converterConfigFilepath, "converter-config-filepath", "/converter-config/converter_config.json", "A file path to the gardener shoot converter configuration.") flag.BoolVar(&shootSpecDumpEnabled, "shoot-spec-dump-enabled", false, "Feature flag to allow persisting specs of created shoots") flag.BoolVar(&auditLogMandatory, "audit-log-mandatory", true, "Feature flag to enable strict mode for audit log configuration") @@ -142,7 +158,7 @@ func main() { } gardenerNamespace := fmt.Sprintf("garden-%s", gardenerProjectName) - gardenerClient, shootClient, dynamicKubeconfigClient, err := initGardenerClients(gardenerKubeconfigPath, gardenerNamespace) + gardenerClient, shootClient, dynamicKubeconfigClient, err := initGardenerClients(gardenerKubeconfigPath, gardenerNamespace, runtimeCtrlGardenerRequestTimeout, runtimeCtrlGardenerRateLimiterQPS, runtimeCtrlGardenerRateLimiterBurst) if err != nil { setupLog.Error(err, "unable to initialize gardener clients", "controller", "GardenerCluster") @@ -163,7 +179,7 @@ func main() { logger, rotationPeriod, minimalRotationTimeRatio, - gardenerRequestTimeout, + gardenerCtrlReconciliationTimeout, metrics, ).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "GardenerCluster") @@ -193,14 +209,17 @@ func main() { } cfg := fsm.RCCfg{ - GardenerRequeueDuration: defaultGardenerRequeueDuration, - ControlPlaneRequeueDuration: defaultControlPlaneRequeueDuration, - Finalizer: infrastructuremanagerv1.Finalizer, - ShootNamesapace: gardenerNamespace, - Config: config, - AuditLogMandatory: auditLogMandatory, - Metrics: metrics, - AuditLogging: auditLogDataMap, + GardenerRequeueDuration: defaultGardenerRequeueDuration, + RequeueDurationShootCreate: defaultShootCreateRequeueDuration, + RequeueDurationShootDelete: defaultShootDeleteRequeueDuration, + RequeueDurationShootReconcile: defaultShootReconcileRequeueDuration, + ControlPlaneRequeueDuration: defaultControlPlaneRequeueDuration, + Finalizer: infrastructuremanagerv1.Finalizer, + ShootNamesapace: gardenerNamespace, + Config: config, + AuditLogMandatory: auditLogMandatory, + Metrics: metrics, + AuditLogging: auditLogDataMap, } if shootSpecDumpEnabled { cfg.PVCPath = "/testdata/kim" @@ -239,12 +258,15 @@ func main() { } } -func initGardenerClients(kubeconfigPath string, namespace string) (client.Client, gardener_apis.ShootInterface, client.SubResourceClient, error) { +func initGardenerClients(kubeconfigPath string, namespace string, timeout time.Duration, rlQPS, rlBurst int) (client.Client, gardener_apis.ShootInterface, client.SubResourceClient, error) { restConfig, err := gardener.NewRestConfigFromFile(kubeconfigPath) if err != nil { return nil, nil, nil, err } + restConfig.Timeout = timeout + restConfig.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(float32(rlQPS), rlBurst) + gardenerClientSet, err := gardener_apis.NewForConfig(restConfig) if err != nil { return nil, nil, nil, err diff --git a/internal/controller/kubeconfig/gardener_cluster_controller.go b/internal/controller/kubeconfig/gardener_cluster_controller.go index c532e203..67aa9f5b 100644 --- a/internal/controller/kubeconfig/gardener_cluster_controller.go +++ b/internal/controller/kubeconfig/gardener_cluster_controller.go @@ -34,6 +34,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + pkgctrl "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/predicate" ) @@ -43,6 +44,7 @@ const ( clusterCRNameLabel = "operator.kyma-project.io/cluster-name" rotationPeriodRatio = 0.95 + numberOfWorkers = 25 ) // GardenerClusterController reconciles a GardenerCluster object @@ -436,5 +438,6 @@ func (controller *GardenerClusterController) SetupWithManager(mgr ctrl.Manager) predicate.AnnotationChangedPredicate{}, predicate.GenerationChangedPredicate{}), )). + WithOptions(pkgctrl.Options{MaxConcurrentReconciles: numberOfWorkers}). Complete(controller) } diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index 0a5391d1..5d79d549 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -26,14 +26,17 @@ type writerGetter = func(filePath string) (io.Writer, error) // runtime reconciler specific configuration type RCCfg struct { - GardenerRequeueDuration time.Duration - ControlPlaneRequeueDuration time.Duration - Finalizer string - PVCPath string - ShootNamesapace string - AuditLogMandatory bool - Metrics metrics.Metrics - AuditLogging auditlogs.Configuration + GardenerRequeueDuration time.Duration + RequeueDurationShootCreate time.Duration + RequeueDurationShootDelete time.Duration + RequeueDurationShootReconcile time.Duration + ControlPlaneRequeueDuration time.Duration + Finalizer string + PVCPath string + ShootNamesapace string + AuditLogMandatory bool + Metrics metrics.Metrics + AuditLogging auditlogs.Configuration config.Config } diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go index a73bffc2..87613dba 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go @@ -2,14 +2,15 @@ package fsm import ( "context" + "fmt" "slices" - authenticationv1alpha1 "github.com/gardener/gardener/pkg/apis/authentication/v1alpha1" - gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -27,9 +28,7 @@ var ( ) func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { - // prepare subresource client to request admin kubeconfig - srscClient := m.ShootClient.SubResource("adminkubeconfig") - shootAdminClient, err := GetShootClient(ctx, srscClient, s.shoot) + shootAdminClient, err := GetShootClient(ctx, m.Client, s.instance) if err != nil { updateCRBApplyFailed(&s.instance) return updateStatusAndStopWithError(err) @@ -66,15 +65,15 @@ func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (s } //nolint:gochecknoglobals -var GetShootClient = func(ctx context.Context, - adminKubeconfigClient client.SubResourceClient, shoot *gardener_api.Shoot) (client.Client, error) { - // request for admin kubeconfig with low expiration timeout - var req authenticationv1alpha1.AdminKubeconfigRequest - if err := adminKubeconfigClient.Create(ctx, shoot, &req); err != nil { +var GetShootClient = func(ctx context.Context, cnt client.Client, runtime imv1.Runtime) (client.Client, error) { + runtimeID := runtime.Labels[imv1.LabelKymaRuntimeID] + + secret, err := getKubeconfigSecret(ctx, cnt, runtimeID, runtime.Namespace) + if err != nil { return nil, err } - restConfig, err := clientcmd.RESTConfigFromKubeConfig(req.Status.Kubeconfig) + restConfig, err := clientcmd.RESTConfigFromKubeConfig(secret.Data[kubeconfigSecretKey]) if err != nil { return nil, err } @@ -87,6 +86,24 @@ var GetShootClient = func(ctx context.Context, return shootClientWithAdmin, nil } +func getKubeconfigSecret(ctx context.Context, cnt client.Client, runtimeID, namespace string) (corev1.Secret, error) { + secretName := fmt.Sprintf("kubeconfig-%s", runtimeID) + + var kubeconfigSecret corev1.Secret + secretKey := types.NamespacedName{Name: secretName, Namespace: namespace} + + err := cnt.Get(ctx, secretKey, &kubeconfigSecret) + + if err != nil { + return corev1.Secret{}, err + } + + if kubeconfigSecret.Data == nil { + return corev1.Secret{}, fmt.Errorf("kubeconfig secret `%s` does not contain kubeconfig data", kubeconfigSecret.Name) + } + return kubeconfigSecret, nil +} + func isRBACUserKindOneOf(names []string) func(rbacv1.Subject) bool { return func(s rbacv1.Subject) bool { return s.Kind == rbacv1.UserKind && diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go b/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go index 5fbea952..62c78823 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics/mocks" . "github.com/onsi/ginkgo/v2" @@ -154,8 +153,8 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { defaultSetup := func(f *fsm) error { GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener_api.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return f.Client, nil } return nil @@ -229,8 +228,8 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { setup: func(f *fsm) error { GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener_api.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return nil, testErr } return nil diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 58c8ce0d..fa7b140a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -72,8 +72,7 @@ func createDefaultOIDCConfig(defaultSharedIASTenant config.OidcProvider) gardene } func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { - srscClient := m.ShootClient.SubResource("adminkubeconfig") - shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) + shootAdminClient, shootClientError := GetShootClient(ctx, m.Client, s.instance) if shootClientError != nil { return shootClientError } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go index c3a6beb7..e74ba1ab 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -63,7 +63,7 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFsm := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }, @@ -77,8 +77,8 @@ func TestOidcState(t *testing.T) { } GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -106,7 +106,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFsm, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") @@ -131,14 +131,14 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFsm := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }} GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -171,7 +171,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFsm, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") @@ -198,14 +198,14 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFSM := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }} GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -241,7 +241,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFSM, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go index 72155b6d..a52c79e5 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go @@ -12,6 +12,10 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) +const ( + kubeconfigSecretKey = "config" +) + func sFnCreateKubeconfig(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create Gardener Cluster CR state") @@ -110,7 +114,7 @@ func makeGardenerClusterForRuntime(runtime imv1.Runtime, shoot *gardener.Shoot) Secret: imv1.Secret{ Name: fmt.Sprintf("kubeconfig-%s", runtime.Labels[imv1.LabelKymaRuntimeID]), Namespace: runtime.Namespace, - Key: "config", + Key: kubeconfigSecretKey, }, }, }, diff --git a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go index 37f4a33d..0875cbb9 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go @@ -16,7 +16,7 @@ func sFnDeleteShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl // wait section if !s.shoot.GetDeletionTimestamp().IsZero() { m.log.Info("Waiting for shoot to be deleted", "Name", s.shoot.Name, "Namespace", s.shoot.Namespace) - return requeueAfter(m.RCCfg.GardenerRequeueDuration) + return requeueAfter(m.RCCfg.RequeueDurationShootDelete) } // action section @@ -58,7 +58,7 @@ func sFnDeleteShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl } // out section - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootDelete) } // workaround diff --git a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go index 788e60d1..1b6f2855 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go +++ b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go @@ -23,7 +23,7 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF "Unknown", "Shoot update is in progress") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootReconcile) case gardener.LastOperationStateFailed: lastErrors := s.shoot.Status.LastErrors @@ -36,7 +36,7 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF imv1.ConditionReasonShootCreationPending, "Unknown", "Retryable gardener errors during cluster reconcile") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootReconcile) } msg := fmt.Sprintf("error during cluster processing: reconcilation failed for shoot %s, reason: %s, exiting with no retry", s.shoot.Name, reason) diff --git a/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go b/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go index 2c0036fc..d0322379 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go +++ b/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go @@ -39,7 +39,7 @@ func sFnWaitForShootCreation(_ context.Context, m *fsm, s *systemState) (stateFn "Unknown", "Shoot creation in progress") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootCreate) case gardener.LastOperationStateFailed: lastErrors := s.shoot.Status.LastErrors @@ -52,7 +52,7 @@ func sFnWaitForShootCreation(_ context.Context, m *fsm, s *systemState) (stateFn imv1.ConditionReasonShootCreationPending, "Unknown", "Retryable gardener errors during cluster provisioning") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootCreate) } msg := fmt.Sprintf("Provisioning failed for shoot: %s ! Last state: %s, Description: %s", s.shoot.Name, s.shoot.Status.LastOperation.State, s.shoot.Status.LastOperation.Description) diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index f5134dd7..d0c8801c 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -24,6 +24,8 @@ type fakeFSMOpt func(*fsm) error const defaultControlPlaneRequeueDuration = 10 * time.Second const defaultGardenerRequeueDuration = 15 * time.Second +const defaultRequeueDurationShootCreate = 15 * time.Second +const defaultRequeueDurationShootDelete = 15 * time.Second var ( errFailedToCreateFakeFSM = fmt.Errorf("failed to create fake FSM") diff --git a/internal/controller/runtime/runtime_controller.go b/internal/controller/runtime/runtime_controller.go index 1f8eb574..f621ae40 100644 --- a/internal/controller/runtime/runtime_controller.go +++ b/internal/controller/runtime/runtime_controller.go @@ -27,9 +27,12 @@ import ( "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const numberOfWorkers = 25 + // RuntimeReconciler reconciles a Runtime object // nolint:revive type RuntimeReconciler struct { @@ -86,6 +89,7 @@ func NewRuntimeReconciler(mgr ctrl.Manager, shootClient client.Client, logger lo func (r *RuntimeReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&imv1.Runtime{}). + WithOptions(controller.Options{MaxConcurrentReconciles: numberOfWorkers}). WithEventFilter(predicate.Or( predicate.GenerationChangedPredicate{}, predicate.LabelChangedPredicate{}, diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index cf1e044d..8eb94681 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -25,7 +25,7 @@ import ( gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" - infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics/mocks" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" "github.com/kyma-project/infrastructure-manager/pkg/config" @@ -94,7 +94,7 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = infrastructuremanagerv1.AddToScheme(scheme.Scheme) + err = imv1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) mgr, err := ctrl.NewManager(cfg, ctrl.Options{ @@ -106,7 +106,7 @@ var _ = BeforeSuite(func() { clientScheme := runtime.NewScheme() _ = gardener_api.AddToScheme(clientScheme) - _ = infrastructuremanagerv1.AddToScheme(clientScheme) + _ = imv1.AddToScheme(clientScheme) // tracker will be updated with different shoot sequence for each test case tracker := clienttesting.NewObjectTracker(clientScheme, serializer.NewCodecFactory(clientScheme).UniversalDecoder()) @@ -121,12 +121,15 @@ var _ = BeforeSuite(func() { mm.On("CleanUpRuntimeGauge", mock.Anything, mock.Anything).Return() fsmCfg := fsm.RCCfg{ - Finalizer: infrastructuremanagerv1.Finalizer, - Config: convConfig, - Metrics: mm, - AuditLogging: map[string]map[string]auditlogs.AuditLogData{}, - GardenerRequeueDuration: 3 * time.Second, - ControlPlaneRequeueDuration: 3 * time.Second, + Finalizer: imv1.Finalizer, + Config: convConfig, + Metrics: mm, + AuditLogging: map[string]map[string]auditlogs.AuditLogData{}, + GardenerRequeueDuration: 3 * time.Second, + ControlPlaneRequeueDuration: 3 * time.Second, + RequeueDurationShootReconcile: 3 * time.Second, + RequeueDurationShootCreate: 3 * time.Second, + RequeueDurationShootDelete: 3 * time.Second, } runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsmCfg) @@ -144,7 +147,7 @@ var _ = BeforeSuite(func() { err = gardener_oidc.AddToScheme(shootClientScheme) k8sFakeClientRoleBindings = fake.NewClientBuilder().WithScheme(shootClientScheme).Build() - fsm.GetShootClient = func(_ context.Context, _ client.SubResourceClient, _ *gardener_api.Shoot) (client.Client, error) { + fsm.GetShootClient = func(_ context.Context, _ client.Client, _ imv1.Runtime) (client.Client, error) { return k8sFakeClientRoleBindings, nil }