Skip to content
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
}