diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod
index 8e686705..ea02517b 100644
--- a/backend/go-app/go.mod
+++ b/backend/go-app/go.mod
@@ -22,7 +22,7 @@ require (
github.com/gorilla/mux v1.8.1
github.com/h2non/filetype v1.1.3
github.com/satori/go.uuid v1.2.0
- github.com/shuffle/shuffle-shared v0.8.39
+ github.com/shuffle/shuffle-shared v0.8.50
golang.org/x/crypto v0.36.0
google.golang.org/api v0.228.0
google.golang.org/grpc v1.71.1
diff --git a/backend/go-app/go.sum b/backend/go-app/go.sum
index a3382d6a..ca216f74 100644
--- a/backend/go-app/go.sum
+++ b/backend/go-app/go.sum
@@ -341,8 +341,8 @@ github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fc
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
-github.com/shuffle/shuffle-shared v0.8.39 h1:ylRj+2xGIOPQfpawf45udnQzKLtTP9JFEFyREc2GJXM=
-github.com/shuffle/shuffle-shared v0.8.39/go.mod h1:z+ISGBgNINmZvWNrtGTc51yVG+pMkpBFu9ZLVlTyuag=
+github.com/shuffle/shuffle-shared v0.8.50 h1:Sy6o7Nrcd3QG+m28775STKS3uOfaXDzDcctTuaYfdYQ=
+github.com/shuffle/shuffle-shared v0.8.50/go.mod h1:z+ISGBgNINmZvWNrtGTc51yVG+pMkpBFu9ZLVlTyuag=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
diff --git a/backend/go-app/main.go b/backend/go-app/main.go
index 68fc4e88..fbd2a251 100755
--- a/backend/go-app/main.go
+++ b/backend/go-app/main.go
@@ -5138,7 +5138,7 @@ func initHandlers() {
r.HandleFunc("/api/v1/apps/{key}/execute", executeSingleAction).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/{key}/run", executeSingleAction).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/categories", shuffle.GetActiveCategories).Methods("GET", "OPTIONS")
- r.HandleFunc("/api/v1/apps/categories/run", shuffle.RunCategoryAction).Methods("POST", "OPTIONS")
+ //r.HandleFunc("/api/v1/apps/categories/run", shuffle.RunCategoryAction).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/upload", handleAppZipUpload).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}/activate", activateWorkflowAppDocker).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}/deactivate", activateWorkflowAppDocker).Methods("GET", "OPTIONS")
diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go
index 14c5ac28..8357de3e 100755
--- a/backend/go-app/walkoff.go
+++ b/backend/go-app/walkoff.go
@@ -3039,7 +3039,13 @@ func executeSingleAction(resp http.ResponseWriter, request *http.Request) {
shouldRerun = true
}
- workflowExecution, err := shuffle.PrepareSingleAction(ctx, user, fileId, body, runValidationAction)
+ decisionId := ""
+ decision, decisionOk := query["decision_id"]
+ if decisionOk && len(decision) > 0 {
+ decisionId = decision[0]
+ }
+
+ workflowExecution, err := shuffle.PrepareSingleAction(ctx, user, fileId, body, runValidationAction, decisionId)
debugUrl := fmt.Sprintf("/workflows/%s?execution_id=%s", workflowExecution.Workflow.ID, workflowExecution.ExecutionId)
resp.Header().Add("X-Debug-Url", debugUrl)
@@ -3101,7 +3107,12 @@ func executeSingleAction(resp http.ResponseWriter, request *http.Request) {
return
}
- returnBody := shuffle.HandleRetValidation(ctx, workflowExecution, 1)
+ actionId := ""
+ if len(workflowExecution.Workflow.Actions) == 1 {
+ actionId = workflowExecution.Workflow.Actions[0].ID
+ }
+
+ returnBody := shuffle.HandleRetValidation(ctx, workflowExecution, 1, actionId)
returnBytes, err := json.Marshal(returnBody)
if err != nil {
log.Printf("[ERROR] Failed to marshal retStruct in single execution: %s", err)
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 7fa7c847..2192be04 100755
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -791,6 +791,40 @@ const App = (message, props) => {
/>
}
/>
+
+ }
+ />
+
+ }
+ />
{
/>
}
/>
+
+
+ }
+ />
+
0 {
+ env = append(env, fmt.Sprintf("SHUFFLE_APP_POD_SECURITY_CONTEXT=%s", appPodSecurityContext))
+ }
+
+ if len(appContainerSecurityContext) > 0 {
+ env = append(env, fmt.Sprintf("SHUFFLE_APP_CONTAINER_SECURITY_CONTEXT=%s", appContainerSecurityContext))
+ }
+
clientset, _, err := shuffle.GetKubernetesClient()
if err != nil {
log.Printf("[ERROR] Error getting kubernetes client:", err)
@@ -1085,10 +1097,33 @@ func deployK8sWorker(image string, identifier string, env []string) error {
"app.kubernetes.io/instance": identifier,
}
+ // Parse security contexts from env
+ var podSecurityContext *corev1.PodSecurityContext
+ var containerSecurityContext *corev1.SecurityContext
+
+ if len(workerPodSecurityContext) > 0 {
+ podSecurityContext = &corev1.PodSecurityContext{}
+ err = json.Unmarshal([]byte(workerPodSecurityContext), podSecurityContext)
+ if err != nil {
+ log.Printf("[ERROR] Failed to unmarshal worker pod security context: %v", err)
+ return fmt.Errorf("failed to unmarshal worker pod security context: %v", err)
+ }
+ }
+
+ if len(workerContainerSecurityContext) > 0 {
+ containerSecurityContext = &corev1.SecurityContext{}
+ err = json.Unmarshal([]byte(workerContainerSecurityContext), containerSecurityContext)
+ if err != nil {
+ log.Printf("[ERROR] Failed to unmarshal worker container security context: %v", err)
+ return fmt.Errorf("failed to unmarshal worker container security context: %v", err)
+ }
+ }
+
containerAttachment := corev1.Container{
- Name: identifier,
- Image: kubernetesImage,
- Env: buildEnvVars(envMap),
+ Name: identifier,
+ Image: kubernetesImage,
+ Env: buildEnvVars(envMap),
+ SecurityContext: containerSecurityContext,
//ImagePullPolicy: "Never",
ImagePullPolicy: corev1.PullIfNotPresent,
@@ -1205,6 +1240,7 @@ func deployK8sWorker(image string, identifier string, env []string) error {
},
DNSPolicy: corev1.DNSClusterFirst,
ServiceAccountName: workerServiceAccountName,
+ SecurityContext: podSecurityContext,
},
},
},
diff --git a/functions/onprem/worker/worker.go b/functions/onprem/worker/worker.go
index c411ae52..0fddb006 100644
--- a/functions/onprem/worker/worker.go
+++ b/functions/onprem/worker/worker.go
@@ -57,9 +57,13 @@ var logsDisabled = os.Getenv("SHUFFLE_LOGS_DISABLED")
var cleanupEnv = strings.ToLower(os.Getenv("CLEANUP"))
var swarmNetworkName = os.Getenv("SHUFFLE_SWARM_NETWORK_NAME")
var dockerApiVersion = strings.ToLower(os.Getenv("DOCKER_API_VERSION"))
-var appServiceAccountName = os.Getenv("SHUFFLE_APP_SERVICE_ACCOUNT_NAME")
+// Kubernetes settings
+var appServiceAccountName = os.Getenv("SHUFFLE_APP_SERVICE_ACCOUNT_NAME")
+var appPodSecurityContext = os.Getenv("SHUFFLE_APP_POD_SECURITY_CONTEXT")
+var appContainerSecurityContext = os.Getenv("SHUFFLE_APP_CONTAINER_SECURITY_CONTEXT")
var kubernetesNamespace = os.Getenv("KUBERNETES_NAMESPACE")
+
var executionCount int64
var baseimagename = os.Getenv("SHUFFLE_BASE_IMAGE_NAME")
@@ -74,6 +78,7 @@ var appsInitialized = false
var hostname string
var maxReplicas = uint64(12)
+var debug bool
/*
var environments []string
@@ -506,6 +511,28 @@ func deployk8sApp(image string, identifier string, env []string) error {
"app.kubernetes.io/instance": name,
}
+ // Parse security contexts from env
+ var podSecurityContext *corev1.PodSecurityContext
+ var containerSecurityContext *corev1.SecurityContext
+
+ if len(appPodSecurityContext) > 0 {
+ podSecurityContext = &corev1.PodSecurityContext{}
+ err = json.Unmarshal([]byte(appPodSecurityContext), podSecurityContext)
+ if err != nil {
+ log.Printf("[ERROR] Failed to unmarshal app pod security context: %v", err)
+ return fmt.Errorf("failed to unmarshal app pod security context: %v", err)
+ }
+ }
+
+ if len(appContainerSecurityContext) > 0 {
+ containerSecurityContext = &corev1.SecurityContext{}
+ err = json.Unmarshal([]byte(appContainerSecurityContext), containerSecurityContext)
+ if err != nil {
+ log.Printf("[ERROR] Failed to unmarshal app container security context: %v", err)
+ return fmt.Errorf("failed to unmarshal app container security context: %v", err)
+ }
+ }
+
// pod := &corev1.Pod{
// ObjectMeta: metav1.ObjectMeta{
// Name: podName,
@@ -608,10 +635,12 @@ func deployk8sApp(image string, identifier string, env []string) error {
ContainerPort: int32(deployport),
},
},
+ SecurityContext: containerSecurityContext,
},
},
DNSPolicy: corev1.DNSClusterFirst,
ServiceAccountName: appServiceAccountName,
+ SecurityContext: podSecurityContext,
},
},
},
@@ -2555,11 +2584,16 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl
}
if setExecution || workflowExecution.Status == "FINISHED" || workflowExecution.Status == "ABORTED" || workflowExecution.Status == "FAILURE" {
- log.Printf("[DEBUG][%s] Running setexec with status %s and %d/%d results", workflowExecution.ExecutionId, workflowExecution.Status, len(workflowExecution.Results), len(workflowExecution.Workflow.Actions))
+ if debug {
+ log.Printf("[DEBUG][%s] Running setexec with status %s and %d/%d results", workflowExecution.ExecutionId, workflowExecution.Status, len(workflowExecution.Results), len(workflowExecution.Workflow.Actions))
+ }
+
//result(s)", workflowExecution.ExecutionId, workflowExecution.Status, len(workflowExecution.Results))
err = setWorkflowExecution(ctx, *workflowExecution, dbSave)
if err != nil {
- resp.WriteHeader(401)
+ log.Printf("[ERROR][%s] Failed setting execution: %s", workflowExecution.ExecutionId, err)
+
+ resp.WriteHeader(400)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed setting workflowexecution actionresult: %s"}`, err)))
return
}
@@ -2568,7 +2602,10 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl
if os.Getenv("SHUFFLE_SWARM_CONFIG") == "run" || os.Getenv("SHUFFLE_SWARM_CONFIG") == "swarm" {
finished := shuffle.ValidateFinished(ctx, -1, *workflowExecution)
if !finished {
- log.Printf("[DEBUG][%s] Handling next node since it's not finished!", workflowExecution.ExecutionId)
+ if debug {
+ log.Printf("[DEBUG][%s] Handling next node since it's not finished!", workflowExecution.ExecutionId)
+ }
+
handleExecutionResult(*workflowExecution)
} else {
shutdownData, err := json.Marshal(workflowExecution)
@@ -3526,7 +3563,9 @@ func sendAppRequest(ctx context.Context, incomingUrl, appName string, port int,
log.Printf("[ERROR] Failed reading app request body body: %s", err)
return err
} else {
- log.Printf("[DEBUG][%s] NEWRESP (from app): %s", workflowExecution.ExecutionId, string(body))
+ if debug {
+ log.Printf("[DEBUG][%s] NEWRESP (from app): %s", workflowExecution.ExecutionId, string(body))
+ }
}
return nil
@@ -3918,6 +3957,10 @@ func checkStandaloneRun() {
func main() {
checkStandaloneRun()
+ if os.Getenv("DEBUG") == "true" {
+ debug = true
+ }
+
/*** STARTREMOVE ***/
if os.Getenv("SHUFFLE_SWARM_CONFIG") == "run" || os.Getenv("SHUFFLE_SWARM_CONFIG") == "swarm" {
logsDisabled = "true"