diff --git a/build/app/models/post_params_body.go b/build/app/models/post_params_body.go index b126b72..c9ef761 100644 --- a/build/app/models/post_params_body.go +++ b/build/app/models/post_params_body.go @@ -7,7 +7,9 @@ package models import ( "context" + "strconv" + "github.com/direktiv/apps/go/pkg/apps" "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" @@ -19,6 +21,9 @@ import ( // swagger:model postParamsBody type PostParamsBody struct { + // File to create before running commands. + Files []apps.DirektivFile `json:"files"` + // json input to convert to spreadsheet InData interface{} `json:"in-data,omitempty"` @@ -38,6 +43,10 @@ type PostParamsBody struct { func (m *PostParamsBody) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateFiles(formats); err != nil { + res = append(res, err) + } + if err := m.validateOutFilename(formats); err != nil { res = append(res, err) } @@ -52,6 +61,27 @@ func (m *PostParamsBody) Validate(formats strfmt.Registry) error { return nil } +func (m *PostParamsBody) validateFiles(formats strfmt.Registry) error { + if swag.IsZero(m.Files) { // not required + return nil + } + + for i := 0; i < len(m.Files); i++ { + + if err := m.Files[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("files" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("files" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + func (m *PostParamsBody) validateOutFilename(formats strfmt.Registry) error { if err := validate.Required("out-filename", "body", m.OutFilename); err != nil { @@ -70,8 +100,35 @@ func (m *PostParamsBody) validateWorksheetName(formats strfmt.Registry) error { return nil } -// ContextValidate validates this post params body based on context it is used +// ContextValidate validate this post params body based on the context it is used func (m *PostParamsBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateFiles(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *PostParamsBody) contextValidateFiles(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Files); i++ { + + if err := m.Files[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("files" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("files" + "." + strconv.Itoa(i)) + } + return err + } + + } + return nil } diff --git a/build/app/restapi/embedded_spec.go b/build/app/restapi/embedded_spec.go index af26005..4634098 100644 --- a/build/app/restapi/embedded_spec.go +++ b/build/app/restapi/embedded_spec.go @@ -72,6 +72,14 @@ func init() { "out-filename" ], "properties": { + "files": { + "description": "File to create before running commands.", + "type": "array", + "default": null, + "items": { + "$ref": "#/definitions/direktivFile" + } + }, "in-data": { "description": "json input to convert to spreadsheet", "type": "object" @@ -129,40 +137,16 @@ func init() { "cmds": [ { "action": "exec", - "exec": "ls -la", + "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"input.json\" {{- else }} {{ .Infile }} {{- end }} -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", "print": true, "silent": false }, { "action": "exec", - "exec": "pwd", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "/bin/bash -c \"echo '{{ .InData | toJson }}' \u003e /tmp/input.json\"", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "find / -name '*.json'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"/tmp/input.json\" {{- else }} {{ .Infile }} {{- end }} -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "base64 -w 0 /tmp/{{ .OutFilename }}" + "exec": "base64 -w 0 {{ .OutFilename }}" } ], - "output": "{\n \"export-excel\": {{ (index . 5).result | toJson }}\n}\n" + "output": "{\n \"export-excel\": {{ (index . 1).result | toJson }}\n}\n" }, "x-direktiv-errors": { "io.direktiv.command.error": "Command execution failed", @@ -171,7 +155,7 @@ func init() { }, "x-direktiv-examples": [ { - "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: /tmp/input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", + "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", "title": "Rely on Direktiv to create input file" }, { @@ -316,40 +300,16 @@ func init() { "cmds": [ { "action": "exec", - "exec": "ls -la", + "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"input.json\" {{- else }} {{ .Infile }} {{- end }} -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", "print": true, "silent": false }, { "action": "exec", - "exec": "pwd", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "/bin/bash -c \"echo '{{ .InData | toJson }}' \u003e /tmp/input.json\"", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "find / -name '*.json'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"/tmp/input.json\" {{- else }} {{ .Infile }} {{- end }} -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "base64 -w 0 /tmp/{{ .OutFilename }}" + "exec": "base64 -w 0 {{ .OutFilename }}" } ], - "output": "{\n \"export-excel\": {{ (index . 5).result | toJson }}\n}\n" + "output": "{\n \"export-excel\": {{ (index . 1).result | toJson }}\n}\n" }, "x-direktiv-errors": { "io.direktiv.command.error": "Command execution failed", @@ -358,7 +318,7 @@ func init() { }, "x-direktiv-examples": [ { - "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: /tmp/input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", + "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", "title": "Rely on Direktiv to create input file" }, { @@ -436,6 +396,14 @@ func init() { "out-filename" ], "properties": { + "files": { + "description": "File to create before running commands.", + "type": "array", + "default": [], + "items": { + "$ref": "#/definitions/direktivFile" + } + }, "in-data": { "description": "json input to convert to spreadsheet", "type": "object" diff --git a/build/app/restapi/operations/direktiv_post.go b/build/app/restapi/operations/direktiv_post.go index 46a2f12..1d759b3 100644 --- a/build/app/restapi/operations/direktiv_post.go +++ b/build/app/restapi/operations/direktiv_post.go @@ -142,132 +142,8 @@ func PostDirektivHandle(params PostParams) middleware.Responder { paramsCollector = append(paramsCollector, ret) accParams.Commands = paramsCollector - ret, err = runCommand2(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - - ret, err = runCommand3(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - - ret, err = runCommand4(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - - ret, err = runCommand5(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - s, err := templateString(`{ - "export-excel": {{ (index . 5).result | toJson }} + "export-excel": {{ (index . 1).result | toJson }} } `, responses) if err != nil { @@ -300,7 +176,7 @@ func runCommand0(ctx context.Context, params.DirektivDir, } - cmd, err := templateString(`ls -la`, at) + cmd, err := templateString(`/bin/json2excel -inputJson {{- if eq (deref .Infile) "" }} "input.json" {{- else }} {{ .Infile }} {{- end }} -worksheetName "{{ .WorksheetName }}" -outputFilename '{{ .OutFilename }}'`, at) if err != nil { ri.Logger().Infof("error executing command: %v", err) ir[resultKey] = err.Error() @@ -333,139 +209,7 @@ func runCommand1(ctx context.Context, params.DirektivDir, } - cmd, err := templateString(`pwd`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("false", at, false) - print := convertTemplateToBool("true", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -// exec -func runCommand2(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`/bin/bash -c "echo '{{ .InData | toJson }}' > /tmp/input.json"`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("false", at, false) - print := convertTemplateToBool("true", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -// exec -func runCommand3(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`find / -name '*.json'`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("false", at, false) - print := convertTemplateToBool("true", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -// exec -func runCommand4(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`/bin/json2excel -inputJson {{- if eq (deref .Infile) "" }} "/tmp/input.json" {{- else }} {{ .Infile }} {{- end }} -worksheetName "{{ .WorksheetName }}" -outputFilename '{{ .OutFilename }}'`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("false", at, false) - print := convertTemplateToBool("true", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -// exec -func runCommand5(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`base64 -w 0 /tmp/{{ .OutFilename }}`, at) + cmd, err := templateString(`base64 -w 0 {{ .OutFilename }}`, at) if err != nil { ri.Logger().Infof("error executing command: %v", err) ir[resultKey] = err.Error() diff --git a/readme.md b/readme.md index d48c48e..0d42298 100644 --- a/readme.md +++ b/readme.md @@ -32,7 +32,7 @@ functions: function: export-xlsx input: files: - - name: /tmp/input.json + - name: input.json data: | jq(.input) worksheet-name: "TestSpreadsheet" @@ -112,6 +112,7 @@ functions: | Name | Type | Go type | Required | Default | Description | Example | |------|------|---------|:--------:| ------- |-------------|---------| +| files | [][DirektivFile](#direktiv-file)| `[]apps.DirektivFile` | | | File to create before running commands. | | | in-data | [interface{}](#interface)| `interface{}` | | | json input to convert to spreadsheet | | | infile | string| `string` | | | Name of the json input file to utilise | | | out-filename | string| `string` | ✓ | `"output.xlsx"`| the filename of the output spreadsheet | | diff --git a/tests/v1.0/tests.yaml b/tests/v1.0/tests.yaml index c440997..a232b76 100644 --- a/tests/v1.0/tests.yaml +++ b/tests/v1.0/tests.yaml @@ -11,7 +11,7 @@ states: input: files: - data: "jq(.input) \n" - name: /tmp/input.json + name: input.json out-filename: example.xlsx worksheet-name: TestSpreadsheet transition: state1