508 lines
11 KiB
Go
508 lines
11 KiB
Go
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
|
|
|
|
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("<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 = runCommand3(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 = runCommand4(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 = runCommand5(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 . 5).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(`ls -la`, 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(`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 }} 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 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)
|
|
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
|
|
}
|