Skip to content

Commit

Permalink
Add deletionProtection for releases
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Bigler <nicolas.bigler@vshn.ch>
  • Loading branch information
TheBigLee committed Oct 16, 2024
1 parent 88cb04c commit 090be12
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 40 deletions.
91 changes: 51 additions & 40 deletions cmd/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ type controller struct {
metricsAddr, healthAddr string
leaderElect bool
enableWebhooks bool
enableAppcatWebhooks bool
enableQuotas bool
enableEventForwarding bool
certDir string
}

Expand All @@ -44,8 +46,10 @@ func init() {
ControllerCMD.Flags().BoolVar(&c.leaderElect, "leader-elect", false, "Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
ControllerCMD.Flags().BoolVar(&c.enableWebhooks, "webhooks", true, "Disable the validation webhooks.")
ControllerCMD.Flags().BoolVar(&c.enableAppcatWebhooks, "appcat-webhooks", true, "Disable the appcat validation webhooks")
ControllerCMD.Flags().StringVar(&c.certDir, "certdir", "/etc/webhook/certs", "Set the webhook certificate directory")
ControllerCMD.Flags().BoolVar(&c.enableQuotas, "quotas", false, "Enable the quota webhooks, is only active if webhooks is also true")
ControllerCMD.Flags().BoolVar(&c.enableEventForwarding, "event-forwarding", true, "Disable event-forwarding")
viper.AutomaticEnv()
if !viper.IsSet("PLANS_NAMESPACE") {
viper.Set("PLANS_NAMESPACE", "syn-appcat")
Expand Down Expand Up @@ -84,15 +88,17 @@ func (c *controller) executeController(cmd *cobra.Command, _ []string) error {
return err
}

events := &events.EventHandler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}
if c.enableEventForwarding {
events := &events.EventHandler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}

err = events.SetupWithManager(mgr)
err = events.SetupWithManager(mgr)

if err != nil {
return err
if err != nil {
return err
}
}

if c.enableWebhooks {
Expand All @@ -101,7 +107,7 @@ func (c *controller) executeController(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("PLANS_NAMEPSACE env variable needs to be set for quota support")
}

err := setupWebhooks(mgr, c.enableQuotas)
err := setupWebhooks(mgr, c.enableQuotas, c.enableAppcatWebhooks)
if err != nil {
return err
}
Expand All @@ -117,45 +123,50 @@ func (c *controller) executeController(cmd *cobra.Command, _ []string) error {
return mgr.Start(ctrl.SetupSignalHandler())
}

func setupWebhooks(mgr manager.Manager, withQuota bool) error {
err := webhooks.SetupPostgreSQLWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupRedisWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupMariaDBWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupMinioWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupNextcloudWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupKeycloakWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupNamespaceDeletionProtectionHandlerWithManager(mgr)
if err != nil {
return err
func setupWebhooks(mgr manager.Manager, withQuota bool, withAppcatWebhooks bool) error {
if withAppcatWebhooks {
err := webhooks.SetupPostgreSQLWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupRedisWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupMariaDBWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupMinioWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupNextcloudWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupKeycloakWebhookHandlerWithManager(mgr, withQuota)
if err != nil {
return err
}
err = webhooks.SetupXObjectbucketCDeletionProtectionHandlerWithManager(mgr)
if err != nil {
return err
}

err = webhooks.SetupObjectbucketDeletionProtectionHandlerWithManager(mgr)
if err != nil {
return err
}
}

err = webhooks.SetupXObjectbucketCDeletionProtectionHandlerWithManager(mgr)
err := webhooks.SetupReleaseDeletionProtectionHandlerWithManager(mgr)
if err != nil {
return err
}

err = webhooks.SetupObjectbucketDeletionProtectionHandlerWithManager(mgr)
err = webhooks.SetupNamespaceDeletionProtectionHandlerWithManager(mgr)
if err != nil {
return err
}

return webhooks.SetupPVCDeletionProtectionHandlerWithManager(mgr)
}
19 changes: 19 additions & 0 deletions config/controller/webhooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,25 @@ webhooks:
resources:
- persistentvolumeclaims
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-helm-crossplane-io-v1beta1-release
failurePolicy: Fail
name: releases.vshn.appcat.vshn.io
rules:
- apiGroups:
- helm.crossplane.io
apiVersions:
- v1beta1
operations:
- DELETE
resources:
- releases
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
Expand Down
72 changes: 72 additions & 0 deletions pkg/controller/webhooks/release.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package webhooks

import (
"context"
"fmt"

"github.com/go-logr/logr"
helmv1beta1 "github.com/vshn/appcat/v4/apis/helm/release/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

//+kubebuilder:webhook:verbs=delete,path=/validate-helm-crossplane-io-v1beta1-release,mutating=false,failurePolicy=fail,groups="helm.crossplane.io",resources=releases,versions=v1beta1,name=releases.vshn.appcat.vshn.io,sideEffects=None,admissionReviewVersions=v1

var _ webhook.CustomValidator = &ReleaseDeletionProtectionHandler{}

type ReleaseDeletionProtectionHandler struct {
client client.Client
log logr.Logger
}

// SetupNamespaceDeletionProtectionHandlerWithManager registers the validation webhook with the manager.
func SetupReleaseDeletionProtectionHandlerWithManager(mgr ctrl.Manager) error {

return ctrl.NewWebhookManagedBy(mgr).
For(&helmv1beta1.Release{}).
WithValidator(&ReleaseDeletionProtectionHandler{
client: mgr.GetClient(),
log: mgr.GetLogger().WithName("webhook").WithName("release"),
}).
Complete()
}

// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type
func (p *ReleaseDeletionProtectionHandler) ValidateCreate(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
// NOOP for now
return nil, nil
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (p *ReleaseDeletionProtectionHandler) ValidateUpdate(_ context.Context, _, _ runtime.Object) (admission.Warnings, error) {
// NOOP for now
return nil, nil
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (p *ReleaseDeletionProtectionHandler) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {

release, ok := obj.(client.Object)
if !ok {
return nil, fmt.Errorf("object is not valid")
}

l := p.log.WithValues("object", release.GetName(), "release", release.GetNamespace(), "GVK", release.GetObjectKind().GroupVersionKind().String())

compInfo, err := checkManagedObject(ctx, release, p.client, l)
if err != nil {
return nil, err
}

if compInfo.Exists {
l.Info("Blocking deletion of release", "parent", compInfo.Name)
return nil, fmt.Errorf(protectedMessage, "release", compInfo.Name)
}

l.Info("Allowing deletion of release", "parent", compInfo.Name)

return nil, nil
}

0 comments on commit 090be12

Please sign in to comment.