diff --git a/Makefile b/Makefile index e2f2b9a4..e8db7468 100644 --- a/Makefile +++ b/Makefile @@ -378,7 +378,7 @@ ko: $(call go-install-tool,$(KO),github.com/$(KO_LOOKUP)@$(KO_VERSION)) NWA := $(LOCALBIN)/nwa -NWA_VERSION := v0.7.7 +NWA_VERSION := v0.7.6 NWA_LOOKUP := B1NARY-GR0UP/nwa nwa: @test -s $(NWA) && $(NWA) -h | grep -q $(NWA_VERSION) || \ diff --git a/charts/capsule/README.md b/charts/capsule/README.md index 4542264b..6ca60685 100644 --- a/charts/capsule/README.md +++ b/charts/capsule/README.md @@ -116,6 +116,7 @@ The following Values have changed key or Value: | manager.options.annotations | object | `{}` | Additional annotations to add to the CapsuleConfiguration resource | | manager.options.capsuleConfiguration | string | `"default"` | Change the default name of the capsule configuration name | | manager.options.capsuleUserGroups | list | `["projectcapsule.dev"]` | Names of the groups considered as Capsule users. | +| manager.options.createConfiguration | bool | `true` | Create Configuration | | manager.options.forceTenantPrefix | bool | `false` | Boolean, enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix, separated by a dash | | manager.options.generateCertificates | bool | `true` | Specifies whether capsule webhooks certificates should be generated by capsule operator | | manager.options.ignoreUserWithGroups | list | `[]` | Define groups which when found in the request of a user will be ignored by the Capsule this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups. | @@ -124,6 +125,7 @@ The following Values have changed key or Value: | manager.options.nodeMetadata | object | `{"forbiddenAnnotations":{"denied":[],"deniedRegex":""},"forbiddenLabels":{"denied":[],"deniedRegex":""}}` | Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant | | manager.options.protectedNamespaceRegex | string | `""` | If specified, disallows creation of namespaces matching the passed regexp | | manager.options.userNames | list | `[]` | Names of the users considered as Capsule users. | +| manager.options.workers | int | `1` | Workers (MaxConcurrentReconciles) is the maximum number of concurrent Reconciles which can be run (ALPHA). | | manager.rbac.create | bool | `true` | Specifies whether RBAC resources should be created. | | manager.rbac.existingClusterRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. | | manager.rbac.existingRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. | diff --git a/charts/capsule/templates/_helpers.tpl b/charts/capsule/templates/_helpers.tpl index 1fb127b4..446ec9ad 100644 --- a/charts/capsule/templates/_helpers.tpl +++ b/charts/capsule/templates/_helpers.tpl @@ -53,6 +53,15 @@ app.kubernetes.io/name: {{ include "capsule.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} + +{{/* +Release Annotations +*/}} +{{- define "capsule.releaseAnnotations" -}} +meta.helm.sh/release-name: {{ $.Release.Name }} +meta.helm.sh/release-namespace: {{ .Release.Namespace }} +{{- end }} + {{/* ServiceAccount annotations */}} diff --git a/charts/capsule/templates/_pod.tpl b/charts/capsule/templates/_pod.tpl index db926896..c7a241a4 100644 --- a/charts/capsule/templates/_pod.tpl +++ b/charts/capsule/templates/_pod.tpl @@ -64,6 +64,7 @@ spec: - --webhook-port={{ .Values.manager.webhookPort }} - --zap-log-level={{ default 4 .Values.manager.options.logLevel }} - --configuration-name={{ .Values.manager.options.capsuleConfiguration }} + - --workers={{ .Values.manager.options.workers }} {{- with .Values.manager.extraArgs }} {{- toYaml . | nindent 8 }} {{- end }} @@ -74,6 +75,10 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName {{- with .Values.manager.env }} {{- toYaml . | nindent 6 }} {{- end }} diff --git a/charts/capsule/templates/certificate.yaml b/charts/capsule/templates/certificate.yaml index bf14c1f7..1ebaa271 100644 --- a/charts/capsule/templates/certificate.yaml +++ b/charts/capsule/templates/certificate.yaml @@ -4,6 +4,7 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: {{ include "capsule.fullname" . }}-webhook-selfsigned + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} @@ -17,6 +18,7 @@ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: {{ include "capsule.fullname" . }}-webhook-cert + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/templates/certs.yaml b/charts/capsule/templates/certs.yaml index 6662f865..8006403f 100644 --- a/charts/capsule/templates/certs.yaml +++ b/charts/capsule/templates/certs.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: Secret metadata: + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/templates/configuration-default.yaml b/charts/capsule/templates/configuration.yaml similarity index 89% rename from charts/capsule/templates/configuration-default.yaml rename to charts/capsule/templates/configuration.yaml index 34dec210..d6a4cb2b 100644 --- a/charts/capsule/templates/configuration-default.yaml +++ b/charts/capsule/templates/configuration.yaml @@ -1,8 +1,9 @@ -{{- if or (not $.Values.crds.exclusive) ($.Values.crds.createConfig) }} +{{- if $.Values.manager.options.createConfiguration }} apiVersion: capsule.clastix.io/v1beta2 kind: CapsuleConfiguration metadata: - name: default + name: {{ .Values.manager.options.capsuleConfiguration }} + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.manager.options.labels }} diff --git a/charts/capsule/templates/crd-lifecycle/crds.tpl b/charts/capsule/templates/crd-lifecycle/crds.tpl index 1daed3d9..d994c72b 100644 --- a/charts/capsule/templates/crd-lifecycle/crds.tpl +++ b/charts/capsule/templates/crd-lifecycle/crds.tpl @@ -14,7 +14,7 @@ {{/* Add Common Lables */}} - {{- $_ := set $p.metadata "annotations" (mergeOverwrite (default dict (get $p.metadata "annotations")) (default dict $.Values.crds.annotations)) -}} + {{- $_ := set $p.metadata "annotations" (mergeOverwrite (default dict (get $p.metadata "annotations")) (default dict $.Values.crds.annotations) (fromYaml (include "capsule.releaseAnnotations" $))) -}} {{/* Add Keep annotation to CRDs */}} {{- if $.Values.crds.keep }} diff --git a/charts/capsule/templates/daemonset.yaml b/charts/capsule/templates/daemonset.yaml index dd332107..c65ec8f1 100644 --- a/charts/capsule/templates/daemonset.yaml +++ b/charts/capsule/templates/daemonset.yaml @@ -4,6 +4,7 @@ apiVersion: apps/v1 kind: DaemonSet metadata: name: {{ include "capsule.controllerName" . }} + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/templates/deployment.yaml b/charts/capsule/templates/deployment.yaml index ad538af8..ee78da79 100644 --- a/charts/capsule/templates/deployment.yaml +++ b/charts/capsule/templates/deployment.yaml @@ -4,6 +4,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "capsule.controllerName" . }} + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/templates/metrics-service.yaml b/charts/capsule/templates/metrics-service.yaml index 45cd4e7e..49cf236c 100644 --- a/charts/capsule/templates/metrics-service.yaml +++ b/charts/capsule/templates/metrics-service.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: Service metadata: name: {{ include "capsule.fullname" . }}-controller-manager-metrics-service + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/templates/post-install/job.yaml b/charts/capsule/templates/post-install/job.yaml index 524bf3f7..8f40da95 100644 --- a/charts/capsule/templates/post-install/job.yaml +++ b/charts/capsule/templates/post-install/job.yaml @@ -6,6 +6,7 @@ apiVersion: batch/v1 kind: Job metadata: name: "{{ include "capsule.post-install.name" . }}" + namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/component: {{ include "capsule.post-install.component" . | quote }} {{- include "capsule.labels" . | nindent 4 }} diff --git a/charts/capsule/templates/pre-delete/job.yaml b/charts/capsule/templates/pre-delete/job.yaml index 3f839a27..ad5350a3 100644 --- a/charts/capsule/templates/pre-delete/job.yaml +++ b/charts/capsule/templates/pre-delete/job.yaml @@ -6,6 +6,7 @@ apiVersion: batch/v1 kind: Job metadata: name: "{{ include "capsule.pre-delete.name" $ }}" + namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/component: {{ include "capsule.pre-delete.component" . | quote }} {{- include "capsule.labels" . | nindent 4 }} diff --git a/charts/capsule/templates/rbac.yaml b/charts/capsule/templates/rbac.yaml index eec7c212..62d168b3 100644 --- a/charts/capsule/templates/rbac.yaml +++ b/charts/capsule/templates/rbac.yaml @@ -47,6 +47,7 @@ kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ include "capsule.fullname" $ }}-{{ $nr }} + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" $ | nindent 4 }} {{- with $.Values.customAnnotations }} diff --git a/charts/capsule/templates/serviceaccount.yaml b/charts/capsule/templates/serviceaccount.yaml index fa1b0133..1ada5d22 100644 --- a/charts/capsule/templates/serviceaccount.yaml +++ b/charts/capsule/templates/serviceaccount.yaml @@ -4,6 +4,7 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ include "capsule.serviceAccountName" . }} + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- if or (.Values.serviceAccount.annotations) (.Values.customAnnotations) }} diff --git a/charts/capsule/templates/validatingwebhookconfiguration.yaml b/charts/capsule/templates/validatingwebhookconfiguration.yaml index 3b4869c7..78d1408e 100644 --- a/charts/capsule/templates/validatingwebhookconfiguration.yaml +++ b/charts/capsule/templates/validatingwebhookconfiguration.yaml @@ -3,6 +3,7 @@ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: {{ include "capsule.fullname" . }}-validating-webhook-configuration + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} annotations: diff --git a/charts/capsule/templates/webhook-service.yaml b/charts/capsule/templates/webhook-service.yaml index 48e47040..f13028ef 100644 --- a/charts/capsule/templates/webhook-service.yaml +++ b/charts/capsule/templates/webhook-service.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: Service metadata: name: {{ include "capsule.fullname" . }}-webhook-service + namespace: {{ $.Release.Namespace }} labels: {{- include "capsule.labels" . | nindent 4 }} {{- with .Values.customAnnotations }} diff --git a/charts/capsule/values.schema.json b/charts/capsule/values.schema.json index 3fb5a9c7..f1ba5b12 100644 --- a/charts/capsule/values.schema.json +++ b/charts/capsule/values.schema.json @@ -338,6 +338,10 @@ "type": "string" } }, + "createConfiguration": { + "description": "Create Configuration", + "type": "boolean" + }, "forceTenantPrefix": { "description": "Boolean, enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix, separated by a dash", "type": "boolean" @@ -393,6 +397,10 @@ "userNames": { "description": "Names of the users considered as Capsule users.", "type": "array" + }, + "workers": { + "description": "Workers (MaxConcurrentReconciles) is the maximum number of concurrent Reconciles which can be run (ALPHA).", + "type": "integer" } } }, diff --git a/charts/capsule/values.yaml b/charts/capsule/values.yaml index 4e04a0c1..f59081d7 100644 --- a/charts/capsule/values.yaml +++ b/charts/capsule/values.yaml @@ -166,12 +166,16 @@ manager: # Additional Capsule Controller Options options: + # -- Create Configuration + createConfiguration: true + # -- Change the default name of the capsule configuration name + capsuleConfiguration: default # -- Additional labels to add to the CapsuleConfiguration resource labels: {} # -- Additional annotations to add to the CapsuleConfiguration resource annotations: {} - # -- Change the default name of the capsule configuration name - capsuleConfiguration: default + # -- Workers (MaxConcurrentReconciles) is the maximum number of concurrent Reconciles which can be run (ALPHA). + workers: 1 # -- Set the log verbosity of the capsule with a value from 1 to 5 logLevel: '3' # -- Names of the users considered as Capsule users. diff --git a/cmd/main.go b/cmd/main.go index 0c21e899..877ff341 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -40,6 +40,7 @@ import ( servicelabelscontroller "github.com/projectcapsule/capsule/controllers/servicelabels" tenantcontroller "github.com/projectcapsule/capsule/controllers/tenant" tlscontroller "github.com/projectcapsule/capsule/controllers/tls" + utilscontroller "github.com/projectcapsule/capsule/controllers/utils" "github.com/projectcapsule/capsule/pkg/configuration" "github.com/projectcapsule/capsule/pkg/indexer" "github.com/projectcapsule/capsule/pkg/metrics" @@ -87,6 +88,8 @@ func printVersion() { //nolint:maintidx func main() { + controllerConfig := utilscontroller.ControllerOptions{} + var enableLeaderElection, version bool var metricsAddr, namespace, configurationName string @@ -95,6 +98,7 @@ func main() { var goFlagSet goflag.FlagSet + flag.IntVar(&controllerConfig.MaxConcurrentReconciles, "workers", 1, "MaxConcurrentReconciles is the maximum number of concurrent Reconciles which can be run.") flag.IntVar(&webhookPort, "webhook-port", 9443, "The port the webhook server binds to.") flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") flag.BoolVar(&enableLeaderElection, "enable-leader-election", false, @@ -203,7 +207,7 @@ func main() { Metrics: metrics.MustMakeTenantRecorder(), Log: ctrl.Log.WithName("controllers").WithName("Tenant"), Recorder: manager.GetEventRecorderFor("tenant-controller"), - }).SetupWithManager(manager); err != nil { + }).SetupWithManager(manager, controllerConfig); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Tenant") os.Exit(1) } @@ -294,7 +298,7 @@ func main() { os.Exit(1) } - if err = (&pv.Controller{}).SetupWithManager(manager); err != nil { + if err = (&pv.Controller{}).SetupWithManager(manager, controllerConfig); err != nil { setupLog.Error(err, "unable to create controller", "controller", "PersistentVolume") os.Exit(1) } @@ -306,12 +310,12 @@ func main() { os.Exit(1) } - if err = (&resources.Global{}).SetupWithManager(manager); err != nil { + if err = (&resources.Global{}).SetupWithManager(manager, controllerConfig); err != nil { setupLog.Error(err, "unable to create controller", "controller", "resources.Global") os.Exit(1) } - if err = (&resources.Namespaced{}).SetupWithManager(manager); err != nil { + if err = (&resources.Namespaced{}).SetupWithManager(manager, controllerConfig); err != nil { setupLog.Error(err, "unable to create controller", "controller", "resources.Namespaced") os.Exit(1) } @@ -320,6 +324,7 @@ func main() { ctrl.Log.WithName("controllers").WithName("ResourcePools"), manager, manager.GetEventRecorderFor("pools-ctrl"), + controllerConfig, ); err != nil { setupLog.Error(err, "unable to create controller", "controller", "resourcepools") os.Exit(1) diff --git a/controllers/pv/controller.go b/controllers/pv/controller.go index fb549d69..6537b7c5 100644 --- a/controllers/pv/controller.go +++ b/controllers/pv/controller.go @@ -12,11 +12,13 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" log2 "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" + "github.com/projectcapsule/capsule/controllers/utils" capsuleutils "github.com/projectcapsule/capsule/pkg/utils" webhookutils "github.com/projectcapsule/capsule/pkg/webhook/utils" ) @@ -26,6 +28,35 @@ type Controller struct { label string } +func (c *Controller) SetupWithManager(mgr ctrl.Manager, cfg utils.ControllerOptions) error { + label, err := capsuleutils.GetTypeLabel(&capsulev1beta2.Tenant{}) + if err != nil { + return err + } + + c.client = mgr.GetClient() + c.label = label + + return ctrl.NewControllerManagedBy(mgr). + For(&corev1.PersistentVolume{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool { + pv, ok := object.(*corev1.PersistentVolume) + if !ok { + return false + } + + if pv.Spec.ClaimRef == nil { + return false + } + + labels := object.GetLabels() + _, ok = labels[c.label] + + return !ok + }))). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). + Complete(c) +} + func (c *Controller) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { log := log2.FromContext(ctx) @@ -87,31 +118,3 @@ func (c *Controller) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, nil } - -func (c *Controller) SetupWithManager(mgr ctrl.Manager) error { - label, err := capsuleutils.GetTypeLabel(&capsulev1beta2.Tenant{}) - if err != nil { - return err - } - - c.client = mgr.GetClient() - c.label = label - - return ctrl.NewControllerManagedBy(mgr). - For(&corev1.PersistentVolume{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool { - pv, ok := object.(*corev1.PersistentVolume) - if !ok { - return false - } - - if pv.Spec.ClaimRef == nil { - return false - } - - labels := object.GetLabels() - _, ok = labels[c.label] - - return !ok - }))). - Complete(c) -} diff --git a/controllers/resourcepools/claim_controller.go b/controllers/resourcepools/claim_controller.go index 05936e87..ef911306 100644 --- a/controllers/resourcepools/claim_controller.go +++ b/controllers/resourcepools/claim_controller.go @@ -17,11 +17,13 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" + "github.com/projectcapsule/capsule/controllers/utils" "github.com/projectcapsule/capsule/pkg/api" "github.com/projectcapsule/capsule/pkg/meta" "github.com/projectcapsule/capsule/pkg/metrics" @@ -35,7 +37,7 @@ type resourceClaimController struct { recorder record.EventRecorder } -func (r *resourceClaimController) SetupWithManager(mgr ctrl.Manager) error { +func (r *resourceClaimController) SetupWithManager(mgr ctrl.Manager, cfg utils.ControllerOptions) error { return ctrl.NewControllerManagedBy(mgr). For(&capsulev1beta2.ResourcePoolClaim{}). Watches( @@ -43,6 +45,7 @@ func (r *resourceClaimController) SetupWithManager(mgr ctrl.Manager) error { handler.EnqueueRequestsFromMapFunc(r.claimsWithoutPoolFromNamespaces), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). Complete(r) } diff --git a/controllers/resourcepools/manager.go b/controllers/resourcepools/manager.go index c88daa8a..df7973b8 100644 --- a/controllers/resourcepools/manager.go +++ b/controllers/resourcepools/manager.go @@ -10,6 +10,7 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/manager" + "github.com/projectcapsule/capsule/controllers/utils" "github.com/projectcapsule/capsule/pkg/metrics" ) @@ -17,13 +18,14 @@ func Add( log logr.Logger, mgr manager.Manager, recorder record.EventRecorder, + cfg utils.ControllerOptions, ) (err error) { if err = (&resourcePoolController{ Client: mgr.GetClient(), log: log.WithName("Pools"), recorder: recorder, metrics: metrics.MustMakeResourcePoolRecorder(), - }).SetupWithManager(mgr); err != nil { + }).SetupWithManager(mgr, cfg); err != nil { return fmt.Errorf("unable to create pool controller: %w", err) } @@ -32,7 +34,7 @@ func Add( log: log.WithName("Claims"), recorder: recorder, metrics: metrics.MustMakeClaimRecorder(), - }).SetupWithManager(mgr); err != nil { + }).SetupWithManager(mgr, cfg); err != nil { return fmt.Errorf("unable to create claim controller: %w", err) } diff --git a/controllers/resourcepools/pool_controller.go b/controllers/resourcepools/pool_controller.go index 5e6bca84..1d1bc396 100644 --- a/controllers/resourcepools/pool_controller.go +++ b/controllers/resourcepools/pool_controller.go @@ -20,11 +20,13 @@ import ( "k8s.io/client-go/util/retry" 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/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" + ctrlutils "github.com/projectcapsule/capsule/controllers/utils" "github.com/projectcapsule/capsule/pkg/api" "github.com/projectcapsule/capsule/pkg/meta" "github.com/projectcapsule/capsule/pkg/metrics" @@ -39,7 +41,7 @@ type resourcePoolController struct { recorder record.EventRecorder } -func (r *resourcePoolController) SetupWithManager(mgr ctrl.Manager) error { +func (r *resourcePoolController) SetupWithManager(mgr ctrl.Manager, cfg ctrlutils.ControllerOptions) error { return ctrl.NewControllerManagedBy(mgr). For(&capsulev1beta2.ResourcePool{}). Owns(&corev1.ResourceQuota{}). @@ -67,6 +69,7 @@ func (r *resourcePoolController) SetupWithManager(mgr ctrl.Manager) error { return requests }), ). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). Complete(r) } diff --git a/controllers/resources/global.go b/controllers/resources/global.go index deab58e0..76f9b70e 100644 --- a/controllers/resources/global.go +++ b/controllers/resources/global.go @@ -16,12 +16,14 @@ import ( "sigs.k8s.io/cluster-api/util/patch" 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/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" ctrllog "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" + "github.com/projectcapsule/capsule/controllers/utils" ) type Global struct { @@ -29,7 +31,7 @@ type Global struct { processor Processor } -func (r *Global) SetupWithManager(mgr ctrl.Manager) error { +func (r *Global) SetupWithManager(mgr ctrl.Manager, cfg utils.ControllerOptions) error { r.client = mgr.GetClient() r.processor = Processor{ client: mgr.GetClient(), @@ -38,6 +40,7 @@ func (r *Global) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&capsulev1beta2.GlobalTenantResource{}). Watches(&capsulev1beta2.Tenant{}, handler.EnqueueRequestsFromMapFunc(r.enqueueRequestFromTenant)). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). Complete(r) } diff --git a/controllers/resources/namespaced.go b/controllers/resources/namespaced.go index 6af40b24..6aec6872 100644 --- a/controllers/resources/namespaced.go +++ b/controllers/resources/namespaced.go @@ -14,11 +14,13 @@ import ( "sigs.k8s.io/cluster-api/util/patch" 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/controller/controllerutil" ctrllog "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" + "github.com/projectcapsule/capsule/controllers/utils" ) type Namespaced struct { @@ -26,7 +28,7 @@ type Namespaced struct { processor Processor } -func (r *Namespaced) SetupWithManager(mgr ctrl.Manager) error { +func (r *Namespaced) SetupWithManager(mgr ctrl.Manager, cfg utils.ControllerOptions) error { r.client = mgr.GetClient() r.processor = Processor{ client: mgr.GetClient(), @@ -34,6 +36,7 @@ func (r *Namespaced) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&capsulev1beta2.TenantResource{}). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). Complete(r) } diff --git a/controllers/tenant/manager.go b/controllers/tenant/manager.go index 2ee45414..813cd17f 100644 --- a/controllers/tenant/manager.go +++ b/controllers/tenant/manager.go @@ -19,11 +19,13 @@ import ( "k8s.io/client-go/util/retry" 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/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" - "github.com/projectcapsule/capsule/pkg/meta" + "github.com/projectcapsule/capsule/controllers/utils" + meta "github.com/projectcapsule/capsule/pkg/meta" "github.com/projectcapsule/capsule/pkg/metrics" ) @@ -36,7 +38,7 @@ type Manager struct { RESTConfig *rest.Config } -func (r *Manager) SetupWithManager(mgr ctrl.Manager) error { +func (r *Manager) SetupWithManager(mgr ctrl.Manager, cfg utils.ControllerOptions) error { return ctrl.NewControllerManagedBy(mgr). For(&capsulev1beta2.Tenant{}). Owns(&networkingv1.NetworkPolicy{}). @@ -44,6 +46,7 @@ func (r *Manager) SetupWithManager(mgr ctrl.Manager) error { Owns(&corev1.ResourceQuota{}). Owns(&rbacv1.RoleBinding{}). Watches(&corev1.Namespace{}, handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &capsulev1beta2.Tenant{})). + WithOptions(controller.Options{MaxConcurrentReconciles: cfg.MaxConcurrentReconciles}). Complete(r) } @@ -77,12 +80,17 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct }() // Ensuring Metadata. - if err = r.ensureMetadata(ctx, instance); err != nil { + err, updated := r.ensureMetadata(ctx, instance) + if err != nil { err = fmt.Errorf("cannot ensure metadata: %w", err) return result, err } + if updated { + return result, nil + } + // Ensuring ResourceQuota r.Log.V(4).Info("Ensuring limit resources count is updated") diff --git a/controllers/tenant/metadata.go b/controllers/tenant/metadata.go index 024bc92b..f5803ad8 100644 --- a/controllers/tenant/metadata.go +++ b/controllers/tenant/metadata.go @@ -6,26 +6,24 @@ package tenant import ( "context" - "k8s.io/apimachinery/pkg/types" - capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" capsuleapi "github.com/projectcapsule/capsule/pkg/api" ) // Sets a label on the Tenant object with it's name. -func (r *Manager) ensureMetadata(ctx context.Context, tnt *capsulev1beta2.Tenant) (err error) { +func (r *Manager) ensureMetadata(ctx context.Context, tnt *capsulev1beta2.Tenant) (err error, changed bool) { // Assign Labels if tnt.Labels == nil { tnt.Labels = make(map[string]string) } - if v, ok := tnt.Labels[capsuleapi.TenantNameLabel]; ok && v == tnt.Name { - return err + if v, ok := tnt.Labels[capsuleapi.TenantNameLabel]; !ok || v != tnt.Name { + if err := r.Update(ctx, tnt); err != nil { + return err, false + } + + return nil, true } - if err := r.Update(ctx, tnt); err != nil { - return err - } - - return r.Get(ctx, types.NamespacedName{Name: tnt.GetName()}, tnt) + return nil, false } diff --git a/controllers/tenant/utils.go b/controllers/tenant/utils.go index 6a7947ca..4774a775 100644 --- a/controllers/tenant/utils.go +++ b/controllers/tenant/utils.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - capsulev1beta2 "github.com/projectcapsule/capsule/pkg/utils" + "github.com/projectcapsule/capsule/pkg/utils" ) // pruningResources is taking care of removing the no more requested sub-resources as LimitRange, ResourceQuota or @@ -22,7 +22,7 @@ import ( func (r *Manager) pruningResources(ctx context.Context, ns string, keys []string, obj client.Object) (err error) { var capsuleLabel string - if capsuleLabel, err = capsulev1beta2.GetTypeLabel(obj); err != nil { + if capsuleLabel, err = utils.GetTypeLabel(obj); err != nil { return err } diff --git a/controllers/utils/options.go b/controllers/utils/options.go new file mode 100644 index 00000000..2db7583b --- /dev/null +++ b/controllers/utils/options.go @@ -0,0 +1,8 @@ +// Copyright 2020-2025 Project Capsule Authors +// SPDX-License-Identifier: Apache-2.0 + +package utils + +type ControllerOptions struct { + MaxConcurrentReconciles int +} diff --git a/pkg/webhook/utils/is_capsule_user.go b/pkg/webhook/utils/is_capsule_user.go index dd0c5271..3548cf37 100644 --- a/pkg/webhook/utils/is_capsule_user.go +++ b/pkg/webhook/utils/is_capsule_user.go @@ -5,10 +5,11 @@ package utils import ( "context" - "strings" + "os" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/authentication/serviceaccount" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -27,13 +28,14 @@ func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client //nolint:nestif if sets.NewString(req.UserInfo.Groups...).Has("system:serviceaccounts") { - parts := strings.Split(req.UserInfo.Username, ":") - - if len(parts) == 4 { - targetNamespace := parts[2] + namespace, name, err := serviceaccount.SplitUsername(req.UserInfo.Username) + if err == nil { + if namespace == os.Getenv("NAMESPACE") && name == os.Getenv("SERVICE_ACCOUNT") { + return false + } tl := &capsulev1beta2.TenantList{} - if err := clt.List(ctx, tl, client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(".status.namespaces", targetNamespace)}); err != nil { + if err := clt.List(ctx, tl, client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(".status.namespaces", namespace)}); err != nil { return false }