Skip to content

Commit 362e705

Browse files
committed
feat(webhook): dataset validation rules + tests
1 parent a3ea57c commit 362e705

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

pkg/webhook/handler/validating/validating_handler.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"net/http"
77

8+
v1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
89
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
910
)
1011

@@ -18,7 +19,35 @@ func NewValidatingHandler() *ValidatingHandler {
1819
}
1920

2021
func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
21-
// Generic validation: ensure object contains metadata.name
22+
// Try to decode into a known type (Dataset) when possible
23+
var ds v1alpha1.Dataset
24+
if h.decoder != nil {
25+
if err := h.decoder.Decode(req, &ds); err == nil {
26+
// Perform Dataset-specific validations
27+
// Require either Mounts or Runtimes to be present
28+
if len(ds.Spec.Mounts) == 0 && len(ds.Spec.Runtimes) == 0 {
29+
return admission.Denied("dataset.spec must contain at least one mount or runtime")
30+
}
31+
32+
// Validate mounts
33+
for _, m := range ds.Spec.Mounts {
34+
if len(m.MountPoint) < 5 {
35+
return admission.Denied("mount.mountPoint must be at least 5 characters")
36+
}
37+
}
38+
39+
// Validate runtimes
40+
for _, r := range ds.Spec.Runtimes {
41+
if r.Name == "" || r.Namespace == "" {
42+
return admission.Denied("runtime entries must include name and namespace")
43+
}
44+
}
45+
46+
return admission.Allowed("dataset validation passed")
47+
}
48+
}
49+
50+
// Fallback generic validation: ensure object contains metadata.name
2251
var obj map[string]interface{}
2352
if err := json.Unmarshal(req.Object.Raw, &obj); err != nil {
2453
return admission.Errored(http.StatusBadRequest, err)
@@ -33,7 +62,6 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a
3362
return admission.Denied("metadata.name is required")
3463
}
3564

36-
// Passed basic validation
3765
return admission.Allowed("validation passed")
3866
}
3967

pkg/webhook/handler/validating/validating_handler_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import (
44
"context"
55
"testing"
66

7+
"encoding/json"
8+
79
"github.com/stretchr/testify/assert"
810
admissionv1 "k8s.io/api/admission/v1"
911
"k8s.io/apimachinery/pkg/runtime"
1012
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
13+
v1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
1114
)
1215

1316
func TestValidatingHandler_Basic(t *testing.T) {
@@ -30,3 +33,42 @@ func TestValidatingHandler_Basic(t *testing.T) {
3033
assert.False(t, resp.Allowed)
3134
assert.Contains(t, resp.Result.Message, "metadata.name is required")
3235
}
36+
37+
func TestValidatingHandler_Dataset(t *testing.T) {
38+
h := NewValidatingHandler()
39+
// prepare decoder with scheme so that typed decoding works
40+
scheme := runtime.NewScheme()
41+
err := v1alpha1.AddToScheme(scheme)
42+
if err != nil {
43+
t.Fatalf("failed to add v1alpha1 to scheme: %v", err)
44+
}
45+
dec := admission.NewDecoder(scheme)
46+
h.InjectDecoder(dec)
47+
48+
// Dataset missing mounts and runtimes -> denied
49+
ds := &v1alpha1.Dataset{}
50+
raw, _ := json.Marshal(ds)
51+
req := admission.Request{
52+
AdmissionRequest: admissionv1.AdmissionRequest{
53+
Object: runtime.RawExtension{Raw: raw},
54+
},
55+
}
56+
resp := h.Handle(context.Background(), req)
57+
assert.False(t, resp.Allowed)
58+
59+
// Dataset with a valid mount -> allowed
60+
ds = &v1alpha1.Dataset{}
61+
ds.Spec.Mounts = []v1alpha1.Mount{{MountPoint: "/data"}}
62+
raw, _ = json.Marshal(ds)
63+
req.AdmissionRequest.Object.Raw = raw
64+
resp = h.Handle(context.Background(), req)
65+
assert.True(t, resp.Allowed)
66+
67+
// Dataset with invalid mount (too short) -> denied
68+
ds = &v1alpha1.Dataset{}
69+
ds.Spec.Mounts = []v1alpha1.Mount{{MountPoint: "abc"}}
70+
raw, _ = json.Marshal(ds)
71+
req.AdmissionRequest.Object.Raw = raw
72+
resp = h.Handle(context.Background(), req)
73+
assert.False(t, resp.Allowed)
74+
}

0 commit comments

Comments
 (0)