diff --git a/automation/rest/workflow.go b/automation/rest/workflow.go index 7c6baeaf3..d8b584e0b 100644 --- a/automation/rest/workflow.go +++ b/automation/rest/workflow.go @@ -6,6 +6,9 @@ import ( "github.com/cortezaproject/corteza-server/automation/rest/request" "github.com/cortezaproject/corteza-server/automation/service" "github.com/cortezaproject/corteza-server/automation/types" + "github.com/cortezaproject/corteza-server/compose/automation" + cmpService "github.com/cortezaproject/corteza-server/compose/service" + cmpTypes "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/api" "github.com/cortezaproject/corteza-server/pkg/expr" "github.com/cortezaproject/corteza-server/pkg/filter" @@ -23,6 +26,11 @@ type ( UndeleteByID(ctx context.Context, workflowID uint64) error Exec(ctx context.Context, workflowID uint64, p types.WorkflowExecParams) (*expr.Vars, types.Stacktrace, error) } + + // cross-link with compose service to load module on resolved records + svcModule interface { + FindByID(ctx context.Context, namespaceID, moduleID uint64) (*cmpTypes.Module, error) + } } workflowSetPayload struct { @@ -40,6 +48,7 @@ type ( func (Workflow) New() *Workflow { ctrl := &Workflow{} ctrl.svc = service.DefaultWorkflow + ctrl.svcModule = cmpService.DefaultModule return ctrl } @@ -124,16 +133,46 @@ func (ctrl Workflow) Exec(ctx context.Context, r *request.WorkflowExec) (interfa var ( wep = &workflowExecPayload{} err error + + execParams = types.WorkflowExecParams{ + StepID: r.StepID, + Trace: r.Trace, + Input: r.Input, + Async: r.Async, + Wait: r.Wait, + } ) - wep.Results, wep.Trace, err = ctrl.svc.Exec(ctx, r.WorkflowID, types.WorkflowExecParams{ - StepID: r.StepID, - Trace: r.Trace, - Input: r.Input, - Async: r.Async, - Wait: r.Wait, + if execParams.Input != nil { + if err = execParams.Input.ResolveTypes(service.Registry().Type); err != nil { + return nil, err + } + } + + // Now that all types are resolved we have to load modules and link them to records + // + // Very naive approach for now. + execParams.Input.Each(func(k string, v expr.TypedValue) error { + switch c := v.(type) { + case *automation.ComposeRecord: + rec := c.GetValue() + if rec == nil { + return nil + } + + mod, err := ctrl.svcModule.FindByID(ctx, rec.NamespaceID, rec.ModuleID) + if err != nil { + return fmt.Errorf("failed to resolve ComposeRecord type: %w", err) + } + + c.GetValue().SetModule(mod) + } + + return nil }) + wep.Results, wep.Trace, err = ctrl.svc.Exec(ctx, r.WorkflowID, execParams) + if err != nil && wep.Trace != nil && r.Trace { // in case of an error & trace enabled (and stacktrace present) // we'll suppress the error diff --git a/compose/automation/expr_types.go b/compose/automation/expr_types.go index 4dfd53339..fd56cf068 100644 --- a/compose/automation/expr_types.go +++ b/compose/automation/expr_types.go @@ -2,6 +2,7 @@ package automation import ( "context" + "encoding/json" "fmt" "github.com/PaesslerAG/gval" "github.com/cortezaproject/corteza-server/compose/types" @@ -23,6 +24,12 @@ func CastToComposeNamespace(val interface{}) (out *types.Namespace, err error) { switch val := expr.UntypedValue(val).(type) { case *types.Namespace: return val, nil + case map[string]interface{}: + out = &types.Namespace{} + m, _ := json.Marshal(val) + _ = json.Unmarshal(m, out) + + return default: return nil, fmt.Errorf("unable to cast type %T to %T", val, out) } @@ -40,6 +47,12 @@ func CastToComposeModule(val interface{}) (out *types.Module, err error) { switch val := expr.UntypedValue(val).(type) { case *types.Module: return val, nil + case map[string]interface{}: + out = &types.Module{} + m, _ := json.Marshal(val) + _ = json.Unmarshal(m, out) + return + default: return nil, fmt.Errorf("unable to cast type %T to %T", val, out) } @@ -63,6 +76,13 @@ func CastToComposeRecord(val interface{}) (out *types.Record, err error) { val.Values = types.RecordValueSet{} } return val, nil + case map[string]interface{}: + out = &types.Record{} + m, _ := json.Marshal(val) + _ = json.Unmarshal(m, out) + + return + default: return nil, fmt.Errorf("unable to cast type %T to %T", val, out) } @@ -93,6 +113,10 @@ var _ gval.Selector = &ComposeRecord{} // func (t ComposeRecord) SelectGVal(ctx context.Context, k string) (interface{}, error) { if k == "values" { + if t.value.Values == nil { + t.value.Values = types.RecordValueSet{} + } + return t.value.Values.Dict(t.value.GetModule().Fields), nil }