#444: Fixed basic pieces for user input trigger to run open source standalone
This commit is contained in:
@@ -65,17 +65,19 @@ class AppBase:
|
||||
# Checks output for whether it should be automatically parsed or not
|
||||
def run_magic_parser(self, input_data):
|
||||
if not isinstance(input_data, str):
|
||||
self.logger.info("[DEBUG] Not string. Returning from magic")
|
||||
return input_data
|
||||
|
||||
# Don't touch existing JSON/lists
|
||||
if (input_data.startswith("[") and input_data.endswith("]")) or (input_data.startswith("{") and input_data.endswith("}")):
|
||||
self.logger.info("[DEBUG] Already JSON-like. Returning from magic")
|
||||
return input_data
|
||||
|
||||
# Don't touch large data.
|
||||
if len(input_data) > 100000:
|
||||
self.logger.info("[DEBUG] Value too large. Returning from magic")
|
||||
return input_data
|
||||
|
||||
|
||||
new_input = input_data
|
||||
try:
|
||||
#new_input.strip()
|
||||
@@ -91,6 +93,7 @@ class AppBase:
|
||||
splititem = ","
|
||||
else:
|
||||
new_return.append(item)
|
||||
|
||||
index += 1
|
||||
continue
|
||||
|
||||
@@ -102,6 +105,7 @@ class AppBase:
|
||||
|
||||
# Prevent large data or infinite loops
|
||||
if index > 10000:
|
||||
self.logger.info(f"[DEBUG] Infinite loop. Returning default data.")
|
||||
return input_data
|
||||
|
||||
fixed_return = []
|
||||
@@ -120,13 +124,13 @@ class AppBase:
|
||||
|
||||
new_input = fixed_return
|
||||
except Exception as e:
|
||||
self.logger.info(f"[DEBUG] Failed to run magic parser (2): {e}")
|
||||
self.logger.info(f"[ERROR] Failed to run magic parser (2): {e}")
|
||||
return input_data
|
||||
|
||||
try:
|
||||
new_input = input_data.split()
|
||||
except Exception as e:
|
||||
self.logger.info(f"[DEBUG] Failed to run magic parser (1): {e}")
|
||||
self.logger.info(f"[ERROR] Failed to run magic parser (1): {e}")
|
||||
return input_data
|
||||
|
||||
# Won't ever touch this one?
|
||||
@@ -134,7 +138,7 @@ class AppBase:
|
||||
try:
|
||||
return json.dumps(new_input)
|
||||
except Exception as e:
|
||||
self.logger.info(f"[DEBUG] Failed to run magic parser: {e}")
|
||||
self.logger.info(f"[ERROR] Failed to run magic parser: {e}")
|
||||
|
||||
return new_input
|
||||
|
||||
@@ -145,13 +149,14 @@ class AppBase:
|
||||
action_result["status"] = "FAILURE"
|
||||
|
||||
try:
|
||||
if self.original_action["run_magic_output"] == True:
|
||||
self.logger.warning("[INFO] Action result ran with Magic parser output.")
|
||||
#self.logger.info(f"[DEBUG] ACTION: {self.action}")
|
||||
if self.action["run_magic_output"] == True:
|
||||
self.logger.warning(f"[INFO] Action result ran with Magic parser output.")
|
||||
action_result["result"] = self.run_magic_parser(action_result["result"])
|
||||
else:
|
||||
self.logger.warning("[ERROR] Magic output not defined.")
|
||||
self.logger.warning(f"[ERROR] Magic output not defined.")
|
||||
except Exception as e:
|
||||
self.logger.warning("[ERROR] Failed to run magic autoparser: {e}")
|
||||
self.logger.warning(f"[ERROR] Failed to run magic autoparser: {e}")
|
||||
pass
|
||||
|
||||
# Try it with some magic
|
||||
|
||||
+42
-17
@@ -366,7 +366,7 @@ func handleGetStreamResults(resp http.ResponseWriter, request *http.Request) {
|
||||
ctx := context.Background()
|
||||
workflowExecution, err := shuffle.GetWorkflowExecution(ctx, actionResult.ExecutionId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting execution (streamresult) %s: %s", actionResult.ExecutionId, err)
|
||||
log.Printf("[WARNING] Failed getting execution (streamresult) %s: %s", actionResult.ExecutionId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad authorization key or execution_id might not exist."}`)))
|
||||
return
|
||||
@@ -494,7 +494,9 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
||||
err := handleUserInput(trigger, orgId, workflowExecution.Workflow.ID, workflowExecution.ExecutionId)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed userinput handler: %s", err)
|
||||
actionResult.Result = fmt.Sprintf("Cloud error: %s", err)
|
||||
|
||||
actionResult.Result = fmt.Sprintf(`{"success": False, "reason": "%s"}`, err)
|
||||
|
||||
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
||||
workflowExecution.Status = "ABORTED"
|
||||
err = shuffle.SetWorkflowExecution(ctx, *workflowExecution, true)
|
||||
@@ -506,12 +508,13 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error: %s"}`, err)))
|
||||
return
|
||||
} else {
|
||||
log.Printf("[INFO] Successful userinput handler")
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "CLOUD IS DONE"}`)))
|
||||
|
||||
actionResult.Result = "Waiting for user feedback based on configuration"
|
||||
actionResult.Result = `{"success": True, "reason": "Waiting for user feedback based on configuration"}`
|
||||
|
||||
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
||||
workflowExecution.Status = actionResult.Status
|
||||
@@ -519,7 +522,7 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed setting userinput: %s", err)
|
||||
} else {
|
||||
log.Printf("Successfully set the execution to waiting.")
|
||||
log.Printf("[DEBUG] Successfully set the execution to waiting.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1035,13 +1038,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Api authentication failed in execute workflow: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
user, userErr := shuffle.HandleApiAuthentication(resp, request)
|
||||
|
||||
if user.Role == "org-reader" {
|
||||
log.Printf("[WARNING] Org-reader doesn't have access to run workflow: %s (%s)", user.Username, user.Id)
|
||||
@@ -1079,14 +1076,38 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if user.Id != workflow.Owner && user.Role != "scheduler" && user.Role != fmt.Sprintf("workflow_%s", fileId) {
|
||||
if workflow.OrgId == user.ActiveOrg.Id && user.Role == "admin" {
|
||||
log.Printf("[AUDIT] Letting user %s execute %s because they're admin of the same org", user.Username, workflow.ID)
|
||||
} else {
|
||||
log.Printf("[AUDIT] Wrong user (%s) for workflow %s (execute)", user.Username, workflow.ID)
|
||||
executionAuthValid := false
|
||||
newOrgId := ""
|
||||
if userErr != nil {
|
||||
// Check if the execution data has correct info in it! Happens based on subflows.
|
||||
// 1. Parent workflow contains this workflow ID in the source trigger?
|
||||
// 2. Parent workflow's owner is same org?
|
||||
// 3. Parent execution auth is correct
|
||||
|
||||
executionAuthValid, newOrgId = shuffle.RunExecuteAccessValidation(request, workflow)
|
||||
if !executionAuthValid {
|
||||
log.Printf("[INFO] Api authentication failed in execute workflow: %s", userErr)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
} else {
|
||||
log.Printf("[DEBUG] Execution of %s successfully validated and started based on subflow or user input execution", workflow.ID)
|
||||
user.ActiveOrg = shuffle.OrgMini{
|
||||
Id: newOrgId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !executionAuthValid {
|
||||
if user.Id != workflow.Owner && user.Role != "scheduler" && user.Role != fmt.Sprintf("workflow_%s", fileId) {
|
||||
if workflow.OrgId == user.ActiveOrg.Id && user.Role == "admin" {
|
||||
log.Printf("[AUDIT] Letting user %s execute %s because they're admin of the same org", user.Username, workflow.ID)
|
||||
} else {
|
||||
log.Printf("[AUDIT] Wrong user (%s) for workflow %s (execute)", user.Username, workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2419,6 +2440,7 @@ func handleUserInput(trigger shuffle.Trigger, organizationId string, workflowId
|
||||
// E.g. check email
|
||||
sms := ""
|
||||
email := ""
|
||||
subflow := ""
|
||||
triggerType := ""
|
||||
triggerInformation := ""
|
||||
for _, item := range trigger.Parameters {
|
||||
@@ -2430,11 +2452,14 @@ func handleUserInput(trigger shuffle.Trigger, organizationId string, workflowId
|
||||
email = item.Value
|
||||
} else if item.Name == "sms" {
|
||||
sms = item.Value
|
||||
} else if item.Name == "subflow" {
|
||||
subflow = item.Value
|
||||
}
|
||||
}
|
||||
_ = subflow
|
||||
|
||||
if len(triggerType) == 0 {
|
||||
log.Printf("No type specified for user input node")
|
||||
log.Printf("[WARNING] No type specified for user input node")
|
||||
return errors.New("No type specified for user input node")
|
||||
}
|
||||
|
||||
|
||||
@@ -8705,6 +8705,11 @@ const AngularWorkflow = (props) => {
|
||||
name: "sms",
|
||||
value: "0000000",
|
||||
};
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5] = {
|
||||
name: "subflow",
|
||||
value: "",
|
||||
};
|
||||
|
||||
setWorkflow(workflow);
|
||||
}
|
||||
|
||||
@@ -8807,7 +8812,7 @@ const AngularWorkflow = (props) => {
|
||||
}}
|
||||
/>
|
||||
<div style={{ flex: "10" }}>
|
||||
<b>Information: </b>
|
||||
<b>Information</b>
|
||||
</div>
|
||||
</div>
|
||||
<TextField
|
||||
@@ -8853,13 +8858,33 @@ const AngularWorkflow = (props) => {
|
||||
}}
|
||||
/>
|
||||
<div style={{ flex: "10" }}>
|
||||
<b>Contact options: </b>
|
||||
<b>Contact options</b>
|
||||
</div>
|
||||
</div>
|
||||
<FormGroup
|
||||
style={{ paddingLeft: 10, backgroundColor: inputColor }}
|
||||
row
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={
|
||||
workflow.triggers[selectedTriggerIndex].parameters[2] !==
|
||||
undefined &&
|
||||
workflow.triggers[
|
||||
selectedTriggerIndex
|
||||
].parameters[2].value.includes("subflow")
|
||||
}
|
||||
onChange={() => {
|
||||
setTriggerOptionsWrapper("subflow");
|
||||
}}
|
||||
color="primary"
|
||||
value="subflow"
|
||||
disabled
|
||||
/>
|
||||
}
|
||||
label={<div style={{ color: "white" }}>Subflow</div>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -8916,6 +8941,7 @@ const AngularWorkflow = (props) => {
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
required
|
||||
placeholder={"mail1@company.com,mail2@company.com"}
|
||||
defaultValue={
|
||||
workflow.triggers[selectedTriggerIndex].parameters[3].value
|
||||
@@ -8960,6 +8986,39 @@ const AngularWorkflow = (props) => {
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{workflow.triggers[selectedTriggerIndex].parameters[2] !==
|
||||
undefined &&
|
||||
workflow.triggers[
|
||||
selectedTriggerIndex
|
||||
].parameters[2].value.includes("subflow") ? (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"ID of another workflow"}
|
||||
defaultValue={
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5].value
|
||||
}
|
||||
onBlur={(event) => {
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5].value =
|
||||
event.target.value;
|
||||
setWorkflow(workflow);
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -400,7 +400,7 @@ export const validateJson = (showResult) => {
|
||||
try {
|
||||
result = jsonvalid ? JSON.parse(showResult) : showResult;
|
||||
} catch (e) {
|
||||
//console.log("Failed parsing JSON even though its valid: ", e)
|
||||
////console.log("Failed parsing JSON even though its valid: ", e)
|
||||
jsonvalid = false;
|
||||
}
|
||||
|
||||
@@ -413,12 +413,12 @@ export const validateJson = (showResult) => {
|
||||
try {
|
||||
var newstr = showResult.replaceAll("'", '"')
|
||||
|
||||
console.log("Try replacements and trimming with new value: ", newstr)
|
||||
//console.log("Try replacements and trimming with new value: ", newstr)
|
||||
result = JSON.parse(newstr)
|
||||
jsonvalid = true
|
||||
} catch (e) {
|
||||
|
||||
console.log("Failed parsing JSON even though its valid (2): ", e)
|
||||
//console.log("Failed parsing JSON even though its valid (2): ", e)
|
||||
jsonvalid = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-worker
|
||||
VERSION=0.9.36
|
||||
VERSION=0.9.40
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin .
|
||||
|
||||
@@ -10,6 +10,6 @@ require (
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/shuffle/shuffle-shared v0.1.35
|
||||
github.com/shuffle/shuffle-shared v0.1.55
|
||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||
)
|
||||
|
||||
@@ -574,6 +574,10 @@ github.com/shuffle/shuffle-shared v0.1.33 h1:1U0yKWNfW7K7EKOj2aqSmd20UIA+nJeIurG
|
||||
github.com/shuffle/shuffle-shared v0.1.33/go.mod h1:0QrK51T12CpCj/be8hXduj/RtDnoeaZ3rfogELZE2IU=
|
||||
github.com/shuffle/shuffle-shared v0.1.35 h1:CoCur/G+TaM2xiLgDCVdVxPhFffNK/4YRWTtzRBprvg=
|
||||
github.com/shuffle/shuffle-shared v0.1.35/go.mod h1:2ndjLm4ZOvY6arGFwOgGnkQ457Ke7gka9HDF/EkdIxQ=
|
||||
github.com/shuffle/shuffle-shared v0.1.54 h1:dHpwot+5RPX8k9EC/8Yd+QYsFqCsqsv+J1wC+EtGxzI=
|
||||
github.com/shuffle/shuffle-shared v0.1.54/go.mod h1:2ndjLm4ZOvY6arGFwOgGnkQ457Ke7gka9HDF/EkdIxQ=
|
||||
github.com/shuffle/shuffle-shared v0.1.55 h1:feHtTN7Uhr1aMxkMIo3xZbr97599VB2eLekogTj/9Z4=
|
||||
github.com/shuffle/shuffle-shared v0.1.55/go.mod h1:2ndjLm4ZOvY6arGFwOgGnkQ457Ke7gka9HDF/EkdIxQ=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
|
||||
@@ -82,6 +82,12 @@ var executedIds = []string{}
|
||||
var portMappings map[string]int
|
||||
var baseport = 33333
|
||||
|
||||
type UserInputSubflow struct {
|
||||
Argument string `json:"execution_argument"`
|
||||
ContinueUrl string `json:"continue_url"`
|
||||
CancelUrl string `json:"cancel_url"`
|
||||
}
|
||||
|
||||
// removes every container except itself (worker)
|
||||
func shutdown(workflowExecution shuffle.WorkflowExecution, nodeId string, reason string, handleResultSend bool) {
|
||||
log.Printf("[INFO] Shutdown (%s) started with reason %#v. Result amount: %d. ResultsSent: %d, Send result: %#v", workflowExecution.Status, reason, len(workflowExecution.Results), requestsSent, handleResultSend)
|
||||
@@ -642,6 +648,11 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
ctx := context.Background()
|
||||
startAction, extra, children, parents, visited, executed, nextActions, environments := shuffle.GetExecutionVariables(ctx, workflowExecution.ExecutionId)
|
||||
log.Printf("[DEBUG] Getting info for %s. Extra: %d", workflowExecution.ExecutionId, extra)
|
||||
dockercli, err := dockerclient.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Unable to create docker client (3): %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Inside execution results with %d / %d results", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extra)
|
||||
|
||||
@@ -865,6 +876,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
}
|
||||
|
||||
// FIXME: Add startnode from frontend
|
||||
action.Label = trigger.Label
|
||||
action.Parameters = []shuffle.WorkflowAppActionParameter{}
|
||||
for _, parameter := range trigger.Parameters {
|
||||
parameter.Variant = "STATIC_VALUE"
|
||||
@@ -900,15 +912,15 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
//}
|
||||
//continue
|
||||
} else if action.AppName == "User Input" {
|
||||
log.Printf("USER INPUT!")
|
||||
log.Printf("[DEBUG] RUNNING USER INPUT!")
|
||||
|
||||
if action.ID == workflowExecution.Start {
|
||||
log.Printf("Skipping because it's the startnode")
|
||||
log.Printf("[DEBUG] Skipping user input because it's the startnode")
|
||||
visited = append(visited, action.ID)
|
||||
executed = append(executed, action.ID)
|
||||
continue
|
||||
} else {
|
||||
log.Printf("Should stop after this iteration because it's user-input based. %#v", action)
|
||||
log.Printf("[DEBUG] Should stop after this iteration because it's user-input based. %#v", action)
|
||||
trigger := shuffle.Trigger{}
|
||||
for _, innertrigger := range workflowExecution.Workflow.Triggers {
|
||||
if innertrigger.ID == action.ID {
|
||||
@@ -917,14 +929,23 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
}
|
||||
}
|
||||
|
||||
action.Label = action.Label
|
||||
action.Parameters = []shuffle.WorkflowAppActionParameter{}
|
||||
for _, parameter := range trigger.Parameters {
|
||||
action.Parameters = append(action.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: parameter.Name,
|
||||
Value: parameter.Value,
|
||||
})
|
||||
}
|
||||
|
||||
trigger.LargeImage = ""
|
||||
triggerData, err := json.Marshal(trigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed unmarshalling action: %s", err)
|
||||
log.Printf("[WARNING] Failed unmarshalling action: %s", err)
|
||||
triggerData = []byte("Failed unmarshalling. Cancel execution!")
|
||||
}
|
||||
|
||||
err = runUserInput(topClient, action, workflowExecution.Workflow.ID, workflowExecution.ExecutionId, workflowExecution.Authorization, string(triggerData))
|
||||
err = runUserInput(topClient, action, workflowExecution.Workflow.ID, workflowExecution, workflowExecution.Authorization, string(triggerData), dockercli)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed launching backend magic: %s", err)
|
||||
os.Exit(3)
|
||||
@@ -1025,12 +1046,6 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
//executed = append(executed, action.ID)
|
||||
|
||||
// FIXME - check whether it's running locally yet too
|
||||
dockercli, err := dockerclient.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Unable to create docker client (2): %s", err)
|
||||
//return err
|
||||
continue
|
||||
}
|
||||
|
||||
stats, err := dockercli.ContainerInspect(context.Background(), identifier)
|
||||
if err != nil || stats.ContainerJSONBase.State.Status != "running" {
|
||||
@@ -1328,7 +1343,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
|
||||
// FIXME - new request here
|
||||
// FIXME - clean up stopped (remove) containers with this execution id
|
||||
err := shuffle.UpdateExecutionVariables(ctx, workflowExecution.ExecutionId, startAction, children, parents, visited, executed, nextActions, environments, extra)
|
||||
err = shuffle.UpdateExecutionVariables(ctx, workflowExecution.ExecutionId, startAction, children, parents, visited, executed, nextActions, environments, extra)
|
||||
if err != nil {
|
||||
log.Printf("\n\n[ERROR] Failed to update exec variables for execution %s: %s (2)\n\n", workflowExecution.ExecutionId, err)
|
||||
}
|
||||
@@ -1661,31 +1676,32 @@ func runSkipAction(client *http.Client, action shuffle.Action, workflowId, workf
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error building test request (0): %s", err)
|
||||
log.Printf("[WARNING] Error building skip request (0): %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
newresp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error running test request (0): %s", err)
|
||||
log.Printf("[WARNING] Error running skip request (0): %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(newresp.Body)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed reading body when waiting (0): %s", err)
|
||||
log.Printf("[WARNING] Failed reading body when skipping (0): %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[INFO] User Input Body: %s", string(body))
|
||||
log.Printf("[INFO] Skip Action Body: %s", string(body))
|
||||
return nil
|
||||
}
|
||||
|
||||
func runUserInput(client *http.Client, action shuffle.Action, workflowId, workflowExecutionId, authorization string, configuration string) error {
|
||||
// Sends request back to backend to handle the node
|
||||
func runUserInput(client *http.Client, action shuffle.Action, workflowId string, workflowExecution shuffle.WorkflowExecution, authorization string, configuration string, dockercli *dockerclient.Client) error {
|
||||
timeNow := time.Now().Unix()
|
||||
result := shuffle.ActionResult{
|
||||
Action: action,
|
||||
ExecutionId: workflowExecutionId,
|
||||
ExecutionId: workflowExecution.ExecutionId,
|
||||
Authorization: authorization,
|
||||
Result: configuration,
|
||||
StartedAt: timeNow,
|
||||
@@ -1693,6 +1709,118 @@ func runUserInput(client *http.Client, action shuffle.Action, workflowId, workfl
|
||||
Status: "WAITING",
|
||||
}
|
||||
|
||||
// Checking for userinput to deploy subflow for it
|
||||
subflow := false
|
||||
subflowId := ""
|
||||
argument := ""
|
||||
continueUrl := "testing continue"
|
||||
cancelUrl := "testing cancel"
|
||||
for _, item := range action.Parameters {
|
||||
if item.Name == "subflow" {
|
||||
subflow = true
|
||||
subflowId = item.Value
|
||||
} else if item.Name == "alertinfo" {
|
||||
argument = item.Value
|
||||
}
|
||||
}
|
||||
|
||||
if subflow {
|
||||
log.Printf("[DEBUG] Should run action with subflow app with argument %#v", argument)
|
||||
newAction := shuffle.Action{
|
||||
AppName: "shuffle-subflow",
|
||||
Name: "run_subflow",
|
||||
AppVersion: "1.0.0",
|
||||
Label: "User Input Subflow Execution",
|
||||
}
|
||||
|
||||
identifier := fmt.Sprintf("%s_%s_%s_%s", newAction.AppName, newAction.AppVersion, action.ID, workflowExecution.ExecutionId)
|
||||
if strings.Contains(identifier, " ") {
|
||||
identifier = strings.ReplaceAll(identifier, " ", "-")
|
||||
}
|
||||
|
||||
inputValue := UserInputSubflow{
|
||||
Argument: argument,
|
||||
ContinueUrl: continueUrl,
|
||||
CancelUrl: cancelUrl,
|
||||
}
|
||||
|
||||
parsedArgument, err := json.Marshal(inputValue)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to parse arguments: %s", err)
|
||||
parsedArgument = []byte(argument)
|
||||
}
|
||||
|
||||
newAction.Parameters = []shuffle.WorkflowAppActionParameter{
|
||||
shuffle.WorkflowAppActionParameter{
|
||||
Name: "user_apikey",
|
||||
Value: workflowExecution.Authorization,
|
||||
},
|
||||
shuffle.WorkflowAppActionParameter{
|
||||
Name: "workflow",
|
||||
Value: subflowId,
|
||||
},
|
||||
shuffle.WorkflowAppActionParameter{
|
||||
Name: "argument",
|
||||
Value: string(parsedArgument),
|
||||
},
|
||||
}
|
||||
|
||||
newAction.Parameters = append(newAction.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: "source_workflow",
|
||||
Value: workflowExecution.Workflow.ID,
|
||||
})
|
||||
|
||||
newAction.Parameters = append(newAction.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: "source_execution",
|
||||
Value: workflowExecution.ExecutionId,
|
||||
})
|
||||
|
||||
newAction.Parameters = append(newAction.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: "source_node",
|
||||
Value: action.ID,
|
||||
})
|
||||
|
||||
newAction.Parameters = append(newAction.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: "source_auth",
|
||||
Value: workflowExecution.Authorization,
|
||||
})
|
||||
|
||||
newAction.Parameters = append(newAction.Parameters, shuffle.WorkflowAppActionParameter{
|
||||
Name: "startnode",
|
||||
Value: "",
|
||||
})
|
||||
|
||||
// If cleanup is set, it should run for efficiency
|
||||
//appName := strings.Replace(identifier, fmt.Sprintf("_%s", action.ID), "", -1)
|
||||
//appName = strings.Replace(appName, fmt.Sprintf("_%s", workflowExecution.ExecutionId), "", -1)
|
||||
actionData, err := json.Marshal(newAction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env := []string{
|
||||
fmt.Sprintf("ACTION=%s", string(actionData)),
|
||||
fmt.Sprintf("EXECUTIONID=%s", workflowExecution.ExecutionId),
|
||||
fmt.Sprintf("AUTHORIZATION=%s", workflowExecution.Authorization),
|
||||
fmt.Sprintf("CALLBACK_URL=%s", baseUrl),
|
||||
fmt.Sprintf("BASE_URL=%s", appCallbackUrl),
|
||||
fmt.Sprintf("TZ=%s", timezone),
|
||||
}
|
||||
|
||||
if strings.ToLower(os.Getenv("SHUFFLE_PASS_APP_PROXY")) == "true" {
|
||||
//log.Printf("APPENDING PROXY TO THE APP!")
|
||||
env = append(env, fmt.Sprintf("HTTP_PROXY=%s", os.Getenv("HTTP_PROXY")))
|
||||
env = append(env, fmt.Sprintf("HTTPS_PROXY=%s", os.Getenv("HTTPS_PROXY")))
|
||||
}
|
||||
|
||||
err = deployApp(dockercli, "frikky/shuffle:shuffle-subflow_1.0.0", identifier, env, workflowExecution, newAction)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to deploy subflow for user input trigger %s: %s", action.ID, err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("[DEBUG] Running user input WITHOUT subflow")
|
||||
}
|
||||
|
||||
resultData, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user