Skip to content

Commit 32ffaed

Browse files
pkg simpleschema: Add simple validation support
1 parent 876241c commit 32ffaed

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

pkg/simpleschema/markers.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@ const (
5050
MarkerTypeMinimum MarkerType = "minimum"
5151
// MarkerTypeMaximum represents the `maximum` marker.
5252
MarkerTypeMaximum MarkerType = "maximum"
53+
// MarkerTypeValidation represents the `validation` marker.
54+
MarkerTypeValidation MarkerType = "validation"
5355
// MarkerTypeEnum represents the `enum` marker.
5456
MarkerTypeEnum MarkerType = "enum"
5557
)
5658

5759
func markerTypeFromString(s string) (MarkerType, error) {
5860
switch MarkerType(s) {
5961
case MarkerTypeRequired, MarkerTypeDefault, MarkerTypeDescription,
60-
MarkerTypeMinimum, MarkerTypeMaximum, MarkerTypeEnum:
62+
MarkerTypeMinimum, MarkerTypeMaximum, MarkerTypeValidation, MarkerTypeEnum:
6163
return MarkerType(s), nil
6264
default:
6365
return "", fmt.Errorf("unknown marker type: %s", s)

pkg/simpleschema/transform.go

+11
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,17 @@ func (tf *transformer) applyMarkers(schema *extv1.JSONSchemaProps, markers []*Ma
219219
return fmt.Errorf("failed to parse maximum enum value: %w", err)
220220
}
221221
schema.Maximum = &val
222+
case MarkerTypeValidation:
223+
if marker.Value == "" {
224+
return fmt.Errorf("validation failed")
225+
}
226+
validation := []extv1.ValidationRule{
227+
{
228+
Rule: marker.Value,
229+
Message: "validation failed",
230+
},
231+
}
232+
schema.XValidations = validation
222233
case MarkerTypeEnum:
223234
var enumJSONValues []extv1.JSON
224235

pkg/simpleschema/transform_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,66 @@ func TestBuildOpenAPISchema(t *testing.T) {
360360
want: nil,
361361
wantErr: true,
362362
},
363+
{
364+
name: "Simple string validation",
365+
obj: map[string]interface{}{
366+
"name": `string | validation="self.name != 'invalid'"`,
367+
},
368+
want: &extv1.JSONSchemaProps{
369+
Type: "object",
370+
Properties: map[string]extv1.JSONSchemaProps{
371+
"name": {
372+
Type: "string",
373+
XValidations: []extv1.ValidationRule{
374+
{
375+
Rule: "self.name != 'invalid'",
376+
Message: "validation failed",
377+
},
378+
},
379+
},
380+
},
381+
},
382+
wantErr: false,
383+
},
384+
{
385+
name: "Multiple field validations",
386+
obj: map[string]interface{}{
387+
"age": `integer | validation="self.age >= 0 && self.age <= 120"`,
388+
"name": `string | validation="self.name.length() >= 3"`,
389+
},
390+
want: &extv1.JSONSchemaProps{
391+
Type: "object",
392+
Properties: map[string]extv1.JSONSchemaProps{
393+
"age": {
394+
Type: "integer",
395+
XValidations: []extv1.ValidationRule{
396+
{
397+
Rule: "self.age >= 0 && self.age <= 120",
398+
Message: "validation failed",
399+
},
400+
},
401+
},
402+
"name": {
403+
Type: "string",
404+
XValidations: []extv1.ValidationRule{
405+
{
406+
Rule: "self.name.length() >= 3",
407+
Message: "validation failed",
408+
},
409+
},
410+
},
411+
},
412+
},
413+
wantErr: false,
414+
},
415+
{
416+
name: "Empty validation",
417+
obj: map[string]interface{}{
418+
"age": `integer | validation=""`,
419+
},
420+
want: nil,
421+
wantErr: true,
422+
},
363423
}
364424

365425
for _, tt := range tests {

0 commit comments

Comments
 (0)