From fdf916b7f9fb5512d234fc9c344c296d0a1c7204 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Thu, 1 Apr 2021 11:11:20 +0200 Subject: [PATCH] Rework/simplify expr.Vars handling --- automation/automation/iterators.go | 32 ++-- automation/types/expr.go | 2 +- automation/types/expr_test.go | 28 ++-- compose/automation/expr_types_test.go | 8 +- compose/automation/records_handler.go | 11 +- compose/service/event/events.gen.go | 138 +++++++++++------ pkg/codegen/assets/events.gen.go.tpl | 20 +-- pkg/expr/expr_test.go | 20 +-- pkg/expr/expr_types.gen.go | 12 +- pkg/expr/expr_types.go | 15 +- pkg/expr/expr_types.yaml | 2 +- pkg/expr/expr_types_test.go | 26 ++-- pkg/expr/{func_gen.go => func_generic.go} | 2 +- ...{func_gen_test.go => func_generic_test.go} | 0 pkg/expr/parser.go | 4 +- pkg/expr/vars.go | 83 ++++++---- pkg/expr/vars_test.go | 65 ++++---- pkg/wfexec/gateways_test.go | 7 +- pkg/wfexec/session.go | 7 +- pkg/wfexec/session_test.go | 49 +++--- system/automation/expr_types.go | 17 +- system/automation/expr_types_test.go | 9 +- system/automation/roles_handler.go | 10 +- system/automation/templates_handler.gen.go | 2 +- system/automation/templates_handler.go | 17 +- system/automation/templates_handler.yaml | 2 +- system/automation/users_handler.go | 10 +- system/service/event/events.gen.go | 146 +++++++++++------- tests/automation/trigger_test.go | 2 +- tests/automation/workflow_test.go | 14 +- 30 files changed, 436 insertions(+), 324 deletions(-) rename pkg/expr/{func_gen.go => func_generic.go} (97%) rename pkg/expr/{func_gen_test.go => func_generic_test.go} (100%) diff --git a/automation/automation/iterators.go b/automation/automation/iterators.go index f7e3eb876..583821d44 100644 --- a/automation/automation/iterators.go +++ b/automation/automation/iterators.go @@ -24,14 +24,12 @@ func (i *sequenceIterator) more() bool { func (i *sequenceIterator) Start(context.Context, *Vars) error { return nil } func (i *sequenceIterator) Next(context.Context, *Vars) (*Vars, error) { - scope := RVars{ - "counter": Must(NewInteger(i.counter)), - "isFirst": Must(NewBoolean(i.counter == i.cFirst)), - "isLast": Must(NewBoolean(!i.more())), - }.Vars() - + out := &Vars{} + out.Set("counter", i.counter) + out.Set("isFirst", i.counter == i.cFirst) + out.Set("isLast", !i.more()) i.counter = i.counter + i.cStep - return scope, nil + return out, nil } type ( @@ -66,19 +64,10 @@ func (i *collectionIterator) More(context.Context, *Vars) (bool, error) { func (i *collectionIterator) Start(context.Context, *Vars) error { i.ptr = 0; return nil } func (i *collectionIterator) Next(context.Context, *Vars) (out *Vars, err error) { - var item TypedValue - switch c := i.set[i.ptr].(type) { - case TypedValue: - item = c - default: - if item, err = Typify(c); err != nil { - return - } - } - + out = &Vars{} + out.Set("line", i.set[i.ptr]) i.ptr++ - - return RVars{"item": item}.Vars(), nil + return out, nil } type ( @@ -101,6 +90,7 @@ func (i *lineIterator) Next(context.Context, *Vars) (*Vars, error) { return nil, err } - return RVars{"line": Must(NewString(i.s.Text()))}.Vars(), nil - + out := &Vars{} + out.Set("line", i.s.Text()) + return out, nil } diff --git a/automation/types/expr.go b/automation/types/expr.go index 613e232ab..1af59a892 100644 --- a/automation/types/expr.go +++ b/automation/types/expr.go @@ -111,7 +111,7 @@ func (set ExprSet) Eval(ctx context.Context, in *expr.Vars) (*expr.Vars, error) scope = (&expr.Vars{}).Merge(in) // Prepare output scope - out = &expr.Vars{} + out, _ = expr.NewVars(nil) // Untyped evaluation result value interface{} diff --git a/automation/types/expr_test.go b/automation/types/expr_test.go index 92d1ae7c2..856a3d33a 100644 --- a/automation/types/expr_test.go +++ b/automation/types/expr_test.go @@ -14,25 +14,25 @@ func TestExprSet_Eval(t *testing.T) { cc = []struct { name string set ExprSet - input RVars - output RVars + input map[string]interface{} + output map[string]interface{} err string }{ { name: "empty", set: ExprSet{}, - output: nil, + output: make(map[string]interface{}), }, { name: "constant assignment", set: ExprSet{&Expr{Target: "foo", Expr: `"bar"`}}, - output: RVars{"foo": Must(NewString("bar"))}, + output: map[string]interface{}{"foo": Must(NewString("bar"))}, }, { name: "vars with path", set: ExprSet{&Expr{Target: "l1.l2", Expr: `"bar"`}}, - input: RVars{"l1": RVars{}.Vars()}, - output: RVars{"l1": RVars{"l2": Must(Typify("bar"))}.Vars()}, + input: map[string]interface{}{"l1": map[string]interface{}{}}, + output: map[string]interface{}{"l1": map[string]interface{}{"l2": Must(Typify("bar"))}}, }, { name: "copy vars with same types", @@ -40,7 +40,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "aa", Value: "vv", typ: &String{}}, &Expr{Target: "bb", Source: "aa", typ: &String{}}, }, - output: RVars{ + output: map[string]interface{}{ "aa": Must(NewString("vv")), "bb": Must(NewString("vv")), }, @@ -51,7 +51,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "aa", Value: "should be always String", typ: &String{}}, &Expr{Target: "bb", Source: "aa"}, }, - output: RVars{ + output: map[string]interface{}{ "aa": Must(NewString("should be always String")), "bb": Must(NewString("should be always String")), }, @@ -62,7 +62,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "aa", Value: "42", typ: &String{}}, &Expr{Target: "bb", Source: "aa", typ: &Integer{}}, }, - output: RVars{ + output: map[string]interface{}{ "aa": Must(NewString("42")), "bb": Must(NewInteger(42)), }, @@ -81,7 +81,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "a", typ: &KV{}}, &Expr{Target: "a.b", Value: "c", typ: &String{}}, }, - output: RVars{ + output: map[string]interface{}{ "a": Must(NewKV(map[string]string{ "b": "c", })), @@ -93,7 +93,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "arr", typ: &Array{}, Expr: `[]`}, &Expr{Target: "arr", typ: &Array{}, Expr: `push(arr, "foo")`}, }, - output: RVars{ + output: map[string]interface{}{ "arr": Must(NewArray([]string{ "foo", })), @@ -105,7 +105,7 @@ func TestExprSet_Eval(t *testing.T) { &Expr{Target: "arr", typ: &Array{}, Expr: `[]`}, &Expr{Target: "arr", typ: &Any{}, Expr: `push(arr, "foo")`}, }, - output: RVars{ + output: map[string]interface{}{ "arr": Must(NewArray([]string{ "foo", })), @@ -116,7 +116,7 @@ func TestExprSet_Eval(t *testing.T) { set: ExprSet{ &Expr{Target: "arr", typ: &Array{}, Expr: `push([], "foo")`}, }, - output: RVars{ + output: map[string]interface{}{ "arr": Must(NewArray([]TypedValue{ Must(Typify("foo")), })), @@ -153,7 +153,7 @@ func TestExprSet_Eval(t *testing.T) { return } - req.Equal(c.output.Vars(), output) + req.Equal(Must(Typify(c.output)), output) }) } } diff --git a/compose/automation/expr_types_test.go b/compose/automation/expr_types_test.go index 2ca0cb6ba..f0bd01c59 100644 --- a/compose/automation/expr_types_test.go +++ b/compose/automation/expr_types_test.go @@ -77,11 +77,11 @@ func TestRecordFieldValuesAccess(t *testing.T) { &types.RecordValue{Name: "ref2", Value: "", Ref: 2, Place: 0}, }} - tval = &ComposeRecord{value: raw} - scope = expr.RVars{ + tval = &ComposeRecord{value: raw} + scope, _ = expr.NewVars(map[string]interface{}{ "rec": tval, "nil": nil, - }.Vars() + }) ) // @todo see not above re. back-ref to record @@ -121,6 +121,8 @@ func TestRecordFieldValuesAccess(t *testing.T) { expr string }{ {false, `nil`}, + {true, `rec`}, + {true, `rec.values`}, // interaction with set values {true, `rec.values.s1 == "sVal1"`}, diff --git a/compose/automation/records_handler.go b/compose/automation/records_handler.go index 0e529cecc..5ef8c3b08 100644 --- a/compose/automation/records_handler.go +++ b/compose/automation/records_handler.go @@ -318,12 +318,11 @@ func (i *recordSetIterator) More(context.Context, *Vars) (bool, error) { func (i *recordSetIterator) Start(context.Context, *Vars) error { i.ptr = 0; return nil } func (i *recordSetIterator) Next(context.Context, *Vars) (*Vars, error) { - out := RVars{ - "record": Must(NewComposeRecord(i.set[i.ptr])), - "index": Must(NewUnsignedInteger(i.ptr)), - "total": Must(NewUnsignedInteger(i.filter.Total)), - } + out := &Vars{} + out.Set("record", Must(NewComposeRecord(i.set[i.ptr]))) + out.Set("index", i.ptr) + out.Set("total", i.filter.Total) i.ptr++ - return out.Vars(), nil + return out, nil } diff --git a/compose/service/event/events.gen.go b/compose/service/event/events.gen.go index b8bd41ba9..0ec99eb1a 100644 --- a/compose/service/event/events.gen.go +++ b/compose/service/event/events.gen.go @@ -425,14 +425,14 @@ func (res composeBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res composeBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res composeBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -849,26 +849,38 @@ func (res moduleBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res moduleBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res moduleBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["module"], err = automation.NewComposeModule(res.module); err != nil { - return nil, err + if v, err = automation.NewComposeModule(res.module); err == nil { + err = out.Set("module", v) } - if rvars["oldModule"], err = automation.NewComposeModule(res.oldModule); err != nil { - return nil, err + if err != nil { + return } - if rvars["namespace"], err = automation.NewComposeNamespace(res.namespace); err != nil { - return nil, err + if v, err = automation.NewComposeModule(res.oldModule); err == nil { + err = out.Set("oldModule", v) + } + + if err != nil { + return + } + + if v, err = automation.NewComposeNamespace(res.namespace); err == nil { + err = out.Set("namespace", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -1277,22 +1289,30 @@ func (res namespaceBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res namespaceBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res namespaceBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["namespace"], err = automation.NewComposeNamespace(res.namespace); err != nil { - return nil, err + if v, err = automation.NewComposeNamespace(res.namespace); err == nil { + err = out.Set("namespace", v) } - if rvars["oldNamespace"], err = automation.NewComposeNamespace(res.oldNamespace); err != nil { - return nil, err + if err != nil { + return + } + + if v, err = automation.NewComposeNamespace(res.oldNamespace); err == nil { + err = out.Set("oldNamespace", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -1737,22 +1757,26 @@ func (res pageBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res pageBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res pageBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for *types.Page // Could not found expression-type counterpart for *types.Page - if rvars["namespace"], err = automation.NewComposeNamespace(res.namespace); err != nil { - return nil, err + if v, err = automation.NewComposeNamespace(res.namespace); err == nil { + err = out.Set("namespace", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -2330,34 +2354,54 @@ func (res recordBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res recordBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res recordBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["record"], err = automation.NewComposeRecord(res.record); err != nil { - return nil, err + if v, err = automation.NewComposeRecord(res.record); err == nil { + err = out.Set("record", v) } - if rvars["oldRecord"], err = automation.NewComposeRecord(res.oldRecord); err != nil { - return nil, err + if err != nil { + return } - if rvars["module"], err = automation.NewComposeModule(res.module); err != nil { - return nil, err + if v, err = automation.NewComposeRecord(res.oldRecord); err == nil { + err = out.Set("oldRecord", v) } - if rvars["namespace"], err = automation.NewComposeNamespace(res.namespace); err != nil { - return nil, err + if err != nil { + return } - if rvars["recordValueErrors"], err = automation.NewComposeRecordValueErrorSet(res.recordValueErrors); err != nil { - return nil, err + if v, err = automation.NewComposeModule(res.module); err == nil { + err = out.Set("module", v) + } + + if err != nil { + return + } + + if v, err = automation.NewComposeNamespace(res.namespace); err == nil { + err = out.Set("namespace", v) + } + + if err != nil { + return + } + + if v, err = automation.NewComposeRecordValueErrorSet(res.recordValueErrors); err == nil { + err = out.Set("recordValueErrors", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props diff --git a/pkg/codegen/assets/events.gen.go.tpl b/pkg/codegen/assets/events.gen.go.tpl index 963919765..196924423 100644 --- a/pkg/codegen/assets/events.gen.go.tpl +++ b/pkg/codegen/assets/events.gen.go.tpl @@ -147,25 +147,27 @@ func (res {{ camelCase .ResourceIdent "base" }}) Encode() (args map[string][]byt } // Encode internal data to be passed as event params & arguments to workflow -func (res {{ camelCase .ResourceIdent "base" }}) EncodeVars() (vars *expr.Vars, err error) { +func (res {{ camelCase .ResourceIdent "base" }}) EncodeVars() (out *expr.Vars, err error) { {{- if $r.Properties }} - var ( - rvars = expr.RVars{} - ) + out = &expr.Vars{} + var v expr.TypedValue {{ range $r.Properties }} {{- if .ExprType }} - if rvars[{{ printf "%q" .Name }}], err = automation.{{ export "new" .ExprType }}(res.{{ .Name }}); err != nil { - return nil, err + if v, err = automation.{{ export "new" .ExprType }}(res.{{ .Name }}); err == nil { + err = out.Set({{ printf "%q" .Name }},v) + } + + if err != nil { + return } {{- else }} // Could not found expression-type counterpart for {{ .Type }} {{- end }} {{ end }} - return rvars.Vars(), err - {{ else }} - return {{ end -}} + _ = v + return } // Decode return values from Corredor script into struct props diff --git a/pkg/expr/expr_test.go b/pkg/expr/expr_test.go index 25d9a50f8..c0a342aef 100644 --- a/pkg/expr/expr_test.go +++ b/pkg/expr/expr_test.go @@ -39,19 +39,19 @@ func TestVars(t *testing.T) { var ( req = require.New(t) - vars = RVars{ + vars = Must(Typify(map[string]interface{}{ "int": Must(NewInteger(42)), - "sub": RVars{ + "sub": map[string]interface{}{ "foo": Must(NewString("foo")), - }.Vars(), - "three": RVars{ - "two": RVars{ - "one": RVars{ + }, + "three": map[string]interface{}{ + "two": map[string]interface{}{ + "one": map[string]interface{}{ "go": Must(NewString("!")), - }.Vars(), - }.Vars(), - }.Vars(), - }.Vars() + }, + }, + }, + })) tv = func(in interface{}) TypedValue { switch cnv := in.(type) { diff --git a/pkg/expr/expr_types.gen.go b/pkg/expr/expr_types.gen.go index b3ef8d67d..e4ed6abb3 100644 --- a/pkg/expr/expr_types.gen.go +++ b/pkg/expr/expr_types.gen.go @@ -550,8 +550,12 @@ func (t *UnsignedInteger) Assign(val interface{}) error { } } -// Vars is an expression type, wrapper for RVars type -type Vars struct{ value RVars } +// Vars is an expression type, wrapper for map[string]TypedValue type +type Vars struct{ value map[string]TypedValue } + +func EmptyVars() *Vars { + return &Vars{make(map[string]TypedValue)} +} // NewVars creates new instance of Vars expression type func NewVars(val interface{}) (*Vars, error) { @@ -566,12 +570,12 @@ func NewVars(val interface{}) (*Vars, error) { func (t Vars) Get() interface{} { return t.value } // Return underlying value on Vars -func (t Vars) GetValue() RVars { return t.value } +func (t Vars) GetValue() map[string]TypedValue { return t.value } // Return type name func (Vars) Type() string { return "Vars" } -// Convert value to RVars +// Convert value to map[string]TypedValue func (Vars) Cast(val interface{}) (TypedValue, error) { return NewVars(val) } diff --git a/pkg/expr/expr_types.go b/pkg/expr/expr_types.go index 93a24453c..4869420c5 100644 --- a/pkg/expr/expr_types.go +++ b/pkg/expr/expr_types.go @@ -24,6 +24,10 @@ type ( } ) +func EmptyVars() *Vars { + return &Vars{value: map[string]TypedValue{}} +} + func ResolveTypes(rt resolvableType, resolver func(typ string) Type) error { return rt.ResolveTypes(resolver) } @@ -36,9 +40,6 @@ func Typify(in interface{}) (tv TypedValue, err error) { } switch c := in.(type) { - // @todo - //case map[string]interface{}: - // return NewVars() case []TypedValue: return &Array{value: c}, nil case bool: @@ -75,6 +76,14 @@ func Typify(in interface{}) (tv TypedValue, err error) { return &Duration{value: *c}, nil case time.Duration: return &Duration{value: c}, nil + case map[string]interface{}: + if v, err := CastToVars(c); err != nil { + return nil, err + } else { + return &Vars{v}, nil + } + case map[string]TypedValue: + return &Vars{c}, nil case map[string]string: return &KV{value: c}, nil case map[string][]string: diff --git a/pkg/expr/expr_types.yaml b/pkg/expr/expr_types.yaml index f4d58783f..f87a74ac4 100644 --- a/pkg/expr/expr_types.yaml +++ b/pkg/expr/expr_types.yaml @@ -11,7 +11,7 @@ types: as: '[]TypedValue' Vars: - as: 'RVars' + as: 'map[string]TypedValue' Boolean: as: 'bool' diff --git a/pkg/expr/expr_types_test.go b/pkg/expr/expr_types_test.go index bcc88aa2b..37f31b9b7 100644 --- a/pkg/expr/expr_types_test.go +++ b/pkg/expr/expr_types_test.go @@ -9,13 +9,13 @@ import ( ) func TestTypedValueOperations(t *testing.T) { - scope := RVars{ - "xUint": Must(NewUnsignedInteger(1)), - "xInt": Must(NewInteger(1)), - "xBoolT": Must(NewBoolean(true)), - "xBoolF": Must(NewBoolean(false)), - "xString": Must(NewString("foo")), - }.Vars() + scope, _ := NewVars(map[string]interface{}{ + "xUint": uint(1), + "xInt": 1, + "xBoolT": true, + "xBoolF": false, + "xString": "foo", + }) tcc := []struct { expects interface{} @@ -27,11 +27,11 @@ func TestTypedValueOperations(t *testing.T) { // uint ops {true, "xUint == 1"}, - {uint64(1), "xUint"}, + {uint(1), "xUint"}, // uint ops {true, "xInt == 1"}, - {int64(1), "xInt"}, + {int(1), "xInt"}, // string ops {true, `xString == "foo"`}, @@ -157,12 +157,16 @@ func TestArrayDecode(t *testing.T) { }) req.NoError(err) - req.NoError(RVars{ + + vars, err := NewVars(map[string]interface{}{ "strings": &Array{arr}, "iface": Must(NewString("typed")), "typed": Must(NewString("typed")), "values": &Array{arr}, - }.Vars().Decode(&foo)) + }) + + req.NoError(err) + req.NoError(vars.Decode(&foo)) req.Len(foo.Strings, 2) req.Len(foo.Values, 2) } diff --git a/pkg/expr/func_gen.go b/pkg/expr/func_generic.go similarity index 97% rename from pkg/expr/func_gen.go rename to pkg/expr/func_generic.go index c211a15c6..c80d6c1d3 100644 --- a/pkg/expr/func_gen.go +++ b/pkg/expr/func_generic.go @@ -58,7 +58,7 @@ func isEmpty(i interface{}) bool { } switch reflect.TypeOf(i).Kind() { - case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Map: + case reflect.Slice, reflect.Array, reflect.Map: return reflect.ValueOf(i).Len() == 0 } diff --git a/pkg/expr/func_gen_test.go b/pkg/expr/func_generic_test.go similarity index 100% rename from pkg/expr/func_gen_test.go rename to pkg/expr/func_generic_test.go diff --git a/pkg/expr/parser.go b/pkg/expr/parser.go index 9f7d33ddc..7c2766bec 100644 --- a/pkg/expr/parser.go +++ b/pkg/expr/parser.go @@ -66,11 +66,11 @@ func (p *gvalParser) ParseEvaluators(ee ...Evaluator) error { } func (e *gvalEval) Eval(ctx context.Context, scope *Vars) (interface{}, error) { - return e.evaluable(ctx, scope.Dict()) + return e.evaluable(ctx, scope) } func (e *gvalEval) Test(ctx context.Context, scope *Vars) (bool, error) { - r, err := e.evaluable(ctx, scope.Dict()) + r, err := e.evaluable(ctx, scope) if err != nil { return false, err } diff --git a/pkg/expr/vars.go b/pkg/expr/vars.go index 8a6e313f3..602324c28 100644 --- a/pkg/expr/vars.go +++ b/pkg/expr/vars.go @@ -12,16 +12,6 @@ import ( "strings" ) -type ( - // RVars or raw-vars, used as internal type for Vars expr type - RVars map[string]TypedValue -) - -// Vars is a utility func that returns RVars wrapped in Vars -func (v RVars) Vars() *Vars { - return &Vars{value: v} -} - func (t Vars) Len() int { return len(t.value) } @@ -36,7 +26,7 @@ func (t Vars) Select(k string) (TypedValue, error) { func (t *Vars) AssignFieldValue(key string, val TypedValue) (err error) { if t.value == nil { - t.value = make(RVars) + t.value = make(map[string]TypedValue) } t.value[key] = val @@ -70,7 +60,7 @@ func (t Vars) ResolveTypes(res func(typ string) Type) (err error) { // Assign takes base variables and assigns all new variables func (t *Vars) Merge(nn ...Iterator) *Vars { var ( - out = &Vars{value: make(RVars)} + out = &Vars{value: make(map[string]TypedValue)} ) nn = append([]Iterator{t}, nn...) @@ -92,7 +82,7 @@ func (t *Vars) Copy(dst *Vars, kk ...string) { } if dst.value == nil { - dst.value = make(RVars) + dst.value = make(map[string]TypedValue) } for _, k := range kk { @@ -135,17 +125,12 @@ func (t *Vars) HasAny(key string, kk ...string) bool { return false } -func (t *Vars) Dict() map[string]interface{} { - if t == nil { - return nil - } +var _ gval.Selector = &Vars{} +func (t *Vars) Dict() map[string]interface{} { dict := make(map[string]interface{}) for k, v := range t.value { switch v := v.(type) { - case gval.Selector: - dict[k] = v - case Dict: dict[k] = v.Dict() @@ -227,25 +212,31 @@ func (t *Vars) Value() (driver.Value, error) { } func (t Vars) SelectGVal(_ context.Context, k string) (interface{}, error) { - return t.Select(k) + val, err := t.Select(k) + switch c := val.(type) { + case gval.Selector: + return c, nil + default: + return UntypedValue(val), err + } } // UnmarshalJSON func (t *Vars) UnmarshalJSON(in []byte) (err error) { - if len(in) == 0 { - return nil - } - var ( aux = make(map[string]*typedValueWrap) ) - if err = json.Unmarshal(in, &aux); err != nil { - return + if t.value == nil { + t.value = make(map[string]TypedValue) } - if t.value == nil && len(aux) > 0 { - t.value = make(map[string]TypedValue) + if len(in) == 0 { + return nil + } + + if err = json.Unmarshal(in, &aux); err != nil { + return } for k, v := range aux { @@ -271,6 +262,15 @@ func (t *Vars) Each(fn func(k string, v TypedValue) error) (err error) { return } +func (t *Vars) Set(k string, v interface{}) (err error) { + if t.value == nil { + t.value = make(map[string]TypedValue) + } + + t.value[k], err = Typify(v) + return +} + // UnmarshalJSON parses sort expression when passed inside JSON func (t Vars) MarshalJSON() ([]byte, error) { aux := make(map[string]*typedValueWrap) @@ -307,8 +307,12 @@ func decode(dst reflect.Value, src TypedValue) (err error) { return } - raw := UntypedValue(src) + if reflect.ValueOf(src).Type().ConvertibleTo(dst.Type()) { + dst.Set(reflect.ValueOf(src)) + return + } + raw := UntypedValue(src) // Optimistically try to decode source to destination by comparing (internal) value type for destination if reflect.ValueOf(raw).Type().ConvertibleTo(dst.Type()) { dst.Set(reflect.ValueOf(raw)) @@ -349,6 +353,9 @@ func decode(dst reflect.Value, src TypedValue) (err error) { dst.SetString(vString) } + case reflect.Map: + dst.Set(reflect.ValueOf(src.Get())) + //case reflect.Interface: // dst.Set(reflect.ValueOf(raw)) @@ -363,18 +370,28 @@ func decode(dst reflect.Value, src TypedValue) (err error) { return nil } -func CastToVars(val interface{}) (out RVars, err error) { +func CastToVars(val interface{}) (out map[string]TypedValue, err error) { val = UntypedValue(val) if val == nil { - return make(RVars), nil + return make(map[string]TypedValue), nil } switch c := val.(type) { case *Vars: return c.value, nil - case RVars: + case map[string]TypedValue: return c, nil + case map[string]interface{}: + out = make(map[string]TypedValue) + for k, v := range c { + out[k], err = Typify(v) + if err != nil { + return + } + } + + return } return nil, fmt.Errorf("unable to cast type %T to %T", val, out) diff --git a/pkg/expr/vars_test.go b/pkg/expr/vars_test.go index 4627e6555..a461d7057 100644 --- a/pkg/expr/vars_test.go +++ b/pkg/expr/vars_test.go @@ -9,7 +9,6 @@ import ( // extract typed-value func TestVars_Decode(t *testing.T) { - t.Run("mix", func(t *testing.T) { var ( req = require.New(t) @@ -23,12 +22,12 @@ func TestVars_Decode(t *testing.T) { Unexisting byte }{} - vars = RVars{ + vars, _ = NewVars(map[string]interface{}{ "int": Must(NewInteger(42)), "STRING": Must(NewString("foo")), "bool": Must(NewBoolean(true)), "missing": Must(NewBoolean(true)), - }.Vars() + }) ) req.NoError(vars.Decode(dst)) @@ -48,11 +47,11 @@ func TestVars_Decode(t *testing.T) { IBool interface{} `var:"iBool"` }{} - vars = RVars{ + vars, _ = NewVars(map[string]interface{}{ "iString": Must(NewString("foo")), "iInteger": Must(NewInteger(42)), "iBool": Must(NewBoolean(true)), - }.Vars() + }) ) req.NoError(vars.Decode(dst)) @@ -63,12 +62,12 @@ func TestVars_Decode(t *testing.T) { req = require.New(t) dst = &struct { - Vars RVars `var:"vars"` + Vars *Vars `var:"vars"` }{} - vars = RVars{ - "vars": RVars{"foo": Must(NewString("bar"))}.Vars(), - }.Vars() + vars, _ = NewVars(map[string]interface{}{ + "vars": map[string]interface{}{"foo": Must(NewString("bar"))}, + }) ) req.NoError(vars.Decode(dst)) @@ -83,10 +82,10 @@ func TestVars_Decode(t *testing.T) { Uint64 uint64 }{} - vars = RVars{ + vars, _ = NewVars(map[string]TypedValue{ "uint64": Must(NewAny("42")), "int": Must(NewAny("42")), - }.Vars() + }) ) dst.Uint64 = 0 @@ -96,52 +95,66 @@ func TestVars_Decode(t *testing.T) { req.Equal(uint64(42), dst.Uint64) req.Equal(int64(42), dst.Int) }) + +} + +func TestVars_Assign(t *testing.T) { + var ( + req = require.New(t) + vars = &Vars{} + ) + + req.NoError(Assign(vars, "foo", &String{value: "foo"})) + req.NoError(Assign(vars, "vars", &Vars{})) + req.NoError(Assign(vars, "vars.foo", &String{value: "foo"})) } func TestVars_UnmarshalJSON(t *testing.T) { cases := []struct { name string json string - vars *Vars + vars map[string]interface{} }{ - {"empty", "", &Vars{}}, - {"empty", "{}", &Vars{}}, - {"string", `{"a":{"@value":"b"}}`, RVars{"a": &Unresolved{value: "b"}}.Vars()}, + {"empty", "", make(map[string]interface{})}, + {"object", "{}", make(map[string]interface{})}, + {"string", `{"a":{"@value":"b"}}`, map[string]interface{}{"a": &Unresolved{value: "b"}}}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { var ( - r = require.New(t) - v = &Vars{} + r = require.New(t) + unmarshaled = &Vars{} + aux, _ = NewVars(c.vars) ) - r.NoError(v.UnmarshalJSON([]byte(c.json))) - r.Equal(c.vars, v) + r.NoError(unmarshaled.UnmarshalJSON([]byte(c.json))) + r.Equal(aux, unmarshaled) }) } } -func TestVars_UMarshalJSON(t *testing.T) { +func TestVars_MarshalJSON(t *testing.T) { cases := []struct { name string json string - vars *Vars + vars map[string]interface{} }{ - {"empty", "{}", &Vars{}}, - {"string", `{"a":{"@value":"b","@type":"String"}}`, RVars{"a": &String{value: "b"}}.Vars()}, + {"empty", "{}", nil}, + {"string", `{"a":{"@value":"b","@type":"String"}}`, map[string]interface{}{"a": &String{value: "b"}}}, {"array", `{"arr":{"@value":[{"@value":"foo","@type":"String"},{"@value":"bar","@type":"String"}],"@type":"Array"}}`, - RVars{"arr": &Array{value: []TypedValue{&String{value: "foo"}, &String{value: "bar"}}}}.Vars()}, + map[string]interface{}{"arr": &Array{value: []TypedValue{&String{value: "foo"}, &String{value: "bar"}}}}}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { var ( - r = require.New(t) + r = require.New(t) + aux, _ = NewVars(c.vars) ) - j, err := json.Marshal(c.vars) + j, err := json.Marshal(aux) r.NoError(err) r.Equal(c.json, string(j)) }) diff --git a/pkg/wfexec/gateways_test.go b/pkg/wfexec/gateways_test.go index 9bc0309fe..50c89d2e5 100644 --- a/pkg/wfexec/gateways_test.go +++ b/pkg/wfexec/gateways_test.go @@ -3,18 +3,21 @@ package wfexec import ( "context" "github.com/cortezaproject/corteza-server/pkg/expr" + "github.com/spf13/cast" "github.com/stretchr/testify/require" "testing" ) func gt(key string, val int64) pathTester { return func(ctx context.Context, variables *expr.Vars) (bool, error) { - return expr.Must(expr.Select(variables, key)).Get().(int64) > val, nil + return cast.ToInt64(expr.Must(expr.Select(variables, key)).Get()) > val, nil } } func makeIntVars(k string, num int) *expr.Vars { - return expr.RVars{k: expr.Must(expr.NewInteger(num))}.Vars() + o := &expr.Vars{} + _ = o.Set(k, num) + return o } func TestJoinGateway(t *testing.T) { diff --git a/pkg/wfexec/session.go b/pkg/wfexec/session.go index 1c0b179e7..a9d0e6437 100644 --- a/pkg/wfexec/session.go +++ b/pkg/wfexec/session.go @@ -483,10 +483,9 @@ func (s *Session) queueScheduledSuspended() { delete(s.delayed, id) // Set state input when step is resumed - sus.state.input = expr.RVars{ - "resumed": expr.Must(expr.NewBoolean(true)), - "resumeAt": expr.Must(expr.NewDateTime(sus.resumeAt)), - }.Vars() + sus.state.input = &expr.Vars{} + sus.state.input.Set("resumed", true) + sus.state.input.Set("resumeAt", sus.resumeAt) s.qState <- sus.state } } diff --git a/pkg/wfexec/session_test.go b/pkg/wfexec/session_test.go index dd689b48a..f125ffcd6 100644 --- a/pkg/wfexec/session_test.go +++ b/pkg/wfexec/session_test.go @@ -33,20 +33,22 @@ func (s *sesTestStep) Exec(ctx context.Context, r *ExecRequest) (ExecResponse, e return s.exec(ctx, r) } - var args = &struct { - Path string - Counter int64 - }{} + var ( + args = &struct { + Path string + Counter int64 + }{} + ) if err := r.Scope.Decode(args); err != nil { return nil, err } - return expr.RVars{ - "counter": expr.Must(expr.NewInteger(args.Counter + 1)), - "path": expr.Must(expr.NewString(args.Path + "/" + s.name)), - s.name: expr.Must(expr.NewString("executed")), - }.Vars(), nil + return expr.NewVars(map[string]interface{}{ + "counter": args.Counter + 1, + "path": args.Path + "/" + s.name, + s.name: "executed", + }) } func (s *sesTestTemporal) Exec(ctx context.Context, r *ExecRequest) (ExecResponse, error) { @@ -58,9 +60,9 @@ func (s *sesTestTemporal) Exec(ctx context.Context, r *ExecRequest) (ExecRespons return Delay(s.until), nil } - return expr.RVars{ - "waitForMoment": expr.Must(expr.NewString("executed")), - }.Vars(), nil + return expr.NewVars(map[string]interface{}{ + "waitForMoment": "executed", + }) } func TestSession_TwoStepWorkflow(t *testing.T) { @@ -72,11 +74,16 @@ func TestSession_TwoStepWorkflow(t *testing.T) { s1 = &sesTestStep{name: "s1"} s2 = &sesTestStep{name: "s2"} + + scope = &expr.Vars{} ) + scope.Set("two", 1) + scope.Set("three", 1) + wf.AddStep(s1, s2) // 1st execute s1 then s2 - ses.Exec(ctx, s1, expr.RVars{"two": expr.Must(expr.NewInteger(1)), "three": expr.Must(expr.NewInteger(1))}.Vars()) - ses.Wait(ctx) + req.NoError(ses.Exec(ctx, s1, scope)) + req.NoError(ses.Wait(ctx)) req.NoError(ses.Error()) req.NotNil(ses.Result()) req.Equal("/s1/s2", expr.Must(expr.Select(ses.Result(), "path")).Get()) @@ -140,10 +147,8 @@ func TestSession_Delays(t *testing.T) { return Prompt(0, "", nil), nil } - out := expr.RVars{ - "waitForInput": expr.Must(expr.NewString("executed")), - }.Vars() - + out := &expr.Vars{} + _ = out.Set("waitForInput", "executed") r.Input.Copy(out, "input") return out, nil @@ -159,7 +164,7 @@ func TestSession_Delays(t *testing.T) { req.NoError(ses.Exec(ctx, start, nil)) // wait-for-moment step needs to be executed before we can resume wait-for-input - ses.Wait(ctx) + req.NoError(ses.Wait(ctx)) time.Sleep(delay + unit) req.NotZero(waitForInputStateId.Load()) @@ -168,10 +173,12 @@ func TestSession_Delays(t *testing.T) { req.True(ses.Suspended()) // push in the input - req.NoError(ses.Resume(ctx, waitForInputStateId.Load(), expr.RVars{"input": expr.Must(expr.NewString("foo"))}.Vars())) + input := &expr.Vars{} + input.Set("inout", "foo") + req.NoError(ses.Resume(ctx, waitForInputStateId.Load(), input)) req.False(ses.Suspended()) - ses.Wait(ctx) + req.NoError(ses.Wait(ctx)) time.Sleep(2 * unit) // should not be completed yet... diff --git a/system/automation/expr_types.go b/system/automation/expr_types.go index 6c7a58e6d..edd8696ad 100644 --- a/system/automation/expr_types.go +++ b/system/automation/expr_types.go @@ -3,6 +3,7 @@ package automation import ( "fmt" "io" + "io/ioutil" "github.com/cortezaproject/corteza-server/pkg/expr" "github.com/cortezaproject/corteza-server/system/types" @@ -130,17 +131,7 @@ func CastToRenderOptions(val interface{}) (out map[string]string, err error) { } } -func CastToRenderVariables(val interface{}) (out map[string]interface{}, err error) { - switch val := expr.UntypedValue(val).(type) { - case map[string]interface{}: - return val, nil - case nil: - return make(map[string]interface{}), nil - default: - out, err = cast.ToStringMapE(val) - if err != nil { - return nil, fmt.Errorf("unable to cast type %T to %T", val, out) - } - return out, nil - } +func (doc renderedDocument) String() string { + aux, _ := ioutil.ReadAll(doc.Document) + return string(aux) } diff --git a/system/automation/expr_types_test.go b/system/automation/expr_types_test.go index a2790e849..173c39045 100644 --- a/system/automation/expr_types_test.go +++ b/system/automation/expr_types_test.go @@ -23,16 +23,17 @@ func TestUser(t *testing.T) { func TestUser_Expr(t *testing.T) { var ( - req = require.New(t) - u, err = NewUser(&types.User{Handle: "hendl"}) + req = require.New(t) + u, _ = NewUser(&types.User{Handle: "hendl"}) + scope = &expr.Vars{} ) - req.NoError(err) + req.NoError(scope.Set("user", u)) eval, err := expr.NewParser().Parse("user.handle") req.NoError(err) - res, err := eval.Eval(context.Background(), expr.RVars{"user": u}.Vars()) + res, err := eval.Eval(context.Background(), scope) req.NoError(err) req.Equal("hendl", res.(string)) diff --git a/system/automation/roles_handler.go b/system/automation/roles_handler.go index 8b6b82c5a..c69f6d102 100644 --- a/system/automation/roles_handler.go +++ b/system/automation/roles_handler.go @@ -218,11 +218,11 @@ func (i *roleSetIterator) More(context.Context, *Vars) (bool, error) { func (i *roleSetIterator) Start(context.Context, *Vars) error { i.ptr = 0; return nil } func (i *roleSetIterator) Next(context.Context, *Vars) (*Vars, error) { - out := RVars{ - "role": Must(NewRole(i.set[i.ptr])), - "total": Must(NewUnsignedInteger(i.filter.Total)), - } + out := &Vars{} + out.Set("role", Must(NewRole(i.set[i.ptr]))) + out.Set("index", i.ptr) + out.Set("total", i.filter.Total) i.ptr++ - return out.Vars(), nil + return out, nil } diff --git a/system/automation/templates_handler.gen.go b/system/automation/templates_handler.gen.go index 6fd01938e..096b05914 100644 --- a/system/automation/templates_handler.gen.go +++ b/system/automation/templates_handler.gen.go @@ -746,7 +746,7 @@ type ( DocumentType string hasVariables bool - Variables expr.RVars + Variables *expr.Vars hasOptions bool Options map[string]string diff --git a/system/automation/templates_handler.go b/system/automation/templates_handler.go index 470bd6b2a..6a56d672f 100644 --- a/system/automation/templates_handler.go +++ b/system/automation/templates_handler.go @@ -163,11 +163,6 @@ func (h templatesHandler) recover(ctx context.Context, args *templatesRecoverArg func (h templatesHandler) render(ctx context.Context, args *templatesRenderArgs) (*templatesRenderResults, error) { var err error - vars := args.Variables.Vars().Dict() - if vars == nil { - vars = make(map[string]interface{}) - } - opts := make(map[string]string) if args.hasOptions { opts, err = cast.ToStringMapStringE(args.Options) @@ -181,7 +176,7 @@ func (h templatesHandler) render(ctx context.Context, args *templatesRenderArgs) return nil, err } - doc, err := h.tSvc.Render(ctx, tplID, args.DocumentType, vars, opts) + doc, err := h.tSvc.Render(ctx, tplID, args.DocumentType, args.Variables.Dict(), opts) if err != nil { return nil, err } @@ -204,13 +199,13 @@ func (i *templateSetIterator) More(context.Context, *Vars) (bool, error) { func (i *templateSetIterator) Start(context.Context, *Vars) error { i.ptr = 0; return nil } func (i *templateSetIterator) Next(context.Context, *Vars) (*Vars, error) { - out := RVars{ - "template": Must(NewTemplate(i.set[i.ptr])), - "total": Must(NewUnsignedInteger(i.filter.Total)), - } + out := &Vars{} + out.Set("template", Must(NewTemplate(i.set[i.ptr]))) + out.Set("index", i.ptr) + out.Set("total", i.filter.Total) i.ptr++ - return out.Vars(), nil + return out, nil } func lookupTemplate(ctx context.Context, svc templateService, args templateLookup) (*types.Template, error) { diff --git a/system/automation/templates_handler.yaml b/system/automation/templates_handler.yaml index f6118aa77..dfded0d92 100644 --- a/system/automation/templates_handler.yaml +++ b/system/automation/templates_handler.yaml @@ -153,7 +153,7 @@ functions: - { wf: String } variables: types: - - { wf: Vars, go: 'expr.RVars' } + - { wf: Vars, go: '*expr.Vars' } options: types: - { wf: RenderOptions } diff --git a/system/automation/users_handler.go b/system/automation/users_handler.go index ef0f209ee..b936f21f7 100644 --- a/system/automation/users_handler.go +++ b/system/automation/users_handler.go @@ -219,11 +219,11 @@ func (i *userSetIterator) More(context.Context, *Vars) (bool, error) { func (i *userSetIterator) Start(context.Context, *Vars) error { i.ptr = 0; return nil } func (i *userSetIterator) Next(context.Context, *Vars) (*Vars, error) { - out := RVars{ - "user": Must(NewUser(i.set[i.ptr])), - "total": Must(NewUnsignedInteger(i.filter.Total)), - } + out := &Vars{} + out.Set("user", Must(NewUser(i.set[i.ptr]))) + out.Set("index", i.ptr) + out.Set("total", i.filter.Total) i.ptr++ - return out.Vars(), nil + return out, nil } diff --git a/system/service/event/events.gen.go b/system/service/event/events.gen.go index ccdb292f3..7bc8eceea 100644 --- a/system/service/event/events.gen.go +++ b/system/service/event/events.gen.go @@ -536,14 +536,14 @@ func (res systemBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res systemBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res systemBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -921,10 +921,9 @@ func (res applicationBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res applicationBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res applicationBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for *types.Application @@ -932,7 +931,8 @@ func (res applicationBase) EncodeVars() (vars *expr.Vars, err error) { // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -1214,20 +1214,24 @@ func (res authBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res authBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res authBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["user"], err = automation.NewUser(res.user); err != nil { - return nil, err + if v, err = automation.NewUser(res.user); err == nil { + err = out.Set("user", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for *types.AuthProvider // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -1639,10 +1643,9 @@ func (res authClientBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res authClientBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res authClientBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for *types.AuthClient @@ -1650,7 +1653,8 @@ func (res authClientBase) EncodeVars() (vars *expr.Vars, err error) { // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -1861,16 +1865,16 @@ func (res mailBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res mailBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res mailBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for *types.MailMessage // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -2265,22 +2269,30 @@ func (res roleBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res roleBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res roleBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["role"], err = automation.NewRole(res.role); err != nil { - return nil, err + if v, err = automation.NewRole(res.role); err == nil { + err = out.Set("role", v) } - if rvars["oldRole"], err = automation.NewRole(res.oldRole); err != nil { - return nil, err + if err != nil { + return + } + + if v, err = automation.NewRole(res.oldRole); err == nil { + err = out.Set("oldRole", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -2570,22 +2582,30 @@ func (res roleMemberBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res roleMemberBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res roleMemberBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["user"], err = automation.NewUser(res.user); err != nil { - return nil, err + if v, err = automation.NewUser(res.user); err == nil { + err = out.Set("user", v) } - if rvars["role"], err = automation.NewRole(res.role); err != nil { - return nil, err + if err != nil { + return + } + + if v, err = automation.NewRole(res.role); err == nil { + err = out.Set("role", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -2759,10 +2779,9 @@ func (res sinkBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res sinkBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res sinkBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue // Could not found expression-type counterpart for *types.SinkResponse @@ -2770,7 +2789,8 @@ func (res sinkBase) EncodeVars() (vars *expr.Vars, err error) { // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props @@ -3168,22 +3188,30 @@ func (res userBase) Encode() (args map[string][]byte, err error) { } // Encode internal data to be passed as event params & arguments to workflow -func (res userBase) EncodeVars() (vars *expr.Vars, err error) { - var ( - rvars = expr.RVars{} - ) +func (res userBase) EncodeVars() (out *expr.Vars, err error) { + out = &expr.Vars{} + var v expr.TypedValue - if rvars["user"], err = automation.NewUser(res.user); err != nil { - return nil, err + if v, err = automation.NewUser(res.user); err == nil { + err = out.Set("user", v) } - if rvars["oldUser"], err = automation.NewUser(res.oldUser); err != nil { - return nil, err + if err != nil { + return + } + + if v, err = automation.NewUser(res.oldUser); err == nil { + err = out.Set("oldUser", v) + } + + if err != nil { + return } // Could not found expression-type counterpart for auth.Identifiable - return rvars.Vars(), err + _ = v + return } // Decode return values from Corredor script into struct props diff --git a/tests/automation/trigger_test.go b/tests/automation/trigger_test.go index c759d7d3f..a62d824ef 100644 --- a/tests/automation/trigger_test.go +++ b/tests/automation/trigger_test.go @@ -151,7 +151,7 @@ func TestTriggerCreateFull(t *testing.T) { WorkflowID: wf.ID, ResourceType: "wf-full-test", Enabled: true, - Input: &expr.Vars{}, + Input: expr.EmptyVars(), OwnedBy: 42, } ) diff --git a/tests/automation/workflow_test.go b/tests/automation/workflow_test.go index 75cb2cebe..41a070239 100644 --- a/tests/automation/workflow_test.go +++ b/tests/automation/workflow_test.go @@ -183,11 +183,15 @@ func TestWorkflowCreateFull(t *testing.T) { Enabled: true, Trace: true, KeepSessions: 10000, - Scope: expr.RVars{"foo": expr.Must(expr.NewString("bar"))}.Vars(), - Steps: types.WorkflowStepSet{}, - Paths: types.WorkflowPathSet{}, - RunAs: 0, - OwnedBy: 42, + Scope: func() *expr.Vars { + o := &expr.Vars{} + _ = o.Set("foo", "bar") + return o + }(), + Steps: types.WorkflowStepSet{}, + Paths: types.WorkflowPathSet{}, + RunAs: 0, + OwnedBy: 42, } )