Skip to content

Commit bb89ed0

Browse files
authored
DataInputSchema can only be a string and not an object (#196)
1 parent 66cd3e5 commit bb89ed0

13 files changed

+245
-37
lines changed

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ lint:
1414

1515
.PHONY: test
1616
coverage="false"
17+
1718
test: deepcopy buildergen
1819
make lint
1920
@go test ./...

builder/builder_test.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package builder
1717
import (
1818
"testing"
1919

20+
"github.com/pkg/errors"
2021
"github.com/stretchr/testify/assert"
2122

2223
"github.com/serverlessworkflow/sdk-go/v2/model"
@@ -58,7 +59,13 @@ func TestValidate(t *testing.T) {
5859
state2.End().Terminate(true)
5960
err = Validate(state2.Build())
6061
if assert.Error(t, err) {
61-
assert.Equal(t, "state.name is required", err.(val.WorkflowErrors)[0].Error())
62+
var workflowErrors val.WorkflowErrors
63+
if errors.As(err, &workflowErrors) {
64+
assert.Equal(t, "state.name is required", workflowErrors[0].Error())
65+
} else {
66+
// Handle other error types if necessary
67+
t.Errorf("Unexpected error: %v", err)
68+
}
6269
}
6370
}
6471

model/workflow.go

+40-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
package model
1616

1717
import (
18+
"bytes"
1819
"encoding/json"
20+
"errors"
1921

2022
"github.com/serverlessworkflow/sdk-go/v2/util"
2123
)
@@ -121,7 +123,7 @@ type BaseWorkflow struct {
121123
// qualities.
122124
// +optional
123125
Annotations []string `json:"annotations,omitempty"`
124-
// DataInputSchema URI of the JSON Schema used to validate the workflow data input
126+
// DataInputSchema URI or Object of the JSON Schema used to validate the workflow data input
125127
// +optional
126128
DataInputSchema *DataInputSchema `json:"dataInputSchema,omitempty"`
127129
// Serverless Workflow schema version
@@ -225,6 +227,7 @@ func (w *Workflow) UnmarshalJSON(data []byte) error {
225227
return nil
226228
}
227229

230+
// States ...
228231
// +kubebuilder:validation:MinItems=1
229232
type States []State
230233

@@ -510,7 +513,7 @@ type StateDataFilter struct {
510513
// +builder-gen:new-call=ApplyDefault
511514
type DataInputSchema struct {
512515
// +kubebuilder:validation:Required
513-
Schema string `json:"schema" validate:"required"`
516+
Schema *Object `json:"schema" validate:"required"`
514517
// +kubebuilder:validation:Required
515518
FailOnValidationErrors bool `json:"failOnValidationErrors"`
516519
}
@@ -520,7 +523,41 @@ type dataInputSchemaUnmarshal DataInputSchema
520523
// UnmarshalJSON implements json.Unmarshaler
521524
func (d *DataInputSchema) UnmarshalJSON(data []byte) error {
522525
d.ApplyDefault()
523-
return util.UnmarshalPrimitiveOrObject("dataInputSchema", data, &d.Schema, (*dataInputSchemaUnmarshal)(d))
526+
527+
// expected: data = "{\"key\": \"value\"}"
528+
// data = {"key": "value"}
529+
// data = "file://..."
530+
// data = { "schema": "{\"key\": \"value\"}", "failOnValidationErrors": true }
531+
// data = { "schema": {"key": "value"}, "failOnValidationErrors": true }
532+
// data = { "schema": "file://...", "failOnValidationErrors": true }
533+
534+
schemaString := ""
535+
err := util.UnmarshalPrimitiveOrObject("dataInputSchema", data, &schemaString, (*dataInputSchemaUnmarshal)(d))
536+
if err != nil {
537+
return err
538+
}
539+
540+
if d.Schema != nil {
541+
if d.Schema.Type == Map {
542+
return nil
543+
544+
} else if d.Schema.Type == String {
545+
schemaString = d.Schema.StringValue
546+
547+
} else {
548+
return errors.New("invalid dataInputSchema must be a string or object")
549+
}
550+
}
551+
552+
if schemaString != "" {
553+
data = []byte(schemaString)
554+
if bytes.TrimSpace(data)[0] != '{' {
555+
data = []byte("\"" + schemaString + "\"")
556+
}
557+
}
558+
559+
d.Schema = new(Object)
560+
return util.UnmarshalObjectOrFile("schema", data, &d.Schema)
524561
}
525562

526563
// ApplyDefault set the default values for Data Input Schema

model/workflow_test.go

+42-15
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,13 @@ func TestTransitionUnmarshalJSON(t *testing.T) {
498498
}
499499

500500
func TestDataInputSchemaUnmarshalJSON(t *testing.T) {
501+
502+
var schemaName Object
503+
err := json.Unmarshal([]byte("{\"key\": \"value\"}"), &schemaName)
504+
if !assert.NoError(t, err) {
505+
return
506+
}
507+
501508
type testCase struct {
502509
desp string
503510
data string
@@ -508,53 +515,73 @@ func TestDataInputSchemaUnmarshalJSON(t *testing.T) {
508515
testCases := []testCase{
509516
{
510517
desp: "string success",
511-
data: `"schema name"`,
518+
data: "{\"key\": \"value\"}",
512519
expect: DataInputSchema{
513-
Schema: "schema name",
520+
Schema: &schemaName,
514521
FailOnValidationErrors: true,
515522
},
516523
err: ``,
517524
},
518525
{
519-
desp: `object success`,
520-
data: `{"schema": "schema name"}`,
526+
desp: "string fail",
527+
data: "{\"key\": }",
521528
expect: DataInputSchema{
522-
Schema: "schema name",
529+
Schema: &schemaName,
530+
FailOnValidationErrors: true,
531+
},
532+
err: `invalid character '}' looking for beginning of value`,
533+
},
534+
{
535+
desp: `object success (without quotes)`,
536+
data: `{"key": "value"}`,
537+
expect: DataInputSchema{
538+
Schema: &schemaName,
523539
FailOnValidationErrors: true,
524540
},
525541
err: ``,
526542
},
527543
{
528-
desp: `object fail`,
529-
data: `{"schema": "schema name}`,
544+
desp: `schema object success`,
545+
data: `{"schema": "{\"key\": \"value\"}"}`,
530546
expect: DataInputSchema{
531-
Schema: "schema name",
547+
Schema: &schemaName,
532548
FailOnValidationErrors: true,
533549
},
534-
err: `unexpected end of JSON input`,
550+
err: ``,
535551
},
536552
{
537-
desp: `object key invalid`,
538-
data: `{"schema_invalid": "schema name"}`,
553+
desp: `schema object success (without quotes)`,
554+
data: `{"schema": {"key": "value"}}`,
539555
expect: DataInputSchema{
556+
Schema: &schemaName,
540557
FailOnValidationErrors: true,
541558
},
542559
err: ``,
543560
},
561+
{
562+
desp: `schema object fail`,
563+
data: `{"schema": "schema name}`,
564+
expect: DataInputSchema{
565+
Schema: &schemaName,
566+
FailOnValidationErrors: true,
567+
},
568+
err: `unexpected end of JSON input`,
569+
},
544570
}
545571
for _, tc := range testCases {
546572
t.Run(tc.desp, func(t *testing.T) {
547573
var v DataInputSchema
548574
err := json.Unmarshal([]byte(tc.data), &v)
549575

550576
if tc.err != "" {
551-
assert.Error(t, err)
552-
assert.Regexp(t, tc.err, err)
577+
assert.Error(t, err, tc.desp)
578+
assert.Regexp(t, tc.err, err, tc.desp)
553579
return
554580
}
555581

556-
assert.NoError(t, err)
557-
assert.Equal(t, tc.expect, v)
582+
assert.NoError(t, err, tc.desp)
583+
assert.Equal(t, tc.expect.Schema, v.Schema, tc.desp)
584+
assert.Equal(t, tc.expect.FailOnValidationErrors, v.FailOnValidationErrors, tc.desp)
558585
})
559586
}
560587
}

model/workflow_validator_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ func TestDataInputSchemaStructLevelValidation(t *testing.T) {
425425
action1 := buildActionByOperationState(operationState, "action 1")
426426
buildFunctionRef(baseWorkflow, action1, "function 1")
427427

428+
sampleSchema := FromString("sample schema")
429+
428430
testCases := []ValidationCase{
429431
{
430432
Desp: "empty DataInputSchema",
@@ -440,13 +442,14 @@ func TestDataInputSchemaStructLevelValidation(t *testing.T) {
440442
Model: func() Workflow {
441443
model := baseWorkflow.DeepCopy()
442444
model.DataInputSchema = &DataInputSchema{
443-
Schema: "sample schema",
445+
Schema: &sampleSchema,
444446
}
445447
return *model
446448
},
447449
},
448450
}
449451

452+
//fmt.Printf("%+v", testCases[0].Model)
450453
StructLevelValidationCtx(t, testCases)
451454
}
452455

model/zz_generated.buildergen.go

+36-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

model/zz_generated.deepcopy.go

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/parser_test.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package parser
1616

1717
import (
1818
"encoding/json"
19+
"fmt"
1920
"os"
2021
"path/filepath"
2122
"strings"
@@ -582,8 +583,25 @@ func TestFromFile(t *testing.T) {
582583
}, {
583584
"./testdata/workflows/dataInputSchemaValidation.yaml", func(t *testing.T, w *model.Workflow) {
584585
assert.NotNil(t, w.DataInputSchema)
585-
586-
assert.Equal(t, "sample schema", w.DataInputSchema.Schema)
586+
expected := model.DataInputSchema{}
587+
data, err := util.LoadExternalResource("file://testdata/datainputschema.json")
588+
err1 := util.UnmarshalObject("schema", data, &expected.Schema)
589+
assert.Nil(t, err)
590+
assert.Nil(t, err1)
591+
assert.Equal(t, expected.Schema, w.DataInputSchema.Schema)
592+
assert.Equal(t, false, w.DataInputSchema.FailOnValidationErrors)
593+
},
594+
}, {
595+
"./testdata/workflows/dataInputSchemaObject.json", func(t *testing.T, w *model.Workflow) {
596+
assert.NotNil(t, w.DataInputSchema)
597+
expected := model.Object{}
598+
err := json.Unmarshal([]byte("{\"title\": \"Hello World Schema\", \"properties\": {\"person\": "+
599+
"{\"type\": \"object\",\"properties\": {\"name\": {\"type\": \"string\"}},\"required\": "+
600+
"[\"name\"]}}, \"required\": [\"person\"]}"),
601+
&expected)
602+
fmt.Printf("err: %s\n", err)
603+
fmt.Printf("schema: %+v\n", expected)
604+
assert.Equal(t, &expected, w.DataInputSchema.Schema)
587605
assert.Equal(t, false, w.DataInputSchema.FailOnValidationErrors)
588606
},
589607
},

parser/testdata/datainputschema.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"title": "Hello World Schema",
3+
"properties": {
4+
"person": {
5+
"type": "object",
6+
"properties": {
7+
"name": {
8+
"type": "string"
9+
}
10+
},
11+
"required": [
12+
"name"
13+
]
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)