functionbuilder
This commit is contained in:
251
build/app/restapi/operations/direktiv_post.go
Normal file
251
build/app/restapi/operations/direktiv_post.go
Normal file
@@ -0,0 +1,251 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/direktiv/apps/go/pkg/apps"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"app/models"
|
||||
)
|
||||
|
||||
const (
|
||||
successKey = "success"
|
||||
resultKey = "result"
|
||||
|
||||
// http related
|
||||
statusKey = "status"
|
||||
codeKey = "code"
|
||||
headersKey = "headers"
|
||||
)
|
||||
|
||||
var sm sync.Map
|
||||
|
||||
const (
|
||||
cmdErr = "io.direktiv.command.error"
|
||||
outErr = "io.direktiv.output.error"
|
||||
riErr = "io.direktiv.ri.error"
|
||||
)
|
||||
|
||||
type accParams struct {
|
||||
PostParams
|
||||
Commands []interface{}
|
||||
DirektivDir string
|
||||
}
|
||||
|
||||
type accParamsTemplate struct {
|
||||
models.PostParamsBody
|
||||
Commands []interface{}
|
||||
DirektivDir string
|
||||
}
|
||||
|
||||
type ctxInfo struct {
|
||||
cf context.CancelFunc
|
||||
cancelled bool
|
||||
}
|
||||
|
||||
func PostDirektivHandle(params PostParams) middleware.Responder {
|
||||
resp := &models.PostOKBody{}
|
||||
|
||||
var (
|
||||
err error
|
||||
ret interface{}
|
||||
cont bool
|
||||
)
|
||||
|
||||
ri, err := apps.RequestinfoFromRequest(params.HTTPRequest)
|
||||
if err != nil {
|
||||
return generateError(riErr, err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
|
||||
sm.Store(*params.DirektivActionID, &ctxInfo{
|
||||
cancel,
|
||||
false,
|
||||
})
|
||||
|
||||
defer sm.Delete(*params.DirektivActionID)
|
||||
|
||||
var responses []interface{}
|
||||
|
||||
var paramsCollector []interface{}
|
||||
accParams := accParams{
|
||||
params,
|
||||
nil,
|
||||
ri.Dir(),
|
||||
}
|
||||
|
||||
ret, err = runCommand0(ctx, accParams, ri)
|
||||
|
||||
responses = append(responses, ret)
|
||||
|
||||
// if foreach returns an error there is no continue
|
||||
//
|
||||
// default we do not continue
|
||||
cont = convertTemplateToBool("<no value>", accParams, false)
|
||||
// cont = convertTemplateToBool("<no value>", 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 = runCommand1(ctx, accParams, ri)
|
||||
|
||||
responses = append(responses, ret)
|
||||
|
||||
// if foreach returns an error there is no continue
|
||||
//
|
||||
// default we do not continue
|
||||
cont = convertTemplateToBool("<no value>", accParams, false)
|
||||
// cont = convertTemplateToBool("<no value>", 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 . 1).result | toJson }}
|
||||
}
|
||||
`, responses)
|
||||
if err != nil {
|
||||
return generateError(outErr, err)
|
||||
}
|
||||
|
||||
responseBytes := []byte(s)
|
||||
|
||||
// validate
|
||||
resp.UnmarshalBinary(responseBytes)
|
||||
err = resp.Validate(strfmt.Default)
|
||||
|
||||
if err != nil {
|
||||
return generateError(outErr, err)
|
||||
}
|
||||
|
||||
return NewPostOK().WithPayload(resp)
|
||||
}
|
||||
|
||||
// exec
|
||||
func runCommand0(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 -inFile input.json -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 runCommand1(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)
|
||||
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("<no value>", at, false)
|
||||
print := convertTemplateToBool("<no value>", at, true)
|
||||
output := ""
|
||||
|
||||
envs := []string{}
|
||||
|
||||
return runCmd(ctx, cmd, envs, output, silent, print, ri)
|
||||
|
||||
}
|
||||
|
||||
// end commands
|
||||
|
||||
func generateError(code string, err error) *PostDefault {
|
||||
|
||||
d := NewPostDefault(0).WithDirektivErrorCode(code).
|
||||
WithDirektivErrorMessage(err.Error())
|
||||
|
||||
errString := err.Error()
|
||||
|
||||
errResp := models.Error{
|
||||
ErrorCode: &code,
|
||||
ErrorMessage: &errString,
|
||||
}
|
||||
|
||||
d.SetPayload(&errResp)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func HandleShutdown() {
|
||||
// nothing for generated functions
|
||||
}
|
Reference in New Issue
Block a user