Skip to content

Commit 9055243

Browse files
authored
fix(103): support refs to yaml format file (#105)
Signed-off-by: lsytj0413 <511121939@qq.com> Signed-off-by: lsytj0413 <511121939@qq.com>
1 parent e83573b commit 9055243

File tree

8 files changed

+330
-0
lines changed

8 files changed

+330
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.19
44

55
require (
66
github.com/go-playground/validator/v10 v10.11.1
7+
github.com/pkg/errors v0.9.1
78
github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46
89
github.com/stretchr/testify v1.7.0
910
k8s.io/apimachinery v0.25.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
3030
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
3131
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
3232
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
33+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
34+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3335
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3436
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3537
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=

hack/conv/main.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2022 The Serverless Workflow Specification Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"encoding/json"
19+
"errors"
20+
"log"
21+
"os"
22+
"path"
23+
"path/filepath"
24+
"strings"
25+
26+
"gopkg.in/yaml.v3"
27+
28+
"github.com/serverlessworkflow/sdk-go/v2/test"
29+
)
30+
31+
func convert(i interface{}) interface{} {
32+
switch x := i.(type) {
33+
case map[interface{}]interface{}:
34+
m2 := map[string]interface{}{}
35+
for k, v := range x {
36+
m2[k.(string)] = convert(v)
37+
}
38+
return m2
39+
case []interface{}:
40+
for i, v := range x {
41+
x[i] = convert(v)
42+
}
43+
}
44+
return i
45+
}
46+
47+
func transform(
48+
files []string,
49+
srcFormat string,
50+
destFormat string,
51+
unmarshal func(data []byte, out interface{}) error,
52+
marshal func(in interface{}) ([]byte, error),
53+
) {
54+
for _, srcFile := range files {
55+
if !strings.HasSuffix(srcFile, srcFormat) {
56+
log.Printf("%s is not %s format, skip it", srcFile, srcFormat)
57+
continue
58+
}
59+
60+
destFile := srcFile[0:len(srcFile)-len(srcFormat)] + destFormat
61+
if _, err := os.Stat(destFile); err == nil {
62+
log.Printf("ERR: the target file %v exists, skip it", destFile)
63+
continue
64+
} else if !errors.Is(err, os.ErrNotExist) {
65+
log.Printf("ERR: stat target file %v, %v, skip it", destFile, err)
66+
continue
67+
}
68+
69+
srcData, err := os.ReadFile(filepath.Clean(srcFile))
70+
if err != nil {
71+
log.Printf("ERR: cannot read file %v, %v, skip it", srcFile, err)
72+
continue
73+
}
74+
75+
var srcObj interface{}
76+
err = unmarshal(srcData, &srcObj)
77+
if err != nil {
78+
log.Printf("ERR: cannot unmarshal file %v to %s, %v, skip it", srcFile, srcFormat, err)
79+
continue
80+
}
81+
82+
destObj := convert(srcObj)
83+
destData, err := marshal(destObj)
84+
if err != nil {
85+
log.Printf("ERR: cannot marshal fild %v data to %v, %v, skip it", srcFile, destFormat, err)
86+
continue
87+
}
88+
89+
err = os.WriteFile(destFile, destData, 0600)
90+
if err != nil {
91+
log.Printf("ERR: cannot write to file %v, %v, skip it", destFile, err)
92+
continue
93+
}
94+
95+
log.Printf("convert %v to %v done", srcFile, destFile)
96+
}
97+
}
98+
99+
func main() {
100+
// TODO: make this as argument
101+
dir := path.Join(test.CurrentProjectPath(), "parser", "testdata", "workflows", "urifiles")
102+
dirEntries, err := os.ReadDir(dir)
103+
if err != nil {
104+
panic(err)
105+
}
106+
107+
files := make([]string, 0, len(dirEntries))
108+
for _, entry := range dirEntries {
109+
if entry.IsDir() {
110+
log.Printf("%s is directory, skip it", entry.Name())
111+
continue
112+
}
113+
114+
files = append(files, path.Join(dir, entry.Name()))
115+
}
116+
117+
log.Printf("found %v files", len(files))
118+
119+
// First, convert all json format files to yaml
120+
log.Printf("start to convert all json format files to yaml format")
121+
transform(files, ".json", ".yaml", json.Unmarshal, yaml.Marshal)
122+
123+
// Second, convert all yaml format files to json
124+
log.Printf("start to convert all yaml format files to json format")
125+
transform(files, ".yaml", ".json", yaml.Unmarshal, func(in interface{}) ([]byte, error) {
126+
return json.MarshalIndent(in, "", " ")
127+
})
128+
}

model/util.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"os"
2323
"path/filepath"
2424
"strings"
25+
26+
"sigs.k8s.io/yaml"
2527
)
2628

2729
const prefix = "file:/"
@@ -50,6 +52,17 @@ func getBytesFromFile(s string) (b []byte, err error) {
5052
if b, err = os.ReadFile(filepath.Clean(s)); err != nil {
5153
return nil, err
5254
}
55+
56+
// TODO: optimize this
57+
// NOTE: In specification, we can declared independently definitions with another file format, so
58+
// we must convert independently yaml source to json format data before unmarshal.
59+
if strings.HasSuffix(s, ".yaml") || strings.HasSuffix(s, ".yml") {
60+
b, err = yaml.YAMLToJSON(b)
61+
if err != nil {
62+
return nil, err
63+
}
64+
}
65+
5366
return b, nil
5467
}
5568

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"id": "applicantrequest",
3+
"version": "1.0",
4+
"name": "Applicant Request Decision Workflow",
5+
"description": "Determine if applicant request is valid",
6+
"start": "CheckApplication",
7+
"specVersion": "0.7",
8+
"auth": "./testdata/workflows/urifiles/auth.yaml",
9+
"functions": [
10+
{
11+
"name": "sendRejectionEmailFunction",
12+
"operation": "http://myapis.org/applicationapi.json#emailRejection"
13+
}
14+
],
15+
"retries": [
16+
{
17+
"name": "TimeoutRetryStrategy",
18+
"delay": "PT1M",
19+
"maxAttempts": "5"
20+
}
21+
],
22+
"states": [
23+
{
24+
"name": "CheckApplication",
25+
"type": "switch",
26+
"dataConditions": [
27+
{
28+
"condition": "${ .applicants | .age >= 18 }",
29+
"transition": {
30+
"nextState": "StartApplication"
31+
}
32+
},
33+
{
34+
"condition": "${ .applicants | .age < 18 }",
35+
"transition": {
36+
"nextState": "RejectApplication"
37+
}
38+
}
39+
],
40+
"default": {
41+
"transition": {
42+
"nextState": "RejectApplication"
43+
}
44+
}
45+
},
46+
{
47+
"name": "StartApplication",
48+
"type": "operation",
49+
"actions": [
50+
{
51+
"subFlowRef": {
52+
"workflowId": "startApplicationWorkflowId"
53+
}
54+
}
55+
],
56+
"end": {
57+
"terminate": true
58+
}
59+
},
60+
{
61+
"name": "RejectApplication",
62+
"type": "operation",
63+
"actionMode": "sequential",
64+
"actions": [
65+
{
66+
"functionRef": {
67+
"refName": "sendRejectionEmailFunction",
68+
"parameters": {
69+
"applicant": "${ .applicant }"
70+
}
71+
}
72+
}
73+
],
74+
"end": {
75+
"terminate": true
76+
}
77+
}
78+
]
79+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2022 The Serverless Workflow Specification Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
- name: testAuth
16+
properties:
17+
token: test_token
18+
scheme: bearer
19+
- name: testAuth2
20+
properties:
21+
password: test_pwd
22+
username: test_user
23+
scheme: basic

test/path.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2022 The Serverless Workflow Specification Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package test
16+
17+
import (
18+
"os"
19+
"path/filepath"
20+
"runtime"
21+
22+
"github.com/pkg/errors"
23+
)
24+
25+
// CurrentProjectPath get the project root path
26+
func CurrentProjectPath() string {
27+
path := currentFilePath()
28+
29+
ppath, err := filepath.Abs(filepath.Join(filepath.Dir(path), "../"))
30+
if err != nil {
31+
panic(errors.Wrapf(err, "Get current project path with %s failed", path))
32+
}
33+
34+
f, err := os.Stat(ppath)
35+
if err != nil {
36+
panic(errors.Wrapf(err, "Stat project path %v failed", ppath))
37+
}
38+
39+
if f.Mode()&os.ModeSymlink != 0 {
40+
fpath, err := os.Readlink(ppath)
41+
if err != nil {
42+
panic(errors.Wrapf(err, "Readlink from path %v failed", fpath))
43+
}
44+
ppath = fpath
45+
}
46+
47+
return ppath
48+
}
49+
50+
func currentFilePath() string {
51+
_, file, _, _ := runtime.Caller(1)
52+
return file
53+
}

test/path_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2022 The Serverless Workflow Specification Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package test
16+
17+
import (
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
)
22+
23+
func TestCurrentProjectPath(t *testing.T) {
24+
t.Run("normal test", func(t *testing.T) {
25+
path := CurrentProjectPath()
26+
27+
// NOTE: the '/code' path is used with code pipeline.
28+
// When code running in the pipeline, the codebase will copy to /home/code directory.
29+
assert.Regexp(t, "(/sdk-go$)|(/code$)", path)
30+
})
31+
}

0 commit comments

Comments
 (0)