Skip to content

Create RayCluster ValidatingWebhook #524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ resources:
version: v1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"
4 changes: 2 additions & 2 deletions config/openshift/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace: openshift-operators
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
namePrefix: codeflare-operator-

# Labels to add to all resources and selectors.
commonLabels:
Expand All @@ -19,4 +18,5 @@ bases:

patches:
- path: manager_webhook_patch.yaml
- path: webhookcainjection_patch.yaml
- path: webhookcainjection_mpatch.yaml
- path: webhookcainjection_vpatch.yaml
7 changes: 7 additions & 0 deletions config/openshift/webhookcainjection_vpatch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This patch add annotation to admission webhook config
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration
annotations:
service.beta.openshift.io/inject-cabundle: "true"
2 changes: 2 additions & 0 deletions config/webhook/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
namePrefix: codeflare-operator-

resources:
- manifests.yaml
- service.yaml
Expand Down
27 changes: 27 additions & 0 deletions config/webhook/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,30 @@ webhooks:
resources:
- rayclusters
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-ray-io-v1-raycluster
failurePolicy: Fail
name: vraycluster.kb.io
rules:
- apiGroups:
- ray.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- rayclusters
sideEffects: None
39 changes: 39 additions & 0 deletions pkg/controllers/raycluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import (

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/utils/pointer"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

"github.com/project-codeflare/codeflare-operator/pkg/config"
)
Expand All @@ -40,16 +42,24 @@ func SetupRayClusterWebhookWithManager(mgr ctrl.Manager, cfg *config.KubeRayConf
WithDefaulter(&rayClusterDefaulter{
Config: cfg,
}).
WithValidator(&rayClusterWebhook{
Config: cfg,
}).
Complete()
}

// +kubebuilder:webhook:path=/mutate-ray-io-v1-raycluster,mutating=true,failurePolicy=fail,sideEffects=None,groups=ray.io,resources=rayclusters,verbs=create;update,versions=v1,name=mraycluster.kb.io,admissionReviewVersions=v1
// +kubebuilder:webhook:path=/validate-ray-io-v1-raycluster,mutating=false,failurePolicy=fail,sideEffects=None,groups=ray.io,resources=rayclusters,verbs=create;update,versions=v1,name=vraycluster.kb.io,admissionReviewVersions=v1

type rayClusterDefaulter struct {
Config *config.KubeRayConfiguration
}
type rayClusterWebhook struct {
Config *config.KubeRayConfiguration
}

var _ webhook.CustomDefaulter = &rayClusterDefaulter{}
var _ webhook.CustomValidator = &rayClusterWebhook{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *rayClusterDefaulter) Default(ctx context.Context, obj runtime.Object) error {
Expand Down Expand Up @@ -132,3 +142,32 @@ func (r *rayClusterDefaulter) Default(ctx context.Context, obj runtime.Object) e

return nil
}

func (v *rayClusterWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
raycluster := obj.(*rayv1.RayCluster)
var warnings admission.Warnings
var allErrors field.ErrorList
specPath := field.NewPath("spec")

if pointer.BoolDeref(raycluster.Spec.HeadGroupSpec.EnableIngress, false) {
rayclusterlog.Info("Creating RayCluster resources with EnableIngress set to true or unspecified is not allowed")
allErrors = append(allErrors, field.Invalid(specPath.Child("headGroupSpec").Child("enableIngress"), raycluster.Spec.HeadGroupSpec.EnableIngress, "creating RayCluster resources with EnableIngress set to true or unspecified is not allowed"))
}

return warnings, allErrors.ToAggregate()
}

func (v *rayClusterWebhook) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
newRayCluster := newObj.(*rayv1.RayCluster)
if !newRayCluster.DeletionTimestamp.IsZero() {
// Object is being deleted, skip validations
return nil, nil
}
warnings, err := v.ValidateCreate(ctx, newRayCluster)
return warnings, err
}

func (v *rayClusterWebhook) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
// Optional: Add delete validation logic here
return nil, nil
}