diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py index 9290353c..b4c0fe62 100644 --- a/backend/app_sdk/app_base.py +++ b/backend/app_sdk/app_base.py @@ -1461,7 +1461,12 @@ class AppBase: # FIXME: Only do this IF they want to loop new_replacement = [] for i in range(len(json_replacement)): - newvalue = tmpitem.replace(actualitem[0][0], json_replacement[i], 1) + if isinstance(json_replacement[i], dict) or isinstance(json_replacement[i], dict): + tmp_replacer = json.dumps(json_replacement[i]) + newvalue = tmpitem.replace(actualitem[0][0], tmp_replacer, 1) + else: + newvalue = tmpitem.replace(actualitem[0][0], json_replacement[i], 1) + try: newvalue = json.loads(newvalue) except json.decoder.JSONDecodeError as e: diff --git a/backend/app_sdk/build.sh b/backend/app_sdk/build.sh index 0651424c..5a24cba5 100644 --- a/backend/app_sdk/build.sh +++ b/backend/app_sdk/build.sh @@ -1,6 +1,6 @@ #!/bin/bash NAME=shuffle-app_sdk -VERSION=0.8.5 +VERSION=0.8.51 docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force docker build . -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION diff --git a/backend/go-app/main.go b/backend/go-app/main.go index c4863119..c3987846 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -7173,8 +7173,10 @@ func runInit(ctx context.Context) { } } } else { - if len(users) == 1 { - log.Printf("Found 1 user - %s.", users[0].Username) + if len(users) < 5 && len(users) > 0 { + for _, user := range users { + log.Printf("Username: %s, role: %s", user.Username, user.Role) + } } else { log.Printf("Found %d users.", len(users)) } diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 8c9cdf0d..cc4fb83e 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -1240,20 +1240,19 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl } extraInputs := 0 - for _, result := range workflowExecution.Results { - if result.Action.Name == "User Input" && result.Action.AppName == "User Input" { - log.Printf("Found User Input node - prepare cloud?") + for _, trigger := range workflowExecution.Workflow.Triggers { + if trigger.Name == "User Input" && trigger.AppName == "User Input" { extraInputs += 1 - } else if result.Action.Name == "run_subflow" && result.Action.AppName == "shuffle-subflow" { - log.Printf("[INFO] Found Shuffle Workflow node") + } else if trigger.Name == "Shuffle Workflow" && trigger.AppName == "Shuffle Workflow" { extraInputs += 1 } } - //log.Printf("LENGTH: %d - %d", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)) + //log.Printf("EXTRA: %d", extraInputs) + //log.Printf("LENGTH: %d - %d", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extraInputs) if len(workflowExecution.Results) == len(workflowExecution.Workflow.Actions)+extraInputs { - log.Printf("\nIN HERE WITH RESULTS %d vs %d\n", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extraInputs) + //log.Printf("\nIN HERE WITH RESULTS %d vs %d\n", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extraInputs) finished := true lastResult := "" @@ -1367,13 +1366,15 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl } } - if setExecution { + if setExecution || workflowExecution.Status == "FINISHED" || workflowExecution.Status == "ABORTED" || workflowExecution.Status == "FAILURE" { err = setWorkflowExecution(ctx, *workflowExecution, dbSave) if err != nil { resp.WriteHeader(401) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed setting workflowexecution actionresult: %s"}`, err))) return } + } else { + log.Printf("Skipping setexec with status %s", workflowExecution.Status) } //ExecutionId @@ -2070,7 +2071,17 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { trigger.Status = "stopped" } } else if trigger.TriggerType == "SUBFLOW" { - //log.Printf("Found subflow: %#v", trigger.Parameters) + for _, param := range trigger.Parameters { + if len(param.Value) == 0 && param.Name != "argument" { + workflow.IsValid = false + workflow.Errors = []string{"Trigger is missing a parameter: %s", param.Name} + + log.Printf("No type specified for user input node") + resp.WriteHeader(401) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Trigger %s is missing the parameter %s"}`, trigger.Label, param.Name))) + return + } + } } else if trigger.TriggerType == "WEBHOOK" && trigger.Status != "uninitialized" { hook, err := getHook(ctx, trigger.ID) if err != nil { diff --git a/docker-compose.yml b/docker-compose.yml index b5f9e1f1..3f5674b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ version: '3' services: frontend: - #build: ./frontend - image: ghcr.io/frikky/shuffle-frontend:0.8.5 + build: ./frontend + image: ghcr.io/frikky/shuffle-frontend:0.8.51 container_name: shuffle-frontend hostname: shuffle-frontend ports: @@ -16,8 +16,8 @@ services: depends_on: - backend backend: - #build: ./backend - image: ghcr.io/frikky/shuffle-backend:0.8.5 + build: ./backend + image: ghcr.io/frikky/shuffle-backend:0.8.51 container_name: shuffle-backend hostname: ${BACKEND_HOSTNAME} # Here for debugging: @@ -53,8 +53,8 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - - SHUFFLE_APP_SDK_VERSION=0.8.5 - - SHUFFLE_WORKER_VERSION=0.8.5 + - SHUFFLE_APP_SDK_VERSION=0.8.51 + - SHUFFLE_WORKER_VERSION=0.8.51 - ORG_ID=${ORG_ID} - ENVIRONMENT_NAME=${ENVIRONMENT_NAME} - BASE_URL=http://${OUTER_HOSTNAME}:${BACKEND_PORT} diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index cad79b62..d9558537 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -252,16 +252,12 @@ const AngularWorkflow = (props) => { setWorkflows(responseJson) const trigger = workflow.triggers[trigger_index] - console.log("Trigger: ",trigger) if (trigger.parameters.length >= 3) { for (var key in trigger.parameters) { const param = trigger.parameters[key] - console.log(param) if (param.name === "workflow") { const sub = responseJson.find(data => data.id === param.value) - console.log("SUBFLOW: ", sub) - - if (subworkflow.id !== sub.id) { + if (sub !== undefined && subworkflow.id !== sub.id) { setSubworkflow(sub) } } @@ -321,7 +317,7 @@ const AngularWorkflow = (props) => { setUserSettings(responseJson) }) .catch(error => { - console.log(error) + console.log(error) }); } @@ -2260,6 +2256,8 @@ const AngularWorkflow = (props) => { return } + const triggerLabel = getNextActionName(data.name) + newNodeId = uuid.v4() const newposition = { "x": e.pageX-cycontainer.offsetLeft, @@ -2277,7 +2275,7 @@ const AngularWorkflow = (props) => { id_: newNodeId, _id_: newNodeId, id: newNodeId, - label: data.label, + label: triggerLabel, type: data.type, is_valid: true, trigger_type: data.trigger_type, @@ -2329,7 +2327,7 @@ const AngularWorkflow = (props) => { data: newcybranch, } - if (data.name !== "User Input") { + if (data.name !== "User Input" && data.name !== "Shuffle Workflow") { //workflow.branches.push(newbranch) cy.add(edgeToBeAdded) } @@ -2591,8 +2589,9 @@ const AngularWorkflow = (props) => { const getNextActionName = (appName) => { var highest = "" //label = name + _number - for (var key in workflow.actions) { - const item = workflow.actions[key] + const allitems = workflow.actions.concat(workflow.triggers) + for (var key in allitems) { + const item = allitems[key] if (item.app_name === appName) { var number = item.label.split("_") if (isNaN(number[-1]) && parseInt(number[number.length-1]) > highest) { @@ -5059,7 +5058,7 @@ const AngularWorkflow = (props) => {
- Select workflow to execute: + Select a workflow to execute
{workflows === undefined || workflows === null || workflows.length === 0 ? null : @@ -5114,6 +5113,7 @@ const AngularWorkflow = (props) => { multiline fullWidth color="primary" + placeholder="Some execution data" defaultValue={workflow.triggers[selectedTriggerIndex].parameters[1].value} onBlur={(e) => { console.log("DATA: ", e.target.value) @@ -5491,8 +5491,6 @@ const AngularWorkflow = (props) => { const UserinputSidebar = () => { if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers[selectedTriggerIndex] !== undefined) { - console.log(workflow.triggers[selectedTriggerIndex]) - console.log(selectedTrigger) if (workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null || workflow.triggers[selectedTriggerIndex].parameters.length === 0) { workflow.triggers[selectedTriggerIndex].parameters = [] workflow.triggers[selectedTriggerIndex].parameters[0] = {"name": "alertinfo", "value": "hello this is an alert"} @@ -6337,13 +6335,21 @@ const AngularWorkflow = (props) => { {workflowExecutions.length > 0 ?
- {workflowExecutions.map(data => { + {workflowExecutions.map((data, index) => { const statusColor = data.status === "FINISHED" ? "green" : data.status === "ABORTED" || data.status === "FAILED" ? "red" : "orange" const timeElapsed = data.completed_at-data.started_at const resultsLength = data.results !== undefined && data.results !== null ? data.results.length : 0 const timestamp = new Date(data.started_at*1000).toISOString().split('.')[0].split("T").join(" ") + var calculatedResult = data.workflow.actions.length + for (var key in data.workflow.triggers) { + const trigger = data.workflow.triggers[key] + if ((trigger.app_name === "User Input" && trigger.trigger_type === "USERINPUT") || (trigger.app_name === "Shuffle Workflow" && trigger.trigger_type === "SUBFLOW")) { + calculatedResult += 1 + } + } + return ( {}} onMouseOut={() => {}} onClick={() => { @@ -6355,7 +6361,6 @@ const AngularWorkflow = (props) => { start() setExecutionRunning(true) setExecutionRequestStarted(false) - console.log(data) } setExecutionModalView(1) setExecutionData(data) @@ -6371,7 +6376,7 @@ const AngularWorkflow = (props) => { {data.workflow.actions !== null ?
- {resultsLength}/{data.workflow.actions.length} + {resultsLength}/{calculatedResult}
: null} @@ -6459,9 +6464,6 @@ const AngularWorkflow = (props) => { return null } - // showResult = replaceAll(showResult, " None", " \"None\"") - // Super basic check. - // // FIXME: The latter replace doens't really work if ' is used in a string var showResult = data.result.trim() //console.log(showResult) @@ -6491,10 +6493,21 @@ const AngularWorkflow = (props) => { const curapp = apps.find(a => a.name === data.action.app_name && a.app_version === data.action.app_version) const imgsize = 50 const statusColor = data.status === "FINISHED" || data.status === "SUCCESS" ? "green" : data.status === "ABORTED" || data.status === "FAILURE" ? "red" : "orange" - const actionimg = curapp === null ? + + var actionimg = curapp === null ? null : {data.action.app_name} + if (triggers.length > 2) { + if (data.action.app_name === "shuffle-subflow") { + actionimg = {"Shuffle + } + + if (data.action.app_name === "User Input") { + actionimg = {"Shuffle + } + } + return (
@@ -7150,7 +7163,6 @@ const AngularWorkflow = (props) => {
diff --git a/functions/onprem/orborus/build.sh b/functions/onprem/orborus/build.sh index 409c9e5f..72490aaf 100644 --- a/functions/onprem/orborus/build.sh +++ b/functions/onprem/orborus/build.sh @@ -1,5 +1,5 @@ NAME=shuffle-orborus -VERSION=0.8.5 +VERSION=0.8.51 echo "Running docker build with $NAME:$VERSION" #docker rmi frikky/shuffle:$NAME --force diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go index d95ba97b..d2e2e154 100644 --- a/functions/onprem/orborus/orborus.go +++ b/functions/onprem/orborus/orborus.go @@ -265,9 +265,7 @@ func initializeImages() { // check whether they are the same first images := []string{ - //fmt.Sprintf("%s/%s:app_sdk%s", baseimageregistry, baseimagename, baseimagetagsuffix), - //fmt.Sprintf("%s/%s:worker%s", baseimageregistry, baseimagename, baseimagetagsuffix), - + fmt.Sprintf("frikky/shuffle:app_sdk"), fmt.Sprintf("%s/%s/shuffle-app_sdk:%s", baseimageregistry, baseimagename, appSdkVersion), fmt.Sprintf("%s/%s/shuffle-worker:%s", baseimageregistry, baseimagename, workerVersion), // fmt.Sprintf("docker.io/%s:app_sdk", baseimagename), @@ -628,12 +626,12 @@ func getRunningWorkers(ctx context.Context, workerTimeout int) int { // FIXME - add this to remove exited workers // Should it check what happened to the execution? idk func zombiecheck(ctx context.Context, workerTimeout int) error { - log.Println("[INFO] Looking for old containers") + log.Println("[INFO] Looking for old containers (zombies)") containers, err := dockercli.ContainerList(ctx, types.ContainerListOptions{ All: true, }) - log.Printf("Len: %d", len(containers)) + //log.Printf("Len: %d", len(containers)) if err != nil { log.Printf("[ERROR] Failed creating Containerlist: %s", err) @@ -676,7 +674,7 @@ func zombiecheck(ctx context.Context, workerTimeout int) error { } currenttime := time.Now().Unix() - log.Printf("[INFO] (%s) NAME: %s. TIME: %d", container.State, name, currenttime-container.Created) + //log.Printf("[INFO] (%s) NAME: %s. TIME: %d", container.State, name, currenttime-container.Created) // Need to check time here too because a container can be removed the same instant as its created if container.State != "running" && currenttime-container.Created > int64(workerTimeout) { diff --git a/functions/onprem/worker/build.sh b/functions/onprem/worker/build.sh index c4b91dc7..65c681a8 100644 --- a/functions/onprem/worker/build.sh +++ b/functions/onprem/worker/build.sh @@ -1,5 +1,5 @@ NAME=shuffle-worker -VERSION=0.8.5 +VERSION=0.8.51 echo "Running docker build with $NAME:$VERSION" #CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin . diff --git a/functions/onprem/worker/worker.go b/functions/onprem/worker/worker.go index 9df5fea0..a810bbe5 100644 --- a/functions/onprem/worker/worker.go +++ b/functions/onprem/worker/worker.go @@ -1050,6 +1050,7 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W // source = parent node, dest = child node // parent can have more children, child can have more parents extra := 0 + triggersHandled := []string{} for _, branch := range workflowExecution.Workflow.Branches { // Check what the parent is first. If it's trigger - skip sourceFound := false @@ -1065,20 +1066,30 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W } for _, trigger := range workflowExecution.Workflow.Triggers { - log.Printf("Appname trigger: %s", trigger.AppName) - if !(trigger.AppName == "User Input" || trigger.AppName == "Shuffle Workflow") { - continue - } - if trigger.ID == branch.SourceID { - sourceFound = true - extra += 1 - } + log.Printf("Appname trigger (0): %s", trigger.AppName) + if trigger.AppName == "User Input" || trigger.AppName == "Shuffle Workflow" { + log.Printf("%s is a special trigger. Checking where.", trigger.AppName) - if trigger.ID == branch.DestinationID { - destinationFound = true + found := false + for _, check := range triggersHandled { + if check == trigger.ID { + found = true + break + } + } - if !sourceFound { + if !found { extra += 1 + } else { + triggersHandled = append(triggersHandled, trigger.ID) + } + + if trigger.ID == branch.SourceID { + log.Printf("Trigger %s is the source!", trigger.AppName) + sourceFound = true + } else if trigger.ID == branch.DestinationID { + log.Printf("Trigger %s is the destination!", trigger.AppName) + destinationFound = true } } }