mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-02-14 09:59:57 +00:00
chore(deps): update dependency golangci/golangci-lint to v2 (#1405)
* chore(deps): update dependency golangci/golangci-lint to v2 * chore(golint): bump v2 and satisfy linters 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> Co-authored-by: Oliver Bähler <oliverbaehler@hotmail.com>
This commit is contained in:
83
.golangci.yaml
Normal file
83
.golangci.yaml
Normal file
@@ -0,0 +1,83 @@
|
||||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
allow-parallel-runners: true
|
||||
linters:
|
||||
default: all
|
||||
disable:
|
||||
- depguard
|
||||
- err113
|
||||
- exhaustruct
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nilnil
|
||||
- nonamedreturns
|
||||
- paralleltest
|
||||
- perfsprint
|
||||
- recvcheck
|
||||
- testpackage
|
||||
- unparam
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
settings:
|
||||
cyclop:
|
||||
max-complexity: 27
|
||||
dupl:
|
||||
threshold: 100
|
||||
gocognit:
|
||||
min-complexity: 50
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
goheader:
|
||||
template: |-
|
||||
Copyright 2020-2023 Project Capsule Authors.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
inamedparam:
|
||||
skip-single-param: true
|
||||
nakedret:
|
||||
max-func-lines: 50
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- zz_.*\.go$
|
||||
- .+\.generated.go
|
||||
- .+_test.go
|
||||
- .+_test_.+.go
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/projectcapsule/capsule)
|
||||
gofumpt:
|
||||
module-path: github.com/projectcapsule/capsule
|
||||
extra-rules: false
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- zz_.*\.go$
|
||||
- .+\.generated.go
|
||||
- .+_test.go
|
||||
- .+_test_.+.go
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
@@ -1,60 +0,0 @@
|
||||
linters-settings:
|
||||
dupl:
|
||||
threshold: 100
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
cyclop:
|
||||
max-complexity: 27
|
||||
gocognit:
|
||||
min-complexity: 50
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/projectcapsule/capsule)
|
||||
goheader:
|
||||
template: |-
|
||||
Copyright 2020-2023 Project Capsule Authors.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
gofumpt:
|
||||
module-path: github.com/projectcapsule/capsule
|
||||
extra-rules: false
|
||||
inamedparam:
|
||||
# Skips check for interface methods with only a single parameter.
|
||||
# Default: false
|
||||
skip-single-param: true
|
||||
nakedret:
|
||||
# Make an issue if func has more lines of code than this setting, and it has naked returns.
|
||||
max-func-lines: 50
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- err113
|
||||
- depguard
|
||||
- perfsprint
|
||||
- funlen
|
||||
- gochecknoinits
|
||||
- lll
|
||||
- gochecknoglobals
|
||||
- mnd
|
||||
- nilnil
|
||||
- recvcheck
|
||||
- unparam
|
||||
- paralleltest
|
||||
- ireturn
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
- exhaustruct
|
||||
- nonamedreturns
|
||||
issues:
|
||||
exclude-files:
|
||||
- "zz_.*\\.go$"
|
||||
- ".+\\.generated.go"
|
||||
- ".+_test.go"
|
||||
- ".+_test_.+.go"
|
||||
run:
|
||||
timeout: 3m
|
||||
allow-parallel-runners: true
|
||||
tests: false
|
||||
6
Makefile
6
Makefile
@@ -217,7 +217,7 @@ goimports:
|
||||
# Linting code as PR is expecting
|
||||
.PHONY: golint
|
||||
golint: golangci-lint
|
||||
$(GOLANGCI_LINT) run -c .golangci.yml --verbose --fix
|
||||
$(GOLANGCI_LINT) run -c .golangci.yaml --verbose --fix
|
||||
|
||||
# Running e2e tests in a KinD instance
|
||||
.PHONY: e2e
|
||||
@@ -357,11 +357,11 @@ ko:
|
||||
$(call go-install-tool,$(KO),github.com/$(KO_LOOKUP)@$(KO_VERSION))
|
||||
|
||||
GOLANGCI_LINT := $(LOCALBIN)/golangci-lint
|
||||
GOLANGCI_LINT_VERSION := v1.64.5
|
||||
GOLANGCI_LINT_VERSION := v2.1.5
|
||||
GOLANGCI_LINT_LOOKUP := golangci/golangci-lint
|
||||
golangci-lint: ## Download golangci-lint locally if necessary.
|
||||
@test -s $(GOLANGCI_LINT) && $(GOLANGCI_LINT) -h | grep -q $(GOLANGCI_LINT_VERSION) || \
|
||||
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
|
||||
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
|
||||
|
||||
APIDOCS_GEN := $(LOCALBIN)/crdoc
|
||||
APIDOCS_GEN_VERSION := v0.6.4
|
||||
|
||||
@@ -28,6 +28,12 @@ type MetadataReconciler struct {
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
func (m *MetadataReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&corev1.Pod{}, m.forOptionPerInstanceName(ctx)).
|
||||
Complete(m)
|
||||
}
|
||||
|
||||
func (m *MetadataReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) {
|
||||
var pod corev1.Pod
|
||||
|
||||
@@ -122,9 +128,3 @@ func (m *MetadataReconciler) isNamespaceInTenant(ctx context.Context, namespace
|
||||
|
||||
return len(tl.Items) > 0
|
||||
}
|
||||
|
||||
func (m *MetadataReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&corev1.Pod{}, m.forOptionPerInstanceName(ctx)).
|
||||
Complete(m)
|
||||
}
|
||||
|
||||
@@ -29,40 +29,6 @@ type Global struct {
|
||||
processor Processor
|
||||
}
|
||||
|
||||
func (r *Global) enqueueRequestFromTenant(ctx context.Context, object client.Object) (reqs []reconcile.Request) {
|
||||
tnt := object.(*capsulev1beta2.Tenant) //nolint:forcetypeassert
|
||||
|
||||
resList := capsulev1beta2.GlobalTenantResourceList{}
|
||||
if err := r.client.List(ctx, &resList); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
set := sets.NewString()
|
||||
|
||||
for _, res := range resList.Items {
|
||||
tntSelector := res.Spec.TenantSelector
|
||||
|
||||
selector, err := metav1.LabelSelectorAsSelector(&tntSelector)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if selector.Matches(labels.Set(tnt.GetLabels())) {
|
||||
set.Insert(res.GetName())
|
||||
}
|
||||
}
|
||||
// No need of ordered value here
|
||||
for res := range set {
|
||||
reqs = append(reqs, reconcile.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: res,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return reqs
|
||||
}
|
||||
|
||||
func (r *Global) SetupWithManager(mgr ctrl.Manager) error {
|
||||
r.client = mgr.GetClient()
|
||||
r.processor = Processor{
|
||||
@@ -115,6 +81,40 @@ func (r *Global) Reconcile(ctx context.Context, request reconcile.Request) (reco
|
||||
return r.reconcileNormal(ctx, tntResource)
|
||||
}
|
||||
|
||||
func (r *Global) enqueueRequestFromTenant(ctx context.Context, object client.Object) (reqs []reconcile.Request) {
|
||||
tnt := object.(*capsulev1beta2.Tenant) //nolint:forcetypeassert
|
||||
|
||||
resList := capsulev1beta2.GlobalTenantResourceList{}
|
||||
if err := r.client.List(ctx, &resList); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
set := sets.NewString()
|
||||
|
||||
for _, res := range resList.Items {
|
||||
tntSelector := res.Spec.TenantSelector
|
||||
|
||||
selector, err := metav1.LabelSelectorAsSelector(&tntSelector)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if selector.Matches(labels.Set(tnt.GetLabels())) {
|
||||
set.Insert(res.GetName())
|
||||
}
|
||||
}
|
||||
// No need of ordered value here
|
||||
for res := range set {
|
||||
reqs = append(reqs, reconcile.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: res,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return reqs
|
||||
}
|
||||
|
||||
func (r *Global) reconcileNormal(ctx context.Context, tntResource *capsulev1beta2.GlobalTenantResource) (reconcile.Result, error) {
|
||||
log := ctrllog.FromContext(ctx)
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ func prepareAdditionalMetadata(m map[string]string) map[string]string {
|
||||
if m == nil {
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,17 @@ func (r *abstractServiceLabelsReconciler) Reconcile(ctx context.Context, request
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
func (r *abstractServiceLabelsReconciler) IsNamespaceInTenant(ctx context.Context, namespace string) bool {
|
||||
tl := &capsulev1beta2.TenantList{}
|
||||
if err := r.client.List(ctx, tl, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(".status.namespaces", namespace),
|
||||
}); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(tl.Items) > 0
|
||||
}
|
||||
|
||||
func (r *abstractServiceLabelsReconciler) getTenant(ctx context.Context, namespacedName types.NamespacedName, client client.Client) (*capsulev1beta2.Tenant, error) {
|
||||
ns := &corev1.Namespace{}
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
@@ -109,14 +120,3 @@ func (r *abstractServiceLabelsReconciler) forOptionPerInstanceName(ctx context.C
|
||||
return r.IsNamespaceInTenant(ctx, object.GetNamespace())
|
||||
}))
|
||||
}
|
||||
|
||||
func (r *abstractServiceLabelsReconciler) IsNamespaceInTenant(ctx context.Context, namespace string) bool {
|
||||
tl := &capsulev1beta2.TenantList{}
|
||||
if err := r.client.List(ctx, tl, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(".status.namespaces", namespace),
|
||||
}); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(tl.Items) > 0
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ func (r *EndpointSlicesLabelsReconciler) SetupWithManager(ctx context.Context, m
|
||||
|
||||
return nil
|
||||
case r.VersionMajor == 1 && r.VersionMinor < 25:
|
||||
r.abstractServiceLabelsReconciler.obj = &discoveryv1beta1.EndpointSlice{}
|
||||
r.obj = &discoveryv1beta1.EndpointSlice{}
|
||||
default:
|
||||
r.abstractServiceLabelsReconciler.obj = &discoveryv1.EndpointSlice{}
|
||||
r.obj = &discoveryv1.EndpointSlice{}
|
||||
}
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
|
||||
@@ -76,7 +76,7 @@ func (r *Manager) syncLimitRange(ctx context.Context, tenant *capsulev1beta2.Ten
|
||||
target.SetLabels(labels)
|
||||
target.Spec = spec
|
||||
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
|
||||
})
|
||||
|
||||
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring LimitRange %s", target.GetName()), err)
|
||||
|
||||
@@ -19,5 +19,5 @@ func (r *Manager) ensureMetadata(ctx context.Context, tnt *capsulev1beta2.Tenant
|
||||
|
||||
tnt.Labels[capsuleapi.TenantNameLabel] = tnt.Name
|
||||
|
||||
return r.Client.Update(ctx, tnt)
|
||||
return r.Update(ctx, tnt)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, t
|
||||
|
||||
err = retry.RetryOnConflict(retry.DefaultBackoff, func() (conflictErr error) {
|
||||
ns := &corev1.Namespace{}
|
||||
if conflictErr = r.Client.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil {
|
||||
if conflictErr = r.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func (r *Manager) ensureNamespaceCount(ctx context.Context, tenant *capsulev1bet
|
||||
tenant.Status.Size = uint(len(tenant.Status.Namespaces))
|
||||
|
||||
found := &capsulev1beta2.Tenant{}
|
||||
if err := r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, found); err != nil {
|
||||
if err := r.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, found); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ func (r *Manager) collectNamespaces(ctx context.Context, tenant *capsulev1beta2.
|
||||
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
|
||||
list := &corev1.NamespaceList{}
|
||||
|
||||
err = r.Client.List(ctx, list, client.MatchingFieldsSelector{
|
||||
err = r.List(ctx, list, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(".metadata.ownerReferences[*].capsule", tenant.GetName()),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -75,7 +75,7 @@ func (r *Manager) syncNetworkPolicy(ctx context.Context, tenant *capsulev1beta2.
|
||||
target.SetLabels(labels)
|
||||
target.Spec = spec
|
||||
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
|
||||
})
|
||||
|
||||
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring NetworkPolicy %s", target.GetName()), err)
|
||||
|
||||
@@ -255,7 +255,7 @@ func (r *Manager) syncResourceQuota(ctx context.Context, tenant *capsulev1beta2.
|
||||
target.Spec.Hard = resQuota.Hard
|
||||
}
|
||||
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
|
||||
})
|
||||
|
||||
return retryErr
|
||||
|
||||
@@ -70,7 +70,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
|
||||
for gvk, used := range usedMap {
|
||||
err := retry.RetryOnConflict(retry.DefaultBackoff, func() (retryErr error) {
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
if retryErr = r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, tnt); retryErr != nil {
|
||||
if retryErr = r.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, tnt); retryErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
|
||||
|
||||
tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(gvk)] = fmt.Sprintf("%d", used)
|
||||
|
||||
return r.Client.Update(ctx, tnt)
|
||||
return r.Update(ctx, tnt)
|
||||
})
|
||||
if err != nil {
|
||||
r.Log.Error(err, "cannot update custom Resource Quota", "GVK", gvk)
|
||||
|
||||
@@ -129,12 +129,12 @@ func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsule
|
||||
|
||||
var res controllerutil.OperationResult
|
||||
res, err = controllerutil.CreateOrUpdate(ctx, r.Client, target, func() error {
|
||||
if target.ObjectMeta.Labels == nil {
|
||||
target.ObjectMeta.Labels = map[string]string{}
|
||||
if target.Labels == nil {
|
||||
target.Labels = map[string]string{}
|
||||
}
|
||||
|
||||
target.ObjectMeta.Labels[tenantLabel] = tenant.Name
|
||||
target.ObjectMeta.Labels[roleBindingLabel] = roleBindingHashLabel
|
||||
target.Labels[tenantLabel] = tenant.Name
|
||||
target.Labels[roleBindingLabel] = roleBindingHashLabel
|
||||
target.RoleRef = rbacv1.RoleRef{
|
||||
APIGroup: rbacv1.GroupName,
|
||||
Kind: "ClusterRole",
|
||||
@@ -142,7 +142,7 @@ func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsule
|
||||
}
|
||||
target.Subjects = roleBinding.Subjects
|
||||
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
|
||||
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
|
||||
})
|
||||
|
||||
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring RoleBinding %s", target.GetName()), err)
|
||||
|
||||
@@ -170,7 +170,7 @@ func (r Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.R
|
||||
|
||||
certSecret := &corev1.Secret{}
|
||||
|
||||
if err := r.Client.Get(ctx, request.NamespacedName, certSecret); err != nil {
|
||||
if err := r.Get(ctx, request.NamespacedName, certSecret); err != nil {
|
||||
// Error reading the object - requeue the request.
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
@@ -302,7 +302,7 @@ func (r Reconciler) updateOperatorPod(ctx context.Context, pod corev1.Pod) error
|
||||
// Need to get latest version of pod
|
||||
p := &corev1.Pod{}
|
||||
|
||||
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, p); err != nil && !apierrors.IsNotFound(err) {
|
||||
if err := r.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, p); err != nil && !apierrors.IsNotFound(err) {
|
||||
r.Log.Error(err, "cannot get pod", "name", pod.Name, "namespace", pod.Namespace)
|
||||
|
||||
return err
|
||||
@@ -314,7 +314,7 @@ func (r Reconciler) updateOperatorPod(ctx context.Context, pod corev1.Pod) error
|
||||
|
||||
p.Annotations[PodUpdateAnnotationName] = time.Now().Format(time.RFC3339Nano)
|
||||
|
||||
if err := r.Client.Update(ctx, p, &client.UpdateOptions{}); err != nil {
|
||||
if err := r.Update(ctx, p, &client.UpdateOptions{}); err != nil {
|
||||
r.Log.Error(err, "cannot update pod", "name", pod.Name, "namespace", pod.Namespace)
|
||||
|
||||
return err
|
||||
@@ -329,12 +329,12 @@ func (r Reconciler) getOperatorPods(ctx context.Context) (*corev1.PodList, error
|
||||
|
||||
leaderPod := &corev1.Pod{}
|
||||
|
||||
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: os.Getenv("NAMESPACE"), Name: hostname}, leaderPod); err != nil {
|
||||
if err := r.Get(ctx, types.NamespacedName{Namespace: os.Getenv("NAMESPACE"), Name: hostname}, leaderPod); err != nil {
|
||||
return nil, RunningInOutOfClusterModeError{}
|
||||
}
|
||||
|
||||
podList := &corev1.PodList{}
|
||||
if err := r.Client.List(ctx, podList, client.MatchingLabels(leaderPod.ObjectMeta.Labels)); err != nil {
|
||||
if err := r.List(ctx, podList, client.MatchingLabels(leaderPod.Labels)); err != nil {
|
||||
r.Log.Error(err, "cannot retrieve list of Capsule pods")
|
||||
|
||||
return nil, err
|
||||
|
||||
@@ -33,7 +33,7 @@ type SelectorAllowedListSpec struct {
|
||||
|
||||
func (in *SelectorAllowedListSpec) MatchSelectByName(obj client.Object) bool {
|
||||
if obj != nil {
|
||||
return in.AllowedListSpec.Match(obj.GetName()) || in.SelectorMatch(obj)
|
||||
return in.Match(obj.GetName()) || in.SelectorMatch(obj)
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@@ -58,6 +58,10 @@ func NewForbiddenError(key string, forbiddenSpec ForbiddenListSpec) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (f ForbiddenError) Error() string {
|
||||
return fmt.Sprintf("%s is forbidden for the current Tenant. %s", f.key, f.appendForbiddenError())
|
||||
}
|
||||
|
||||
//nolint:predeclared,revive
|
||||
func (f *ForbiddenError) appendForbiddenError() (append string) {
|
||||
append += "Forbidden are "
|
||||
@@ -75,10 +79,6 @@ func (f *ForbiddenError) appendForbiddenError() (append string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (f ForbiddenError) Error() string {
|
||||
return fmt.Sprintf("%s is forbidden for the current Tenant. %s", f.key, f.appendForbiddenError())
|
||||
}
|
||||
|
||||
func ValidateForbidden(metadata map[string]string, forbiddenList ForbiddenListSpec) error {
|
||||
if reflect.DeepEqual(ForbiddenListSpec{}, forbiddenList) {
|
||||
return nil
|
||||
|
||||
@@ -29,6 +29,18 @@ type CapsuleCA struct {
|
||||
key *rsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewCertificateAuthorityFromBytes(certBytes, keyBytes []byte) (*CapsuleCA, error) {
|
||||
cert, key, err := GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CapsuleCA{
|
||||
certificate: cert,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c CapsuleCA) CACertificatePem() (b *bytes.Buffer, err error) {
|
||||
var crtBytes []byte
|
||||
|
||||
@@ -132,18 +144,6 @@ func GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes []byte) (*x509.Ce
|
||||
return cert, key, nil
|
||||
}
|
||||
|
||||
func NewCertificateAuthorityFromBytes(certBytes, keyBytes []byte) (*CapsuleCA, error) {
|
||||
cert, key, err := GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CapsuleCA{
|
||||
certificate: cert,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
//nolint:nakedret
|
||||
func (c *CapsuleCA) GenerateCertificate(opts CertificateOptions) (certificatePem *bytes.Buffer, certificateKey *bytes.Buffer, err error) {
|
||||
var certPrivKey *rsa.PrivateKey
|
||||
|
||||
@@ -49,12 +49,12 @@ func (h *handler) OnUpdate(client client.Client, decoder admission.Decoder, reco
|
||||
func (h *handler) mutate(ctx context.Context, req admission.Request, c client.Client, decoder admission.Decoder, recorder record.EventRecorder) *admission.Response {
|
||||
var response *admission.Response
|
||||
|
||||
switch {
|
||||
case req.Resource == (metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}):
|
||||
switch req.Resource {
|
||||
case metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}:
|
||||
response = mutatePodDefaults(ctx, req, c, decoder, recorder, req.Namespace)
|
||||
case req.Resource == (metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}):
|
||||
case metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}:
|
||||
response = mutatePVCDefaults(ctx, req, c, decoder, recorder, req.Namespace)
|
||||
case req.Resource == (metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}) || req.Resource == (metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}):
|
||||
case metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}, metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}:
|
||||
response = mutateIngressDefaults(ctx, req, h.version, c, decoder, recorder, req.Namespace)
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ func (n NetworkingV1) HostnamePathsPairs() (pairs map[string]sets.Set[string]) {
|
||||
pairs[host] = sets.New[string]()
|
||||
}
|
||||
|
||||
if http := rule.IngressRuleValue.HTTP; http != nil {
|
||||
if http := rule.HTTP; http != nil {
|
||||
for _, path := range http.Paths {
|
||||
pairs[host].Insert(path.Path)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func (n NetworkingV1Beta1) HostnamePathsPairs() (pairs map[string]sets.Set[strin
|
||||
pairs[host] = sets.New[string]()
|
||||
}
|
||||
|
||||
if http := rule.IngressRuleValue.HTTP; http != nil {
|
||||
if http := rule.HTTP; http != nil {
|
||||
for _, path := range http.Paths {
|
||||
pairs[host].Insert(path.Path)
|
||||
}
|
||||
@@ -217,7 +217,7 @@ func (e Extension) HostnamePathsPairs() (pairs map[string]sets.Set[string]) {
|
||||
pairs[host] = sets.New[string]()
|
||||
}
|
||||
|
||||
if http := rule.IngressRuleValue.HTTP; http != nil {
|
||||
if http := rule.HTTP; http != nil {
|
||||
for _, path := range http.Paths {
|
||||
pairs[host].Insert(path.Path)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (r *freezedHandler) OnCreate(client client.Client, decoder admission.Decode
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
|
||||
for _, objectRef := range ns.OwnerReferences {
|
||||
if !capsuleutils.IsTenantOwnerReference(objectRef) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder admission.Decoder, reco
|
||||
// Extract Tenant from namespace
|
||||
e := fmt.Sprintf("namespace/%s can not be patched", ns.Name)
|
||||
|
||||
if label, ok := ns.ObjectMeta.Labels[ln]; ok {
|
||||
if label, ok := ns.Labels[ln]; ok {
|
||||
// retrieving the selected Tenant
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
if err = c.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {
|
||||
|
||||
@@ -49,7 +49,7 @@ func (r *prefixHandler) OnCreate(clt client.Client, decoder admission.Decoder, r
|
||||
if r.configuration.ForceTenantPrefix() {
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
|
||||
for _, or := range ns.ObjectMeta.OwnerReferences {
|
||||
for _, or := range ns.OwnerReferences {
|
||||
if !capsuleutils.IsTenantOwnerReference(or) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (r *quotaHandler) OnCreate(client client.Client, decoder admission.Decoder,
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
|
||||
for _, objectRef := range ns.OwnerReferences {
|
||||
if !capsuleutils.IsTenantOwnerReference(objectRef) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
|
||||
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
|
||||
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
|
||||
for _, objectRef := range ns.OwnerReferences {
|
||||
if !capsuleutils.IsTenantOwnerReference(objectRef) {
|
||||
continue
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
|
||||
}
|
||||
|
||||
if tnt.Spec.NamespaceOptions != nil {
|
||||
err := api.ValidateForbidden(ns.ObjectMeta.Annotations, tnt.Spec.NamespaceOptions.ForbiddenAnnotations)
|
||||
err := api.ValidateForbidden(ns.Annotations, tnt.Spec.NamespaceOptions.ForbiddenAnnotations)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "namespace annotations validation failed")
|
||||
recorder.Eventf(tnt, corev1.EventTypeWarning, api.ForbiddenAnnotationReason, err.Error())
|
||||
@@ -56,7 +56,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
|
||||
return &response
|
||||
}
|
||||
|
||||
err = api.ValidateForbidden(ns.ObjectMeta.Labels, tnt.Spec.NamespaceOptions.ForbiddenLabels)
|
||||
err = api.ValidateForbidden(ns.Labels, tnt.Spec.NamespaceOptions.ForbiddenLabels)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "namespace labels validation failed")
|
||||
recorder.Eventf(tnt, corev1.EventTypeWarning, api.ForbiddenLabelReason, err.Error())
|
||||
@@ -90,7 +90,7 @@ func (r *userMetadataHandler) OnUpdate(client client.Client, decoder admission.D
|
||||
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
|
||||
for _, objectRef := range newNs.ObjectMeta.OwnerReferences {
|
||||
for _, objectRef := range newNs.OwnerReferences {
|
||||
if !capsuleutils.IsTenantOwnerReference(objectRef) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func (r *handler) handle(ctx context.Context, req admission.Request, client clie
|
||||
allowed = true
|
||||
|
||||
np := &networkingv1.NetworkPolicy{}
|
||||
if err = client.Get(ctx, types.NamespacedName{Namespace: req.AdmissionRequest.Namespace, Name: req.AdmissionRequest.Name}, np); err != nil {
|
||||
if err = client.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: req.Name}, np); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
||||
@@ -42,42 +42,6 @@ func (r *userMetadataHandler) OnDelete(client.Client, admission.Decoder, record.
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userMetadataHandler) getForbiddenNodeLabels(node *corev1.Node) map[string]string {
|
||||
forbiddenNodeLabels := make(map[string]string)
|
||||
|
||||
forbiddenLabels := r.configuration.ForbiddenUserNodeLabels()
|
||||
|
||||
for label, value := range node.GetLabels() {
|
||||
var forbidden, matched bool
|
||||
forbidden = forbiddenLabels.ExactMatch(label)
|
||||
matched = forbiddenLabels.RegexMatch(label)
|
||||
|
||||
if forbidden || matched {
|
||||
forbiddenNodeLabels[label] = value
|
||||
}
|
||||
}
|
||||
|
||||
return forbiddenNodeLabels
|
||||
}
|
||||
|
||||
func (r *userMetadataHandler) getForbiddenNodeAnnotations(node *corev1.Node) map[string]string {
|
||||
forbiddenNodeAnnotations := make(map[string]string)
|
||||
|
||||
forbiddenAnnotations := r.configuration.ForbiddenUserNodeAnnotations()
|
||||
|
||||
for annotation, value := range node.GetAnnotations() {
|
||||
var forbidden, matched bool
|
||||
forbidden = forbiddenAnnotations.ExactMatch(annotation)
|
||||
matched = forbiddenAnnotations.RegexMatch(annotation)
|
||||
|
||||
if forbidden || matched {
|
||||
forbiddenNodeAnnotations[annotation] = value
|
||||
}
|
||||
}
|
||||
|
||||
return forbiddenNodeAnnotations
|
||||
}
|
||||
|
||||
func (r *userMetadataHandler) OnUpdate(_ client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
nodeWebhookSupported, _ := utils.NodeWebhookSupported(r.version)
|
||||
@@ -125,3 +89,39 @@ func (r *userMetadataHandler) OnUpdate(_ client.Client, decoder admission.Decode
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userMetadataHandler) getForbiddenNodeLabels(node *corev1.Node) map[string]string {
|
||||
forbiddenNodeLabels := make(map[string]string)
|
||||
|
||||
forbiddenLabels := r.configuration.ForbiddenUserNodeLabels()
|
||||
|
||||
for label, value := range node.GetLabels() {
|
||||
var forbidden, matched bool
|
||||
forbidden = forbiddenLabels.ExactMatch(label)
|
||||
matched = forbiddenLabels.RegexMatch(label)
|
||||
|
||||
if forbidden || matched {
|
||||
forbiddenNodeLabels[label] = value
|
||||
}
|
||||
}
|
||||
|
||||
return forbiddenNodeLabels
|
||||
}
|
||||
|
||||
func (r *userMetadataHandler) getForbiddenNodeAnnotations(node *corev1.Node) map[string]string {
|
||||
forbiddenNodeAnnotations := make(map[string]string)
|
||||
|
||||
forbiddenAnnotations := r.configuration.ForbiddenUserNodeAnnotations()
|
||||
|
||||
for annotation, value := range node.GetAnnotations() {
|
||||
var forbidden, matched bool
|
||||
forbidden = forbiddenAnnotations.ExactMatch(annotation)
|
||||
matched = forbiddenAnnotations.RegexMatch(annotation)
|
||||
|
||||
if forbidden || matched {
|
||||
forbiddenNodeAnnotations[annotation] = value
|
||||
}
|
||||
}
|
||||
|
||||
return forbiddenNodeAnnotations
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
|
||||
}
|
||||
// If we already had TenantName label on NS -> assign to it
|
||||
|
||||
if label, ok := ns.ObjectMeta.Labels[ln]; ok {
|
||||
if label, ok := ns.Labels[ln]; ok {
|
||||
// retrieving the selected Tenant
|
||||
tnt := &capsulev1beta2.Tenant{}
|
||||
if err = client.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {
|
||||
|
||||
@@ -64,14 +64,14 @@ func (h *containerRegistryHandler) validate(ctx context.Context, c client.Client
|
||||
if tnt.Spec.ContainerRegistries != nil {
|
||||
// Evaluate init containers
|
||||
for _, container := range pod.Spec.InitContainers {
|
||||
if response := h.VerifyContainerRegistry(recorder, req, container, tnt); response != nil {
|
||||
if response := h.verifyContainerRegistry(recorder, req, container, tnt); response != nil {
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate containers
|
||||
for _, container := range pod.Spec.Containers {
|
||||
if response := h.VerifyContainerRegistry(recorder, req, container, tnt); response != nil {
|
||||
if response := h.verifyContainerRegistry(recorder, req, container, tnt); response != nil {
|
||||
return response
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func (h *containerRegistryHandler) validate(ctx context.Context, c client.Client
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *containerRegistryHandler) VerifyContainerRegistry(recorder record.EventRecorder, req admission.Request, container corev1.Container, tnt capsulev1beta2.Tenant) *admission.Response {
|
||||
func (h *containerRegistryHandler) verifyContainerRegistry(recorder record.EventRecorder, req admission.Request, container corev1.Container, tnt capsulev1beta2.Tenant) *admission.Response {
|
||||
var valid, matched bool
|
||||
|
||||
reg := NewRegistry(container.Image)
|
||||
|
||||
@@ -49,6 +49,13 @@ func (r registry) Tag() string {
|
||||
return res
|
||||
}
|
||||
|
||||
type Registry interface {
|
||||
Registry() string
|
||||
Repository() string
|
||||
Image() string
|
||||
Tag() string
|
||||
}
|
||||
|
||||
func NewRegistry(value string) Registry {
|
||||
reg := make(registry)
|
||||
r := regexp.MustCompile(`((?P<registry>[a-zA-Z0-9-._]+(:\d+)?)\/)?(?P<repository>.*\/)?(?P<image>[a-zA-Z0-9-._]+:(?P<tag>[a-zA-Z0-9-._]+))?`)
|
||||
@@ -62,10 +69,3 @@ func NewRegistry(value string) Registry {
|
||||
|
||||
return reg
|
||||
}
|
||||
|
||||
type Registry interface {
|
||||
Registry() string
|
||||
Repository() string
|
||||
Image() string
|
||||
Tag() string
|
||||
}
|
||||
|
||||
@@ -24,19 +24,6 @@ func RuntimeClass() capsulewebhook.Handler {
|
||||
return &runtimeClass{}
|
||||
}
|
||||
|
||||
func (h *runtimeClass) class(ctx context.Context, c client.Client, name string) (client.Object, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
obj := &nodev1.RuntimeClass{}
|
||||
if err := c.Get(ctx, types.NamespacedName{Name: name}, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (h *runtimeClass) OnCreate(c client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.validate(ctx, c, decoder, recorder, req)
|
||||
@@ -55,6 +42,19 @@ func (h *runtimeClass) OnUpdate(client.Client, admission.Decoder, record.EventRe
|
||||
}
|
||||
}
|
||||
|
||||
func (h *runtimeClass) class(ctx context.Context, c client.Client, name string) (client.Object, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
obj := &nodev1.RuntimeClass{}
|
||||
if err := c.Get(ctx, types.NamespacedName{Name: name}, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (h *runtimeClass) validate(ctx context.Context, c client.Client, decoder admission.Decoder, recorder record.EventRecorder, req admission.Request) *admission.Response {
|
||||
pod := &corev1.Pod{}
|
||||
if err := decoder.Decode(req, pod); err != nil {
|
||||
|
||||
@@ -27,6 +27,24 @@ func Handler() capsulewebhook.Handler {
|
||||
return &handler{}
|
||||
}
|
||||
|
||||
func (r *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return r.handleService(ctx, client, decoder, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return r.handleService(ctx, client, decoder, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *handler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *handler) handleService(ctx context.Context, clt client.Client, decoder admission.Decoder, req admission.Request, recorder record.EventRecorder) *admission.Response {
|
||||
svc := &corev1.Service{}
|
||||
if err := decoder.Decode(req, svc); err != nil {
|
||||
@@ -124,21 +142,3 @@ func (r *handler) handleService(ctx context.Context, clt client.Client, decoder
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return r.handleService(ctx, client, decoder, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return r.handleService(ctx, client, decoder, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *handler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,6 @@ func ContainerRegistryRegexHandler() capsulewebhook.Handler {
|
||||
return &containerRegistryRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *containerRegistryRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.ContainerRegistries != nil && len(tenant.Spec.ContainerRegistries.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.ContainerRegistries.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile containerRegistries allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *containerRegistryRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
if err := h.validate(decoder, req); err != nil {
|
||||
@@ -65,3 +48,20 @@ func (h *containerRegistryRegexHandler) OnUpdate(_ client.Client, decoder admiss
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *containerRegistryRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.ContainerRegistries != nil && len(tenant.Spec.ContainerRegistries.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.ContainerRegistries.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile containerRegistries allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -30,6 +30,24 @@ func CordoningHandler(configuration configuration.Configuration) capsulewebhook.
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnCreate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder) *admission.Response {
|
||||
tntList := &capsulev1beta2.TenantList{}
|
||||
|
||||
@@ -54,21 +72,3 @@ func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client,
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnCreate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.cordonHandler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,22 +31,6 @@ func ResourceCounterHandler(client client.Client) capsulewebhook.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resourceCounterHandler) getTenantName(ctx context.Context, clt client.Client, req admission.Request) (string, error) {
|
||||
tntList := &capsulev1beta2.TenantList{}
|
||||
|
||||
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(tntList.Items) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return tntList.Items[0].GetName(), nil
|
||||
}
|
||||
|
||||
func (r *resourceCounterHandler) OnCreate(clt client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
var tntName string
|
||||
@@ -150,3 +134,19 @@ func (r *resourceCounterHandler) OnUpdate(client.Client, admission.Decoder, reco
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resourceCounterHandler) getTenantName(ctx context.Context, clt client.Client, req admission.Request) (string, error) {
|
||||
tntList := &capsulev1beta2.TenantList{}
|
||||
|
||||
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(tntList.Items) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return tntList.Items[0].GetName(), nil
|
||||
}
|
||||
|
||||
@@ -23,32 +23,6 @@ func ForbiddenAnnotationsRegexHandler() capsulewebhook.Handler {
|
||||
return &forbiddenAnnotationsRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *forbiddenAnnotationsRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.NamespaceOptions == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
annotationsToCheck := map[string]string{
|
||||
"labels": tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex,
|
||||
"annotations": tenant.Spec.NamespaceOptions.ForbiddenAnnotations.Regex,
|
||||
}
|
||||
|
||||
for scope, annotation := range annotationsToCheck {
|
||||
if _, err := regexp.Compile(tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex); err != nil {
|
||||
response := admission.Denied(fmt.Sprintf("unable to compile %s regex for forbidden %s", annotation, scope))
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *forbiddenAnnotationsRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
if err := h.validate(decoder, req); err != nil {
|
||||
@@ -74,3 +48,29 @@ func (h *forbiddenAnnotationsRegexHandler) OnUpdate(_ client.Client, decoder adm
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *forbiddenAnnotationsRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.NamespaceOptions == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
annotationsToCheck := map[string]string{
|
||||
"labels": tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex,
|
||||
"annotations": tenant.Spec.NamespaceOptions.ForbiddenAnnotations.Regex,
|
||||
}
|
||||
|
||||
for scope, annotation := range annotationsToCheck {
|
||||
if _, err := regexp.Compile(tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex); err != nil {
|
||||
response := admission.Denied(fmt.Sprintf("unable to compile %s regex for forbidden %s", annotation, scope))
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -23,23 +23,6 @@ func HostnameRegexHandler() capsulewebhook.Handler {
|
||||
return &hostnameRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *hostnameRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.IngressOptions.AllowedHostnames != nil && len(tenant.Spec.IngressOptions.AllowedHostnames.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedHostnames.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile allowedHostnames allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hostnameRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
if response := h.validate(decoder, req); response != nil {
|
||||
@@ -65,3 +48,20 @@ func (h *hostnameRegexHandler) OnUpdate(_ client.Client, decoder admission.Decod
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *hostnameRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.IngressOptions.AllowedHostnames != nil && len(tenant.Spec.IngressOptions.AllowedHostnames.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedHostnames.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile allowedHostnames allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -23,23 +23,6 @@ func IngressClassRegexHandler() capsulewebhook.Handler {
|
||||
return &ingressClassRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *ingressClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.IngressOptions.AllowedClasses != nil && len(tenant.Spec.IngressOptions.AllowedClasses.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedClasses.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile ingressClasses allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ingressClassRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
if response := h.validate(decoder, req); response != nil {
|
||||
@@ -65,3 +48,20 @@ func (h *ingressClassRegexHandler) OnUpdate(_ client.Client, decoder admission.D
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ingressClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.IngressOptions.AllowedClasses != nil && len(tenant.Spec.IngressOptions.AllowedClasses.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedClasses.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile ingressClasses allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (h *protectedHandler) OnDelete(clt client.Client, _ admission.Decoder, _ re
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
|
||||
if err := clt.Get(ctx, types.NamespacedName{Name: req.AdmissionRequest.Name}, tenant); err != nil {
|
||||
if err := clt.Get(ctx, types.NamespacedName{Name: req.Name}, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,24 @@ func RoleBindingRegexHandler() capsulewebhook.Handler {
|
||||
return &rbRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validate(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validate(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) validate(req admission.Request, decoder admission.Decoder) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
@@ -48,21 +66,3 @@ func (h *rbRegexHandler) validate(req admission.Request, decoder admission.Decod
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validate(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *rbRegexHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validate(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,24 @@ func ServiceAccountNameHandler() capsulewebhook.Handler {
|
||||
return &saNameHandler{}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validateServiceAccountName(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validateServiceAccountName(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) validateServiceAccountName(req admission.Request, decoder admission.Decoder) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
@@ -45,21 +63,3 @@ func (h *saNameHandler) validateServiceAccountName(req admission.Request, decode
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validateServiceAccountName(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *saNameHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
return h.validateServiceAccountName(req, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,6 @@ func StorageClassRegexHandler() capsulewebhook.Handler {
|
||||
return &storageClassRegexHandler{}
|
||||
}
|
||||
|
||||
func (h *storageClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.StorageClasses != nil && len(tenant.Spec.StorageClasses.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.StorageClasses.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile storageClasses allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *storageClassRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(_ context.Context, req admission.Request) *admission.Response {
|
||||
if err := h.validate(decoder, req); err != nil {
|
||||
@@ -65,3 +48,20 @@ func (h *storageClassRegexHandler) OnUpdate(_ client.Client, decoder admission.D
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *storageClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Spec.StorageClasses != nil && len(tenant.Spec.StorageClasses.Regex) > 0 {
|
||||
if _, err := regexp.Compile(tenant.Spec.StorageClasses.Regex); err != nil {
|
||||
response := admission.Denied("unable to compile storageClasses allowedRegex")
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,24 @@ func WriteOpsHandler() capsulewebhook.Handler {
|
||||
return &cordoningHandler{}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnCreate(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.handler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.handler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) handler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder) *admission.Response {
|
||||
tntList := &capsulev1beta2.TenantList{}
|
||||
|
||||
@@ -69,21 +87,3 @@ func (h *cordoningHandler) handler(ctx context.Context, clt client.Client, req a
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnCreate(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.handler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return h.handler(ctx, client, req, recorder)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user