Skip to content

fix(103): support refs to yaml format file #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/go-playground/validator/v10 v10.11.1
github.com/pkg/errors v0.9.1
github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46
github.com/stretchr/testify v1.7.0
k8s.io/apimachinery v0.25.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
Expand Down
128 changes: 128 additions & 0 deletions hack/conv/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2022 The Serverless Workflow Specification Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"encoding/json"
"errors"
"log"
"os"
"path"
"path/filepath"
"strings"

"gopkg.in/yaml.v3"

"github.com/serverlessworkflow/sdk-go/v2/test"
)

func convert(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convert(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convert(v)
}
}
return i
}

func transform(
files []string,
srcFormat string,
destFormat string,
unmarshal func(data []byte, out interface{}) error,
marshal func(in interface{}) ([]byte, error),
) {
for _, srcFile := range files {
if !strings.HasSuffix(srcFile, srcFormat) {
log.Printf("%s is not %s format, skip it", srcFile, srcFormat)
continue
}

destFile := srcFile[0:len(srcFile)-len(srcFormat)] + destFormat
if _, err := os.Stat(destFile); err == nil {
log.Printf("ERR: the target file %v exists, skip it", destFile)
continue
} else if !errors.Is(err, os.ErrNotExist) {
log.Printf("ERR: stat target file %v, %v, skip it", destFile, err)
continue
}

srcData, err := os.ReadFile(filepath.Clean(srcFile))
if err != nil {
log.Printf("ERR: cannot read file %v, %v, skip it", srcFile, err)
continue
}

var srcObj interface{}
err = unmarshal(srcData, &srcObj)
if err != nil {
log.Printf("ERR: cannot unmarshal file %v to %s, %v, skip it", srcFile, srcFormat, err)
continue
}

destObj := convert(srcObj)
destData, err := marshal(destObj)
if err != nil {
log.Printf("ERR: cannot marshal fild %v data to %v, %v, skip it", srcFile, destFormat, err)
continue
}

err = os.WriteFile(destFile, destData, 0600)
if err != nil {
log.Printf("ERR: cannot write to file %v, %v, skip it", destFile, err)
continue
}

log.Printf("convert %v to %v done", srcFile, destFile)
}
}

func main() {
// TODO: make this as argument
dir := path.Join(test.CurrentProjectPath(), "parser", "testdata", "workflows", "urifiles")
dirEntries, err := os.ReadDir(dir)
if err != nil {
panic(err)
}

files := make([]string, 0, len(dirEntries))
for _, entry := range dirEntries {
if entry.IsDir() {
log.Printf("%s is directory, skip it", entry.Name())
continue
}

files = append(files, path.Join(dir, entry.Name()))
}

log.Printf("found %v files", len(files))

// First, convert all json format files to yaml
log.Printf("start to convert all json format files to yaml format")
transform(files, ".json", ".yaml", json.Unmarshal, yaml.Marshal)

// Second, convert all yaml format files to json
log.Printf("start to convert all yaml format files to json format")
transform(files, ".yaml", ".json", yaml.Unmarshal, func(in interface{}) ([]byte, error) {
return json.MarshalIndent(in, "", " ")
})
}
13 changes: 13 additions & 0 deletions model/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"os"
"path/filepath"
"strings"

"sigs.k8s.io/yaml"
)

const prefix = "file:/"
Expand Down Expand Up @@ -49,6 +51,17 @@ func getBytesFromFile(s string) (b []byte, err error) {
if b, err = os.ReadFile(filepath.Clean(s)); err != nil {
return nil, err
}

// TODO: optimize this
// NOTE: In specification, we can declared independently definitions with another file format, so
// we must convert independently yaml source to json format data before unmarshal.
if strings.HasSuffix(s, ".yaml") || strings.HasSuffix(s, ".yml") {
b, err = yaml.YAMLToJSON(b)
if err != nil {
return nil, err
}
}

return b, nil
}

Expand Down
79 changes: 79 additions & 0 deletions parser/testdata/workflows/applicationrequest-issue103.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"id": "applicantrequest",
"version": "1.0",
"name": "Applicant Request Decision Workflow",
"description": "Determine if applicant request is valid",
"start": "CheckApplication",
"specVersion": "0.7",
"auth": "./testdata/workflows/urifiles/auth.yaml",
"functions": [
{
"name": "sendRejectionEmailFunction",
"operation": "http://myapis.org/applicationapi.json#emailRejection"
}
],
"retries": [
{
"name": "TimeoutRetryStrategy",
"delay": "PT1M",
"maxAttempts": "5"
}
],
"states": [
{
"name": "CheckApplication",
"type": "switch",
"dataConditions": [
{
"condition": "${ .applicants | .age >= 18 }",
"transition": {
"nextState": "StartApplication"
}
},
{
"condition": "${ .applicants | .age < 18 }",
"transition": {
"nextState": "RejectApplication"
}
}
],
"default": {
"transition": {
"nextState": "RejectApplication"
}
}
},
{
"name": "StartApplication",
"type": "operation",
"actions": [
{
"subFlowRef": {
"workflowId": "startApplicationWorkflowId"
}
}
],
"end": {
"terminate": true
}
},
{
"name": "RejectApplication",
"type": "operation",
"actionMode": "sequential",
"actions": [
{
"functionRef": {
"refName": "sendRejectionEmailFunction",
"parameters": {
"applicant": "${ .applicant }"
}
}
}
],
"end": {
"terminate": true
}
}
]
}
23 changes: 23 additions & 0 deletions parser/testdata/workflows/urifiles/auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2022 The Serverless Workflow Specification Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: testAuth
properties:
token: test_token
scheme: bearer
- name: testAuth2
properties:
password: test_pwd
username: test_user
scheme: basic
53 changes: 53 additions & 0 deletions test/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2022 The Serverless Workflow Specification Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
"os"
"path/filepath"
"runtime"

"github.com/pkg/errors"
)

// CurrentProjectPath get the project root path
func CurrentProjectPath() string {
path := currentFilePath()

ppath, err := filepath.Abs(filepath.Join(filepath.Dir(path), "../"))
if err != nil {
panic(errors.Wrapf(err, "Get current project path with %s failed", path))
}

f, err := os.Stat(ppath)
if err != nil {
panic(errors.Wrapf(err, "Stat project path %v failed", ppath))
}

if f.Mode()&os.ModeSymlink != 0 {
fpath, err := os.Readlink(ppath)
if err != nil {
panic(errors.Wrapf(err, "Readlink from path %v failed", fpath))
}
ppath = fpath
}

return ppath
}

func currentFilePath() string {
_, file, _, _ := runtime.Caller(1)
return file
}
31 changes: 31 additions & 0 deletions test/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2022 The Serverless Workflow Specification Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCurrentProjectPath(t *testing.T) {
t.Run("normal test", func(t *testing.T) {
path := CurrentProjectPath()

// NOTE: the '/code' path is used with code pipeline.
// When code running in the pipeline, the codebase will copy to /home/code directory.
assert.Regexp(t, "(/sdk-go$)|(/code$)", path)
})
}