mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 04:26:45 +00:00
feat(controller): add controllwr concurrency (#1722)
* feat(controllers): add concurrency * feat(controller): add workers flag Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore(deps): update actions/upload-artifact action to v5 (#1721) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore(deps): update github/codeql-action action to v4.31.0 (#1720) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: satisfy linter Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: use serviceaccount parsing Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * fix(deps): update module github.com/onsi/ginkgo/v2 to v2.27.1 (#1714) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore(deps): update github/codeql-action digest to ae78991 (#1719) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: use serviceaccount parsing Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: use serviceaccount parsing Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> --------- Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
@@ -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) || \
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
*/}}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
labels:
|
||||
{{- include "capsule.labels" . | nindent 4 }}
|
||||
{{- with .Values.customAnnotations }}
|
||||
|
||||
+3
-2
@@ -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 }}
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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) }}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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.
|
||||
|
||||
+9
-4
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2020-2025 Project Capsule Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package utils
|
||||
|
||||
type ControllerOptions struct {
|
||||
MaxConcurrentReconciles int
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user