Skip to content

Commit 0eaa90f

Browse files
authored
Fixes #14: Parsing nested files for events and functions (#19)
1 parent 0d31416 commit 0eaa90f

12 files changed

+464
-16
lines changed

hack/generate-spec-types.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/bin/bash
22
# Copyright 2020 The Serverless Workflow Specification Authors
3-
#
43
# Licensed under the Apache License, Version 2.0 (the "License");
54
# you may not use this file except in compliance with the License.
65
# You may obtain a copy of the License at
@@ -21,7 +20,8 @@ declare package="model"
2120
declare targetdir="/tmp/serverlessworkflow"
2221

2322
if [ ! -d "${targetdir}" ]; then
24-
git clone git@github.com:serverlessworkflow/specification.git ${targetdir}
23+
git clone git@github.com:serverlessworkflow/specification.git ${targetdir}
24+
2525
fi
2626

2727
# remove once we have https://github.com/atombender/go-jsonschema/pull/16
@@ -33,6 +33,9 @@ sed -i 's/$id/id/g' "${targetdir}/schema/events.json"
3333
sed -i 's/$id/id/g' "${targetdir}/schema/functions.json"
3434
# shellcheck disable=SC2016
3535
sed -i 's/$id/id/g' "${targetdir}/schema/workflow.json"
36+
# shellcheck disable=SC2016
37+
sed -i 's/$id/id/g' "${targetdir}/schema/retries.json"
38+
3639

3740
./bin/gojsonschema -v \
3841
--schema-package=https://serverlessworkflow.org/core/common.json=github.com/serverlessworkflow/sdk-go/model \
@@ -42,8 +45,10 @@ sed -i 's/$id/id/g' "${targetdir}/schema/workflow.json"
4245
--schema-package=https://serverlessworkflow.org/core/functions.json=github.com/serverlessworkflow/sdk-go/model \
4346
--schema-output=https://serverlessworkflow.org/core/functions.json=zz_generated.types_functions.go \
4447
--schema-package=https://serverlessworkflow.org/core/workflow.json=github.com/serverlessworkflow/sdk-go/model \
45-
--schema-output=https://serverlessworkflow.org/core/workflow.json=zz_generated.types_workflow.go \
46-
"${targetdir}"/schema/common.json "${targetdir}"/schema/events.json "${targetdir}"/schema/functions.json "${targetdir}"/schema/workflow.json
48+
--schema-output=https://serverlessworkflow.org/core/workflow.json=zz_generated.types_workflow.go \
49+
--schema-package=https://serverlessworkflow.org/core/retries.json=github.com/serverlessworkflow/sdk-go/model \
50+
--schema-output=https://serverlessworkflow.org/core/retries.json=zz_generated.types_retries.go \
51+
"${targetdir}"/schema/common.json "${targetdir}"/schema/events.json "${targetdir}"/schema/functions.json "${targetdir}"/schema/workflow.json "${targetdir}"/schema/retries.json
4752

4853
sed -i '/type Workflow/d' zz_generated.types_workflow.go
4954

model/types.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,23 @@ var actionsModelMapping = map[string]func(state map[string]interface{}) State{
3434
// WorkflowCommon describes the partial Workflow definition that does not rely on generic interfaces
3535
// to make it easy for custom unmarshalers implementations to unmarshal the common data structure.
3636
type WorkflowCommon struct {
37-
ID string `json:"id"`
38-
Name string `json:"name"`
39-
Description string `json:"description,omitempty"`
40-
Version string `json:"version"`
41-
SchemaVersion string `json:"schemaVersion"`
42-
DataInputSchema string `json:"dataInputSchema,omitempty"`
43-
DataOutputSchema string `json:"dataOutputSchema,omitempty"`
44-
Metadata Metadata `json:"metadata,omitempty"`
45-
Events []Eventdef `json:"events,omitempty"`
46-
Functions []Function `json:"functions,omitempty"`
37+
ID string `json:"id"`
38+
Name string `json:"name"`
39+
Description string `json:"description,omitempty"`
40+
Version string `json:"version"`
41+
SchemaVersion string `json:"schemaVersion"`
42+
DataInputSchema string `json:"dataInputSchema,omitempty"`
43+
DataOutputSchema string `json:"dataOutputSchema,omitempty"`
44+
Metadata Metadata `json:"metadata,omitempty"`
4745
}
4846

4947
// Workflow base definition
5048
type Workflow struct {
5149
WorkflowCommon
52-
States []State `json:"states"`
50+
States []State `json:"states"`
51+
Events []Eventdef `json:"events,omitempty"`
52+
Functions []Function `json:"functions,omitempty"`
53+
Retries []Retrydef `json:"retries,omitempty"`
5354
}
5455

5556
// State definition for a Workflow state

model/unmarshal_json.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,40 @@
1515
package model
1616

1717
import (
18+
"bytes"
1819
"encoding/json"
1920
"fmt"
21+
"io/ioutil"
22+
"net/http"
23+
"path/filepath"
24+
"strings"
2025
)
2126

27+
const prefix = "file:/"
28+
29+
func getBytesFromFile(s string) (b []byte, err error) {
30+
31+
if resp, err := http.Get(s); err == nil {
32+
defer resp.Body.Close()
33+
buf := new(bytes.Buffer)
34+
if _, err = buf.ReadFrom(resp.Body); err != nil {
35+
return nil, err
36+
}
37+
return buf.Bytes(), nil
38+
}
39+
if strings.HasPrefix(s, prefix) {
40+
s = strings.TrimPrefix(s, prefix)
41+
} else {
42+
if s, err = filepath.Abs(s); err != nil {
43+
return nil, err
44+
}
45+
}
46+
if b, err = ioutil.ReadFile(s); err != nil {
47+
return nil, err
48+
}
49+
return b, nil
50+
}
51+
2252
// UnmarshalJSON implementation for json Unmarshal function for the Workflow type
2353
func (w *Workflow) UnmarshalJSON(data []byte) error {
2454
if err := json.Unmarshal(data, &w.WorkflowCommon); err != nil {
@@ -49,6 +79,57 @@ func (w *Workflow) UnmarshalJSON(data []byte) error {
4979
}
5080
w.States[i] = state
5181
}
82+
if _, ok := workflowMap["events"]; ok {
83+
if err := json.Unmarshal(workflowMap["events"], &w.Events); err != nil {
84+
var s string
85+
if err := json.Unmarshal(workflowMap["events"], &s); err != nil {
86+
return err
87+
}
88+
var nestedData []byte
89+
if nestedData, err = getBytesFromFile(s); err != nil {
90+
return err
91+
}
92+
m := make(map[string][]Eventdef)
93+
if err := json.Unmarshal(nestedData, &m); err != nil {
94+
return err
95+
}
96+
w.Events = m["events"]
97+
}
98+
}
99+
if _, ok := workflowMap["functions"]; ok {
100+
if err := json.Unmarshal(workflowMap["functions"], &w.Functions); err != nil {
101+
var s string
102+
if err := json.Unmarshal(workflowMap["functions"], &s); err != nil {
103+
return err
104+
}
105+
var nestedData []byte
106+
if nestedData, err = getBytesFromFile(s); err != nil {
107+
return err
108+
}
109+
m := make(map[string][]Function)
110+
if err := json.Unmarshal(nestedData, &m); err != nil {
111+
return err
112+
}
113+
w.Functions = m["functions"]
114+
}
115+
}
116+
if _, ok := workflowMap["retries"]; ok {
117+
if err := json.Unmarshal(workflowMap["retries"], &w.Retries); err != nil {
118+
var s string
119+
if err := json.Unmarshal(workflowMap["retries"], &s); err != nil {
120+
return err
121+
}
122+
var nestedData []byte
123+
if nestedData, err = getBytesFromFile(s); err != nil {
124+
return err
125+
}
126+
m := make(map[string][]Retrydef)
127+
if err := json.Unmarshal(nestedData, &m); err != nil {
128+
return err
129+
}
130+
w.Retries = m["retries"]
131+
}
132+
}
52133
return nil
53134
}
54135

model/zz_generated.types_retries.go

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/parser_test.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
package parser
1616

1717
import (
18+
"testing"
19+
1820
"github.com/serverlessworkflow/sdk-go/model"
1921
"github.com/stretchr/testify/assert"
20-
"testing"
2122
)
2223

2324
func TestFromFile(t *testing.T) {
@@ -33,6 +34,15 @@ func TestFromFile(t *testing.T) {
3334
assert.NotNil(t, w.States[0].(*model.Operationstate).Actions[0].FunctionRef)
3435
},
3536
"./testdata/eventbasedgreeting.sw.json": func(t *testing.T, w *model.Workflow) {
37+
assert.Equal(t, "GreetingEvent", *w.Events[0].Name)
38+
assert.IsType(t, &model.Eventstate{}, w.States[0])
39+
eventState := w.States[0].(*model.Eventstate)
40+
assert.NotNil(t, eventState)
41+
assert.NotEmpty(t, eventState.OnEvents)
42+
assert.Equal(t, "GreetingEvent", eventState.OnEvents[0].EventRefs[0])
43+
},
44+
"./testdata/eventbasedgreeting.sw.p.json": func(t *testing.T, w *model.Workflow) {
45+
assert.Equal(t, "GreetingEvent", *w.Events[0].Name)
3646
assert.IsType(t, &model.Eventstate{}, w.States[0])
3747
eventState := w.States[0].(*model.Eventstate)
3848
assert.NotNil(t, eventState)
@@ -46,6 +56,30 @@ func TestFromFile(t *testing.T) {
4656
assert.NotEmpty(t, eventState.EventConditions)
4757
assert.IsType(t, &model.Transitioneventcondition{}, eventState.EventConditions[0])
4858
},
59+
"./testdata/applicationrequest.json": func(t *testing.T, w *model.Workflow) {
60+
assert.IsType(t, &model.Databasedswitch{}, w.States[0])
61+
eventState := w.States[0].(*model.Databasedswitch)
62+
assert.NotNil(t, eventState)
63+
assert.NotEmpty(t, eventState.DataConditions)
64+
assert.IsType(t, &model.Transitiondatacondition{}, eventState.DataConditions[0])
65+
assert.Equal(t, "TimeoutRetryStrategy", w.Retries[0].Name)
66+
},
67+
"./testdata/applicationrequest.rp.json": func(t *testing.T, w *model.Workflow) {
68+
assert.IsType(t, &model.Databasedswitch{}, w.States[0])
69+
eventState := w.States[0].(*model.Databasedswitch)
70+
assert.NotNil(t, eventState)
71+
assert.NotEmpty(t, eventState.DataConditions)
72+
assert.IsType(t, &model.Transitiondatacondition{}, eventState.DataConditions[0])
73+
assert.Equal(t, "TimeoutRetryStrategy", w.Retries[0].Name)
74+
},
75+
"./testdata/applicationrequest.url.json": func(t *testing.T, w *model.Workflow) {
76+
assert.IsType(t, &model.Databasedswitch{}, w.States[0])
77+
eventState := w.States[0].(*model.Databasedswitch)
78+
assert.NotNil(t, eventState)
79+
assert.NotEmpty(t, eventState.DataConditions)
80+
assert.IsType(t, &model.Transitiondatacondition{}, eventState.DataConditions[0])
81+
assert.Equal(t, "TimeoutRetryStrategy", w.Retries[0].Name)
82+
},
4983
"./testdata/checkinbox.sw.yaml": func(t *testing.T, w *model.Workflow) {
5084
assert.IsType(t, &model.Operationstate{}, w.States[0])
5185
operationState := w.States[0].(*model.Operationstate)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
{
3+
"id": "applicantrequest",
4+
"version": "1.0",
5+
"name": "Applicant Request Decision Workflow",
6+
"description": "Determine if applicant request is valid",
7+
"functions": [
8+
{
9+
"name": "sendRejectionEmailFunction",
10+
"operation": "http://myapis.org/applicationapi.json#emailRejection"
11+
}
12+
],
13+
"retries": [
14+
{
15+
"name": "TimeoutRetryStrategy",
16+
"delay": "PT1M",
17+
"maxAttempts": "5"
18+
}
19+
],
20+
"states":[
21+
{
22+
"name":"CheckApplication",
23+
"type":"switch",
24+
"start": {
25+
"kind": "default"
26+
},
27+
"dataConditions": [
28+
{
29+
"condition": "{{ $.applicants[?(@.age >= 18)] }}",
30+
"transition": {
31+
"nextState": "StartApplication"
32+
}
33+
},
34+
{
35+
"condition": "{{ $.applicants[?(@.age < 18)] }}",
36+
"transition": {
37+
"nextState": "RejectApplication"
38+
}
39+
}
40+
],
41+
"default": {
42+
"transition": {
43+
"nextState": "RejectApplication"
44+
}
45+
}
46+
},
47+
{
48+
"name": "StartApplication",
49+
"type": "subflow",
50+
"workflowId": "startApplicationWorkflowId",
51+
"end": {
52+
"kind": "default"
53+
}
54+
},
55+
{
56+
"name":"RejectApplication",
57+
"type":"operation",
58+
"actionMode":"sequential",
59+
"actions":[
60+
{
61+
"functionRef": {
62+
"refName": "sendRejectionEmailFunction",
63+
"parameters": {
64+
"applicant": "{{ $.applicant }}"
65+
}
66+
}
67+
}
68+
],
69+
"end": {
70+
"kind": "default"
71+
}
72+
}
73+
]
74+
}

0 commit comments

Comments
 (0)