mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-14 10:00:02 +00:00
feat!: write permissions (#937)
* fix: decoding object only if requested Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat(api): limiting write permissions Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat: write permissions handlers, routes, and controller Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * docs: write permissions Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> --------- Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
This commit is contained in:
committed by
GitHub
parent
2b707423ff
commit
de459fb5da
@@ -36,7 +36,9 @@ func (r *KubernetesDeploymentResource) isStatusEqual(tenantControlPlane *kamajiv
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) ShouldStatusBeUpdated(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return !r.isStatusEqual(tenantControlPlane) || tenantControlPlane.Spec.Kubernetes.Version != tenantControlPlane.Status.Kubernetes.Version.Version
|
||||
return !r.isStatusEqual(tenantControlPlane) ||
|
||||
tenantControlPlane.Spec.Kubernetes.Version != tenantControlPlane.Status.Kubernetes.Version.Version ||
|
||||
*r.computeStatus(tenantControlPlane) != ptr.Deref(tenantControlPlane.Status.Kubernetes.Version.Status, kamajiv1alpha1.VersionUnknown)
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) ShouldCleanup(*kamajiv1alpha1.TenantControlPlane) bool {
|
||||
@@ -78,19 +80,29 @@ func (r *KubernetesDeploymentResource) GetName() string {
|
||||
return "deployment"
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *KubernetesDeploymentResource) computeStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) *kamajiv1alpha1.KubernetesVersionStatus {
|
||||
switch {
|
||||
case ptr.Deref(tenantControlPlane.Spec.ControlPlane.Deployment.Replicas, 2) == 0:
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionSleeping
|
||||
case !r.isProgressingUpgrade():
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionReady
|
||||
tenantControlPlane.Status.Kubernetes.Version.Version = tenantControlPlane.Spec.Kubernetes.Version
|
||||
case r.isUpgrading(tenantControlPlane):
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionUpgrading
|
||||
case r.isProvisioning(tenantControlPlane):
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionProvisioning
|
||||
return &kamajiv1alpha1.VersionSleeping
|
||||
case r.isNotReady():
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionNotReady
|
||||
return &kamajiv1alpha1.VersionNotReady
|
||||
case tenantControlPlane.Spec.WritePermissions.HasAnyLimitation():
|
||||
return &kamajiv1alpha1.VersionWriteLimited
|
||||
case !r.isProgressingUpgrade():
|
||||
return &kamajiv1alpha1.VersionReady
|
||||
case r.isUpgrading(tenantControlPlane):
|
||||
return &kamajiv1alpha1.VersionUpgrading
|
||||
case r.isProvisioning(tenantControlPlane):
|
||||
return &kamajiv1alpha1.VersionProvisioning
|
||||
default:
|
||||
return &kamajiv1alpha1.VersionUnknown
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
tenantControlPlane.Status.Kubernetes.Version.Status = r.computeStatus(tenantControlPlane)
|
||||
if *tenantControlPlane.Status.Kubernetes.Version.Status == kamajiv1alpha1.VersionReady {
|
||||
tenantControlPlane.Status.Kubernetes.Version.Version = tenantControlPlane.Spec.Kubernetes.Version
|
||||
}
|
||||
|
||||
tenantControlPlane.Status.Kubernetes.Deployment = kamajiv1alpha1.KubernetesDeploymentStatus{
|
||||
|
||||
@@ -25,18 +25,21 @@ type handlersChainer struct {
|
||||
//nolint:gocognit
|
||||
func (h handlersChainer) Handler(object runtime.Object, routeHandlers ...handlers.Handler) admission.HandlerFunc {
|
||||
return func(ctx context.Context, req admission.Request) admission.Response {
|
||||
decodedObj, oldDecodedObj := object.DeepCopyObject(), object.DeepCopyObject()
|
||||
var decodedObj, oldDecodedObj runtime.Object
|
||||
if object != nil {
|
||||
decodedObj, oldDecodedObj = object.DeepCopyObject(), object.DeepCopyObject()
|
||||
|
||||
switch req.Operation {
|
||||
case admissionv1.Delete:
|
||||
// When deleting the OldObject struct field contains the object being deleted:
|
||||
// https://github.com/kubernetes/kubernetes/pull/76346
|
||||
if err := h.decoder.DecodeRaw(req.OldObject, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode deleted object into %T", object)))
|
||||
}
|
||||
default:
|
||||
if err := h.decoder.Decode(req, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode into %T", object)))
|
||||
switch req.Operation {
|
||||
case admissionv1.Delete:
|
||||
// When deleting the OldObject struct field contains the object being deleted:
|
||||
// https://github.com/kubernetes/kubernetes/pull/76346
|
||||
if err := h.decoder.DecodeRaw(req.OldObject, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode deleted object into %T", object)))
|
||||
}
|
||||
default:
|
||||
if err := h.decoder.Decode(req, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode into %T", object)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
32
internal/webhook/handlers/write_permission.go
Normal file
32
internal/webhook/handlers/write_permission.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
)
|
||||
|
||||
type WritePermission struct{}
|
||||
|
||||
func (f WritePermission) OnCreate(runtime.Object) AdmissionResponse {
|
||||
return f.response
|
||||
}
|
||||
|
||||
func (f WritePermission) OnDelete(runtime.Object) AdmissionResponse {
|
||||
return f.response
|
||||
}
|
||||
|
||||
func (f WritePermission) OnUpdate(runtime.Object, runtime.Object) AdmissionResponse {
|
||||
return f.response
|
||||
}
|
||||
|
||||
func (f WritePermission) response(context.Context, admission.Request) ([]jsonpatch.JsonPatchOperation, error) {
|
||||
return nil, fmt.Errorf("the current Control Plane has limited write permissions, current changes are blocked: " +
|
||||
"removing the webhook may lead to an inconsistent state upon its completion")
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -15,5 +14,5 @@ func (t TenantControlPlaneMigrate) GetPath() string {
|
||||
}
|
||||
|
||||
func (t TenantControlPlaneMigrate) GetObject() runtime.Object {
|
||||
return &corev1.Namespace{}
|
||||
return nil
|
||||
}
|
||||
|
||||
18
internal/webhook/routes/tcp_writepermission.go
Normal file
18
internal/webhook/routes/tcp_writepermission.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
type TenantControlPlaneWritePermission struct{}
|
||||
|
||||
func (t TenantControlPlaneWritePermission) GetPath() string {
|
||||
return "/write-permission"
|
||||
}
|
||||
|
||||
func (t TenantControlPlaneWritePermission) GetObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user