Fixed no-path issue with requirement of leading /

This commit is contained in:
frikky
2021-03-29 21:58:48 +02:00
parent 7814eb1e08
commit 1b428b301a
16 changed files with 419 additions and 161 deletions
-3
View File
@@ -7,15 +7,12 @@ WORKDIR /app
ADD ./go-app/main.go /app ADD ./go-app/main.go /app
ADD ./go-app/walkoff.go /app ADD ./go-app/walkoff.go /app
ADD ./go-app/docker.go /app ADD ./go-app/docker.go /app
ADD ./go-app/codegen.go /app
ADD ./go-app/files.go /app
ADD ./go-app/oauth2.go /app ADD ./go-app/oauth2.go /app
ADD ./go-app/go.mod /app ADD ./go-app/go.mod /app
# Required files for code generation # Required files for code generation
ADD ./app_sdk/app_base.py /app_sdk ADD ./app_sdk/app_base.py /app_sdk
ADD ./app_sdk/static_baseline.py /app_sdk
ADD ./app_sdk_kali/app_base.py /app_sdk_kali ADD ./app_sdk_kali/app_base.py /app_sdk_kali
ADD ./app_sdk_kali/static_baseline.py /app_sdk_kali ADD ./app_sdk_kali/static_baseline.py /app_sdk_kali
ADD ./app_sdk_blackarch/app_base.py /app_sdk_blackarch ADD ./app_sdk_blackarch/app_base.py /app_sdk_blackarch
+2 -2
View File
@@ -2,7 +2,7 @@ module shuffle
go 1.13 go 1.13
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared //replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi //replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
require ( require (
@@ -18,7 +18,7 @@ require (
github.com/docker/docker v1.13.1 github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect
github.com/frikky/shuffle-shared v0.0.15 github.com/frikky/shuffle-shared v0.0.20
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-billy/v5 v5.0.0
github.com/go-git/go-git/v5 v5.0.0 github.com/go-git/go-git/v5 v5.0.0
+137 -2
View File
@@ -77,6 +77,8 @@ var registryName = "registry.hub.docker.com"
var runningEnvironment = "onprem" var runningEnvironment = "onprem"
var syncUrl = "https://shuffler.io" var syncUrl = "https://shuffler.io"
//var syncUrl = "http://localhost:5002"
var syncSubUrl = "https://shuffler.io" var syncSubUrl = "https://shuffler.io"
//var syncUrl = "http://localhost:5002" //var syncUrl = "http://localhost:5002"
@@ -5463,12 +5465,12 @@ func runInit(ctx context.Context) {
} }
iterateOpenApiGithub(fs, dir, "", "") iterateOpenApiGithub(fs, dir, "", "")
log.Printf("Finished downloading extra API samples") log.Printf("[INFO] Finished downloading extra API samples")
} }
workflowLocation := os.Getenv("SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION") workflowLocation := os.Getenv("SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION")
if len(workflowLocation) > 0 { if len(workflowLocation) > 0 {
log.Printf("Downloading WORKFLOWS from %s if no workflows - EXTRA workflows", workflowLocation) log.Printf("[INFO] Downloading WORKFLOWS from %s if no workflows - EXTRA workflows", workflowLocation)
q := datastore.NewQuery("workflow").Limit(35) q := datastore.NewQuery("workflow").Limit(35)
var workflows []shuffle.Workflow var workflows []shuffle.Workflow
_, err = dbclient.GetAll(ctx, q, &workflows) _, err = dbclient.GetAll(ctx, q, &workflows)
@@ -5918,6 +5920,138 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
resp.Write(respBody) resp.Write(respBody)
} }
func makeWorkflowPublic(resp http.ResponseWriter, request *http.Request) {
cors := shuffle.HandleCors(resp, request)
if cors {
return
}
user, userErr := shuffle.HandleApiAuthentication(resp, request)
if userErr != nil {
log.Printf("[WARNING] Api authentication failed in make workflow public: %s", userErr)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
location := strings.Split(request.URL.String(), "/")
var fileId string
if location[1] == "api" {
if len(location) <= 4 {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
fileId = location[4]
}
ctx := context.Background()
if strings.Contains(fileId, "?") {
fileId = strings.Split(fileId, "?")[0]
}
if len(fileId) != 36 {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Workflow ID when getting workflow is not valid"}`))
return
}
workflow, err := shuffle.GetWorkflow(ctx, fileId)
if err != nil {
log.Printf("[WARNING] Workflow %s doesn't exist in app publish. User: %s", fileId, user.Id)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// CHECK orgs of user, or if user is owner
// FIXME - add org check too, and not just owner
// Check workflow.Sharing == private / public / org too
if user.Id != workflow.Owner || len(user.Id) == 0 {
if workflow.OrgId == user.ActiveOrg.Id && user.Role == "admin" {
log.Printf("[INFO] User %s is accessing workflow %s as admin", user.Username, workflow.ID)
} else {
log.Printf("[WARNING] Wrong user (%s) for workflow %s (get workflow)", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
}
if !workflow.IsValid || !workflow.PreviouslySaved {
log.Printf("[INFO] Failed uploading workflow because it's invalid or not saved")
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Invalid workflows are not sharable"}`))
return
}
// Starting validation of the POST workflow
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("[WARNING] Body data error on mail: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
parsedWorkflow := shuffle.Workflow{}
err = json.Unmarshal(body, &parsedWorkflow)
if err != nil {
log.Printf("[WARNING] Unmarshal error on mail: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// Super basic validation. Doesn't really matter.
if parsedWorkflow.ID != workflow.ID || len(parsedWorkflow.Actions) != len(workflow.Actions) {
log.Printf("[WARNING] Bad ID during publish: %s vs %s", workflow.ID, parsedWorkflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
if !workflow.IsValid || !workflow.PreviouslySaved {
log.Printf("[INFO] Failed uploading new workflow because it's invalid or not saved")
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Invalid workflows are not sharable"}`))
return
}
workflowData, err := json.Marshal(parsedWorkflow)
if err != nil {
log.Printf("[WARNING] Failed marshalling workflow: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// Sanitization is done in the frontend as well
parsedWorkflow = shuffle.SanitizeWorkflow(parsedWorkflow)
parsedWorkflow.ID = uuid.NewV4().String()
action := shuffle.CloudSyncJob{
Type: "workflow",
Action: "publish",
OrgId: user.ActiveOrg.Id,
PrimaryItemId: workflow.ID,
SecondaryItem: string(workflowData),
FifthItem: user.Id,
}
err = executeCloudAction(action, user.ActiveOrg.SyncConfig.Apikey)
if err != nil {
log.Printf("[WARNING] Failed cloud PUBLISH: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
}
log.Printf("[INFO] Successfully published workflow %s (%s) TO CLOUD", workflow.Name, workflow.ID)
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
}
func initHandlers() { func initHandlers() {
var err error var err error
ctx := context.Background() ctx := context.Background()
@@ -6041,6 +6175,7 @@ func initHandlers() {
r.HandleFunc("/api/v1/get_openapi/{key}", getOpenapi).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/get_openapi/{key}", getOpenapi).Methods("GET", "OPTIONS")
// NEW for 0.8.0 // NEW for 0.8.0
r.HandleFunc("/api/v1/workflows/{key}/publish", makeWorkflowPublic).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/cloud/setup", handleCloudSetup).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/cloud/setup", handleCloudSetup).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/orgs", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/orgs", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/orgs/", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
+2 -1
View File
@@ -981,7 +981,7 @@ func validateNewWorkerExecution(body []byte) error {
execution.Status = "FINISHED" execution.Status = "FINISHED"
} }
log.Printf("BASEEXECUTION LENGTH: %d", len(baseExecution.Workflow.Actions)+extra) log.Printf("[INFO] BASEEXECUTION LENGTH: %d", len(baseExecution.Workflow.Actions)+extra)
} }
// FIXME: Add extra here // FIXME: Add extra here
@@ -4782,6 +4782,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
workflowapp.Sharing = true workflowapp.Sharing = true
workflowapp.Downloaded = true workflowapp.Downloaded = true
workflowapp.Hash = md5 workflowapp.Hash = md5
workflowapp.Public = true
err = shuffle.SetWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID) err = shuffle.SetWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID)
if err != nil { if err != nil {
+6 -6
View File
@@ -1,8 +1,8 @@
version: '3' version: '3'
services: services:
frontend: frontend:
#build: ./frontend build: ./frontend
image: ghcr.io/frikky/shuffle-frontend:0.8.64 image: ghcr.io/frikky/shuffle-frontend:0.8.70
container_name: shuffle-frontend container_name: shuffle-frontend
hostname: shuffle-frontend hostname: shuffle-frontend
ports: ports:
@@ -16,8 +16,8 @@ services:
depends_on: depends_on:
- backend - backend
backend: backend:
#build: ./backend build: ./backend
image: ghcr.io/frikky/shuffle-backend:0.8.64 image: ghcr.io/frikky/shuffle-backend:0.8.70
container_name: shuffle-backend container_name: shuffle-backend
hostname: ${BACKEND_HOSTNAME} hostname: ${BACKEND_HOSTNAME}
# Here for debugging: # Here for debugging:
@@ -47,7 +47,7 @@ services:
- database - database
orborus: orborus:
#build: ./functions/onprem/orborus #build: ./functions/onprem/orborus
image: ghcr.io/frikky/shuffle-orborus:0.8.63 image: ghcr.io/frikky/shuffle-orborus:0.8.70
container_name: shuffle-orborus container_name: shuffle-orborus
hostname: shuffle-orborus hostname: shuffle-orborus
networks: networks:
@@ -56,7 +56,7 @@ services:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
environment: environment:
- SHUFFLE_APP_SDK_VERSION=0.8.60 - SHUFFLE_APP_SDK_VERSION=0.8.60
- SHUFFLE_WORKER_VERSION=0.8.63 - SHUFFLE_WORKER_VERSION=0.8.70
- ORG_ID=${ORG_ID} - ORG_ID=${ORG_ID}
- ENVIRONMENT_NAME=${ENVIRONMENT_NAME} - ENVIRONMENT_NAME=${ENVIRONMENT_NAME}
- BASE_URL=http://${OUTER_HOSTNAME}:${BACKEND_PORT} - BASE_URL=http://${OUTER_HOSTNAME}:${BACKEND_PORT}
+1 -1
View File
@@ -21,7 +21,7 @@ COPY ./*.json /usr/src/app/
RUN yarn build RUN yarn build
# Production environment # Production environment
FROM nginx:latest FROM nginx:1.19
RUN mkdir -p /usr/share/nginx/html/build RUN mkdir -p /usr/share/nginx/html/build
RUN mkdir -p /usr/share/nginx/html/css RUN mkdir -p /usr/share/nginx/html/css
+20 -1
View File
@@ -39,6 +39,23 @@ const data = [{
'border-color': '#81c784', 'border-color': '#81c784',
'background-width': '100%', 'background-width': '100%',
'background-height': '100%', 'background-height': '100%',
'border-radius': '5px',
},
},
{
selector: `node[app_name="Shuffle Tools"]`,
css: {
'width': '30px',
'height': '30px',
'font-size': '0px',
},
},
{
selector: `node[app_name="Testing"]`,
css: {
'width': '30px',
'height': '30px',
'font-size': '0px',
}, },
}, },
{ {
@@ -112,7 +129,7 @@ const data = [{
}, },
}, },
{ {
selector: 'node:selected', selector: ':selected',
css: { css: {
'background-color': '#77b0d0', 'background-color': '#77b0d0',
'border-color': '#77b0d0', 'border-color': '#77b0d0',
@@ -187,6 +204,8 @@ const data = [{
'border-width': '12px', 'border-width': '12px',
'transition-property': 'border-width', 'transition-property': 'border-width',
'transition-duration': '0.25s', 'transition-duration': '0.25s',
'font-size': '30px',
'label': 'data(label)',
}, },
}, },
{ {
+98 -9
View File
@@ -92,7 +92,6 @@ const AngularWorkflow = (props) => {
const theme = useTheme(); const theme = useTheme();
const [bodyWidth, bodyHeight] = useWindowSize(); const [bodyWidth, bodyHeight] = useWindowSize();
const appBarSize = 75
var to_be_copied = "" var to_be_copied = ""
const [cystyle, ] = useState(cytoscapestyle) const [cystyle, ] = useState(cytoscapestyle)
@@ -190,18 +189,22 @@ const AngularWorkflow = (props) => {
const [workflowExecutions, setWorkflowExecutions] = React.useState([]); const [workflowExecutions, setWorkflowExecutions] = React.useState([]);
const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0) const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0)
// This should all be set once, not on every iteration
// Use states and don't update lol
const cloudSyncEnabled = props.userdata !== undefined && props.userdata.active_org !== null && props.userdata.active_org !== undefined ? props.userdata.active_org.cloud_sync === true : false const cloudSyncEnabled = props.userdata !== undefined && props.userdata.active_org !== null && props.userdata.active_org !== undefined ? props.userdata.active_org.cloud_sync === true : false
//const triggerEnvironments = cloudSyncEnabled ? ["cloud", "onprem"] : environments //const triggerEnvironments = cloudSyncEnabled ? ["cloud", "onprem"] : environments
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"
const appBarSize = isCloud ? 75 : 60
const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"] const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"]
const unloadText = 'Are you sure you want to leave without saving (CTRL+S)?' const unloadText = 'Are you sure you want to leave without saving (CTRL+S)?'
useBeforeunload(() => { useBeforeunload(() => {
if (!lastSaved) { if (!lastSaved) {
return unloadText return unloadText
} }
}) })
const [elements, setElements] = useState([]) const [elements, setElements] = useState([])
// No point going as fast, as the nodes aren't realtime anymore, but bulk updated. // No point going as fast, as the nodes aren't realtime anymore, but bulk updated.
// Set it from 2500 to 6000 to reduce overall load // Set it from 2500 to 6000 to reduce overall load
@@ -1121,7 +1124,7 @@ const AngularWorkflow = (props) => {
} }
if (responseJson.public) { if (responseJson.public) {
alert.info("This workflow is public. You'll have to save it to make it your own!") alert.info("This workflow is public. You will have to save it to make it your own!")
setLastSaved(false) setLastSaved(false)
} }
@@ -1215,9 +1218,36 @@ const AngularWorkflow = (props) => {
setSelectedTrigger({}) setSelectedTrigger({})
} }
// Comparing locations between nodes and setting views
const onNodeDrag = (event, newAppAuth) => {
//console.log("DRAGGING: ", event.target)
//console.log("LEN2: ", event.target.edges.length)
/*
event.target.animate({
style: {
"border-width": "12px",
"border-opacity": ".7",
}
}, {
duration: animationDuration,
})
event.target.animate({
style: {
"border-width": "12px",
"border-opacity": ".7",
}
}, {
duration: animationDuration,
})
*/
}
// Nodeselectbatching: // Nodeselectbatching:
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once // https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
const onNodeSelect = (event, newAppAuth) => { const onNodeSelect = (event, newAppAuth) => {
const data = event.target.data() const data = event.target.data()
setLastSaved(false) setLastSaved(false)
@@ -1619,6 +1649,17 @@ const AngularWorkflow = (props) => {
}); });
} }
if (!firstrequest && graphSetup && established && props.match.params.key !== workflow.id && workflow.id !== undefined && workflow.id !== null && workflow.id.length > 0) {
//console.log(props.match.params.key, workflow.id)
//getWorkflow()
//setCy()
//getWorkflowExecution(props.match.params.key, "")
//setEstablished(false)
//setGraphSetup(false)
window.location.pathname = "/workflows/"+props.match.params.key
}
useEffect(() => { useEffect(() => {
if (firstrequest) { if (firstrequest) {
setFirstrequest(false) setFirstrequest(false)
@@ -1642,14 +1683,14 @@ const AngularWorkflow = (props) => {
} }
// App length necessary cus of cy initialization // App length necessary cus of cy initialization
if (elements.length === 0 && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) { if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) {
setGraphSetup(true) setGraphSetup(true)
setupGraph() setupGraph()
} else if (!established && cy !== undefined && apps !== null && apps !== undefined && apps.length > 0 && Object.getOwnPropertyNames(workflow).length > 0 && authLoaded){ } else if (!established && cy !== undefined && apps !== null && apps !== undefined && apps.length > 0 && Object.getOwnPropertyNames(workflow).length > 0 && authLoaded){
//This part has to load LAST, as it's kind of not async. //This part has to load LAST, as it's kind of not async.
//This means we need everything else to happen first. //This means we need everything else to happen first.
console.log("AUTH IN HERE: ", appAuthentication) //
//console.log("IN THIS PART AGAIN")
setEstablished(true) setEstablished(true)
cy.edgehandles({ cy.edgehandles({
@@ -1677,6 +1718,9 @@ const AngularWorkflow = (props) => {
cy.on('mouseover', 'node', (e) => onNodeHover(e)) cy.on('mouseover', 'node', (e) => onNodeHover(e))
cy.on('mouseout', 'node', (e) => onNodeHoverOut(e)) cy.on('mouseout', 'node', (e) => onNodeHoverOut(e))
// Handles dragging
//cy.on('drag', 'node', (e) => onNodeDrag(e))
//cy.on('mouseover', 'node', () => $(targetElement).addClass('mouseover')); //cy.on('mouseover', 'node', () => $(targetElement).addClass('mouseover'));
//cy.on('cxttapstart', 'node', (e) => edgeHandler.start(e.target)) //cy.on('cxttapstart', 'node', (e) => edgeHandler.start(e.target))
@@ -1711,7 +1755,7 @@ const AngularWorkflow = (props) => {
const onNodeHover = (event) => { const onNodeHover = (event) => {
event.target.animate({ event.target.animate({
style: { style: {
"border-width": "5px", "border-width": "7px",
"border-opacity": ".7", "border-opacity": ".7",
} }
}, { }, {
@@ -1727,8 +1771,13 @@ const AngularWorkflow = (props) => {
// This is here to have a proper transition for lines // This is here to have a proper transition for lines
const onEdgeHover = (event) => { const onEdgeHover = (event) => {
if (event === null || event === undefined) {
return
}
const sourcecolor = cy.getElementById(event.target.data("source")).style("border-color") const sourcecolor = cy.getElementById(event.target.data("source")).style("border-color")
const targetcolor = cy.getElementById(event.target.data("target")).style("border-color") const targetcolor = cy.getElementById(event.target.data("target")).style("border-color")
if (sourcecolor !== null && sourcecolor !== undefined && targetcolor !== null && targetcolor !== undefined) {
event.target.animate({ event.target.animate({
style: { style: {
"line-fill": "linear-gradient", "line-fill": "linear-gradient",
@@ -1739,6 +1788,7 @@ const AngularWorkflow = (props) => {
duration: 0, duration: 0,
}) })
} }
}
const setupGraph = () => { const setupGraph = () => {
@@ -1799,6 +1849,31 @@ const AngularWorkflow = (props) => {
conditions: conditions, conditions: conditions,
hasErrors: branch.has_errors hasErrors: branch.has_errors
}; };
// This is an attempt at prettier edges. The numbers are weird to work with.
/*
//http://manual.graphspace.org/projects/graphspace-python/en/latest/demos/edge-types.html
const sourcenode = actions.find(node => node.data._id === branch.source_id)
const destinationnode = actions.find(node => node.data._id === branch.destination_id)
if (sourcenode !== undefined && destinationnode !== undefined && branch.source_id !== branch.destination_id) {
//node.data._id = action["id"]
console.log("SOURCE: ", sourcenode.position)
console.log("DESTINATIONNODE: ", destinationnode.position)
var opposite = true
if (sourcenode.position.x > destinationnode.position.x) {
opposite = false
} else {
opposite = true
}
edge.style = {
'control-point-distance': opposite ? ["25%", "-75%"] : ["-10%", "90%"],
'control-point-weight': ['0.3', '0.7'],
}
}
*/
return edge; return edge;
}) })
@@ -4506,7 +4581,7 @@ const AngularWorkflow = (props) => {
: null : null
} }
onClick={() => { onClick={() => {
console.log("CHANGE FIELD") //console.log("CHANGE FIELD")
}} }}
onBlur={(e) => { onBlur={(e) => {
changeActionVariable(data.action_field, e.target.value) changeActionVariable(data.action_field, e.target.value)
@@ -4803,6 +4878,7 @@ const AngularWorkflow = (props) => {
onClick={() => { onClick={() => {
setSelectedEdge({}) setSelectedEdge({})
var data = { var data = {
condition: conditionValue, condition: conditionValue,
source: sourceValue, source: sourceValue,
@@ -4821,6 +4897,18 @@ const AngularWorkflow = (props) => {
} }
} }
var label = ""
if (selectedEdge.conditions.length === 1) {
label = selectedEdge.conditions.length+" condition"
} else if (selectedEdge.conditions.length > 1) {
label = selectedEdge.conditions.length+" conditions"
}
var currentedge = cy.getElementById(selectedEdge.id)
if (currentedge !== undefined && currentedge !== null) {
currentedge.data().label = label
}
setSelectedEdge(selectedEdge) setSelectedEdge(selectedEdge)
workflow.branches[selectedEdgeIndex] = selectedEdge workflow.branches[selectedEdgeIndex] = selectedEdge
setWorkflow(workflow) setWorkflow(workflow)
@@ -6494,7 +6582,7 @@ const AngularWorkflow = (props) => {
</span> </span>
</Tooltip> </Tooltip>
{/* <FileMenu /> */} {/* <FileMenu /> */}
<WorkflowMenu /> {workflow.configuration !== null && workflow.configuration !== undefined && workflow.configuration.exit_on_error !== undefined ? <WorkflowMenu /> : null}
</div> </div>
</div> </div>
) )
@@ -7211,6 +7299,7 @@ const AngularWorkflow = (props) => {
stylesheet={cystyle} stylesheet={cystyle}
boxSelectionEnabled={true} boxSelectionEnabled={true}
autounselectify={false} autounselectify={false}
showGrid={true}
cy={(incy) => { cy={(incy) => {
// FIXME: There's something specific loading when // FIXME: There's something specific loading when
// you do the first hover of a node. Why is this different? // you do the first hover of a node. Why is this different?
+3 -3
View File
@@ -1565,9 +1565,9 @@ const AppCreator = (props) => {
} }
// Url verification // Url verification
if (currentAction.url.length === 0) { //if (currentAction.url.length === 0) {
errormessage.push("URL path can't be empty.") // errormessage.push("URL path can't be empty.")
} else if (!currentAction.url.startsWith("/") && baseUrl.length > 0) { if (!currentAction.url.startsWith("/") && baseUrl.length > 0 && currentAction.url.length > 0) {
errormessage.push("URL must start with /") errormessage.push("URL must start with /")
} }
+76 -63
View File
@@ -68,11 +68,9 @@ const flexContainerStyle = {
} }
const flexBoxStyle = { const flexBoxStyle = {
width: "333px", width: 333,
height: "125px", height: 125,
margin: "10px", borderRadius: 4,
borderRadius: "4px",
boxShadow: "0px 1px 2px rgba(0, 0, 0, 0.16), 0px 2px 4px rgba(0, 0, 0, 0.12), 0px 1px 8px rgba(0, 0, 0, 0.1)",
boxSizing: "border-box", boxSizing: "border-box",
letterSpacing: "0.4px", letterSpacing: "0.4px",
color: "#D6791E", color: "#D6791E",
@@ -299,37 +297,37 @@ const MyView = (props) => {
} }
const paperAppContainer = { const paperAppContainer = {
cursor: "pointer",
display: "flex", display: "flex",
flexWrap: 'wrap', flexWrap: 'wrap',
alignContent: "space-between", alignContent: "space-between",
} }
const paperAppStyle = { const paperAppStyle = {
minHeight: "148px", minHeight: 130,
width: "333px", width: "100%",
margin: "10px",
color: "white", color: "white",
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
padding: "12px 12px 0px 15px",
borderRadius: 5, borderRadius: 5,
padding: "10px",
cursor: "pointer",
display: "flex", display: "flex",
boxSizing: "border-box", boxSizing: "border-box",
position: "relative",
} }
const gridContainer = { const gridContainer = {
cursor: "pointer",
height: "auto", height: "auto",
color: "white", color: "white",
margin: "10px", margin: "10px",
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
} }
const workFlowActionStyle = { const workflowActionStyle = {
flex: "1", flex: "1",
display: "flex", display: "flex",
width: "150px", width: 150,
height: 44,
justifyContent: "space-between", justifyContent: "space-between",
overflow: "hidden" overflow: "hidden"
} }
@@ -535,23 +533,28 @@ const MyView = (props) => {
}); });
} }
const getWorkFlowMeta = (data) => { const getWorkflowMeta = (data) => {
let triggers = 0
let schedules = 0 let schedules = 0
let webhooks = 0 let webhooks = 0
let webhookImg = "" let subflows = 0
let scheduleImg = ""
if (data.triggers !== undefined && data.triggers !== null && data.triggers.length > 0) { if (data.triggers !== undefined && data.triggers !== null && data.triggers.length > 0) {
triggers = data.triggers.length
for (let key in data.triggers) { for (let key in data.triggers) {
if (data.triggers[key].app_name === "Webhook") { if (data.triggers[key].app_name === "Webhook") {
webhooks += 1 webhooks += 1
webhookImg = data.triggers[key].large_image //webhookImg = data.triggers[key].large_image
} else if (data.triggers[key].app_name === "Schedule") { } else if (data.triggers[key].app_name === "Schedule") {
schedules += 1 schedules += 1
scheduleImg = data.triggers[key].large_image //scheduleImg = data.triggers[key].large_image
} else if (data.triggers[key].app_name === "Subflow") {
subflows += 1
} }
} }
} }
return [schedules, webhooks, webhookImg, scheduleImg];
return [triggers, schedules, webhooks, subflows]
} }
// dropdown with copy etc I guess // dropdown with copy etc I guess
@@ -565,9 +568,9 @@ const MyView = (props) => {
boxWidth = "4px" boxWidth = "4px"
} }
var boxColor = "orange" var boxColor = "#FECC00"
if (data.is_valid) { if (data.is_valid) {
boxColor = "green" boxColor = "#86c142"
} }
const menuClick = (event) => { const menuClick = (event) => {
@@ -575,45 +578,57 @@ const MyView = (props) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
} }
var parsedName = data.name
console.log("LEN: ", parsedName.length)
if (parsedName !== undefined && parsedName !== null && parsedName.length > 25) {
parsedName = parsedName.slice(0,25)+".."
}
const actions = data.actions !== null ? data.actions.length : 0 const actions = data.actions !== null ? data.actions.length : 0
const [triggers, schedules, webhooks, subflows] = getWorkflowMeta(data)
const [schedules, webhooks] = getWorkFlowMeta(data);
const imgSize = 25
return ( return (
<Paper square style={paperAppStyle} onClick={(e) => { <Grid item xs={4} spacing={4} style={{padding: 10,}}>
}}> <Paper square style={paperAppStyle} >
<div style={{width: boxWidth, backgroundColor: boxColor,}} onClick={() => { <div style={{position: "absolute", bottom: 1, left: 1, height: 12, width: 12, backgroundColor: boxColor, borderRadius: "0 100px 0 0",}} />
if (selectedWorkflow.id !== data.id) {
setSelectedWorkflow(data)
//getWorkflowExecution(data.id)
}
}}/>
<Grid container style={{margin: "0px 10px 0px 10px", flex: 1}}>
<Grid item style={{display: "flex", flexDirection: "column", width: "100%"}}> <Grid item style={{display: "flex", flexDirection: "column", width: "100%"}}>
<Grid item style={{flex: 1, display: "flex"}}> <Grid item style={{flex: 1, display: "flex", maxHeight: 34,}}>
<div onClick={() => { <Typography variant="h6" style={{marginBottom: 0, paddingBottom: 0, maxHeight: 30,}}>
if (selectedWorkflow.id !== data.id) { {parsedName}
setSelectedWorkflow(data)
//getWorkflowExecution(data.id)
}
}}>
<Typography variant="h6">
{data.name}
</Typography> </Typography>
</div>
</Grid> </Grid>
<Grid item style={workFlowActionStyle}> <Grid item style={workflowActionStyle}>
<Tooltip color="primary" title="Edit workflow" placement="bottom"> <Tooltip color="primary" title="Action amount" placement="bottom">
<BubbleChartIcon/> <span style={{color: "#979797", display: "flex"}}>
<BubbleChartIcon style={{marginTop: "auto", marginBottom: "auto",}} />
<Typography style={{marginLeft: 5, marginTop: "auto", marginBottom: "auto",}}>
{actions}
</Typography>
</span>
</Tooltip> </Tooltip>
<Tooltip color="primary" title="Execute workflow" placement="bottom"> <Tooltip color="primary" title="Trigger amount" placement="bottom">
<PlayArrowIcon color="secondary" disabled={!data.is_valid} onClick={() => executeWorkflow(data.id)} /> <span style={{marginLeft: 10, color: "#979797", display: "flex"}}>
<RestoreIcon style={{color: "#979797", marginTop: "auto", marginBottom: "auto",}}/>
<Typography style={{marginLeft: 5, marginTop: "auto", marginBottom: "auto",}}>
{triggers}
</Typography>
</span>
</Tooltip> </Tooltip>
<Tooltip color="primary" title="Subflows used" placement="bottom">
<span style={{marginLeft: 10, display: "flex", color: "#979797", }}>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" style={{color: "#979797", marginTop: "auto", marginBottom: "auto",}}>
<path d="M0 0H15V15H0V0ZM16 16H18V18H16V16ZM16 13H18V15H16V13ZM16 10H18V12H16V10ZM16 7H18V9H16V7ZM16 4H18V6H16V4ZM13 16H15V18H13V16ZM10 16H12V18H10V16ZM7 16H9V18H7V16ZM4 16H6V18H4V16Z" fill="#979797"/>
</svg>
<Typography style={{marginLeft: 5, marginTop: "auto", marginBottom: "auto",}}>
{subflows}
</Typography>
</span>
</Tooltip>
{/*
<Tooltip color="primary" title={`Actions: ${data.actions.length}`} placement="bottom"> <Tooltip color="primary" title={`Actions: ${data.actions.length}`} placement="bottom">
<AppsIcon /> <AppsIcon />
</Tooltip> </Tooltip>
{webhooks > 0 ?
<Tooltip color="primary" title={`Webhooks: ${webhooks}`} placement="bottom"> <Tooltip color="primary" title={`Webhooks: ${webhooks}`} placement="bottom">
<RestoreIcon /> <RestoreIcon />
</Tooltip> </Tooltip>
@@ -623,8 +638,9 @@ const MyView = (props) => {
<RestoreIcon /> <RestoreIcon />
</Tooltip> </Tooltip>
: null} : null}
*/}
</Grid> </Grid>
<Grid item style={{flex: "1", justifyContent: "left", overflow: "hidden"}}> <Grid item style={{flex: "1", justifyContent: "left", overflow: "hidden", marginTop: 5,}}>
{data.tags !== undefined ? {data.tags !== undefined ?
data.tags.map((tag, index) => { data.tags.map((tag, index) => {
if (index >= 3) { if (index >= 3) {
@@ -634,7 +650,7 @@ const MyView = (props) => {
return ( return (
<Chip <Chip
key={index} key={index}
style={{height: 30, marginRight: 5, marginTop: 2, cursor: "pointer",}} style={{backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",}}
label={tag} label={tag}
variant="outlined" variant="outlined"
color="primary" color="primary"
@@ -644,7 +660,6 @@ const MyView = (props) => {
: null} : null}
</Grid> </Grid>
</Grid> </Grid>
</Grid>
{data.actions !== undefined && data.actions !== null ? {data.actions !== undefined && data.actions !== null ?
<Grid item style={{display:"flex",flexDirection:"column", justifyContent:"space-between"}}> <Grid item style={{display:"flex",flexDirection:"column", justifyContent:"space-between"}}>
<Grid> <Grid>
@@ -654,7 +669,7 @@ const MyView = (props) => {
aria-haspopup="true" aria-haspopup="true"
style={{color: "white"}} style={{color: "white"}}
onClick={menuClick} onClick={menuClick}
style={{padding:"0px",color:"white"}} style={{padding:"0px",color:"white", color:"#979797"}}
> >
<MoreVertIcon /> <MoreVertIcon />
</IconButton> </IconButton>
@@ -696,15 +711,14 @@ const MyView = (props) => {
<Grid> <Grid>
<Link to={"/workflows/"+data.id}> <Link to={"/workflows/"+data.id}>
<Tooltip title="Edit workflow" placement="bottom"> <Tooltip title="Edit workflow" placement="bottom">
<EditIcon style={{background: "#F85A3E", <EditIcon style={{background: "#F85A3E", borderRadius: "4px", color: "black", height: 20, width: 20, padding: 7, fontSize: "small"}} />
boxShadow: "0px 1px 2px rgba(0, 0, 0, 0.16), 0px 2px 4px rgba(0, 0, 0, 0.12), 0px 1px 8px rgba(0, 0, 0, 0.1)",
borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize: "small"}} />
</Tooltip> </Tooltip>
</Link> </Link>
</Grid> </Grid>
</Grid> </Grid>
: null} : null}
</Paper> </Paper>
</Grid>
) )
} }
@@ -772,7 +786,6 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
marginTop: "5px", marginTop: "5px",
color: "white", color: "white",
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
cursor: "pointer",
display: "flex", display: "flex",
} }
@@ -1294,13 +1307,12 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
let workflowData = ""; let workflowData = "";
if (workflows.length > 0) { if (workflows.length > 0) {
const columns = [ const columns = [
{ field: 'id', headerName: 'ID', width: 70, sortable: false, },
{ field: 'title', headerName: 'Title', width: 330, }, { field: 'title', headerName: 'Title', width: 330, },
{ field: 'actions', headerName: 'Actions', width: 200, sortable: false, { field: 'actions', headerName: 'Actions', width: 200, sortable: false,
disableClickEventBubbling: true, disableClickEventBubbling: true,
renderCell: (params) => { renderCell: (params) => {
const data = params.row.record; const data = params.row.record;
let [schedules, webhooks] = getWorkFlowMeta(data); let [triggers, schedules, webhooks, subflows] = getWorkflowMeta(data);
return <Grid item> return <Grid item>
<Link to={"/workflows/"+data.id}> <Link to={"/workflows/"+data.id}>
@@ -1340,10 +1352,11 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
if (index >= 3) { if (index >= 3) {
return null return null
} }
return ( return (
<Chip <Chip
key={index} key={index}
style={{height: 30, marginRight: 5, marginTop: 2, cursor: "pointer",}} style={{backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",}}
label={tag} label={tag}
variant="outlined" variant="outlined"
color="primary" color="primary"
@@ -1445,13 +1458,13 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
</div> </div>
{view === "grid" && ( {view === "grid" && (
<div style={paperAppContainer}> <Grid container spacing={4} style={paperAppContainer}>
{workflows.map((data, index) => { {workflows.map((data, index) => {
return ( return (
<WorkflowPaper key={index} data={data} /> <WorkflowPaper key={index} data={data} />
) )
})} })}
</div> </Grid>
)} )}
{view === "list" && ( {view === "list" && (
+7 -7
View File
@@ -447,12 +447,12 @@ const Workflows = (props) => {
for (var branchkey in data.branches) { for (var branchkey in data.branches) {
const branch = data.branches[branchkey] const branch = data.branches[branchkey]
if (branch.source_id === data.actions[key].id) { if (branch.source_id === data.actions[key].id) {
console.log("CHANGING SOURCE ID IN ACTION") //console.log("CHANGING SOURCE ID IN ACTION")
branch.source_id = newId branch.source_id = newId
} }
if (branch.destination_id === data.actions[key].id) { if (branch.destination_id === data.actions[key].id) {
console.log("CHANGING DESTINATION ID IN ACTION") //console.log("CHANGING DESTINATION ID IN ACTION")
branch.destination_id = newId branch.destination_id = newId
} }
} }
@@ -505,10 +505,8 @@ const Workflows = (props) => {
data = sanitizeWorkflow(data) data = sanitizeWorkflow(data)
alert.info("Sanitizing and publishing "+data.name) alert.info("Sanitizing and publishing "+data.name)
const url = isCloud ? globalUrl : "https://shuffler.io"
// This ALWAYS talks to Shuffle cloud // This ALWAYS talks to Shuffle cloud
fetch(url+"/api/v1/workflows/"+data.id+"/publish", { fetch(globalUrl+"/api/v1/workflows/"+data.id+"/publish", {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -521,7 +519,11 @@ const Workflows = (props) => {
if (response.status !== 200) { if (response.status !== 200) {
console.log("Status not 200 for workflow publish :O!") console.log("Status not 200 for workflow publish :O!")
} else { } else {
if (isCloud) {
alert.success("Successfully published workflow") alert.success("Successfully published workflow")
} else {
alert.success("Successfully published workflow to https://shuffler.io")
}
} }
return response.json() return response.json()
@@ -690,12 +692,10 @@ const Workflows = (props) => {
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags))) setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)))
} }
}} key={"change"}>{"Change details"}</MenuItem> }} key={"change"}>{"Change details"}</MenuItem>
{isCloud ?
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => { <MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
console.log("Should publish", data) console.log("Should publish", data)
publishWorkflow(data) publishWorkflow(data)
}} key={"publish"}>{"Publish Workflow"}</MenuItem> }} key={"publish"}>{"Publish Workflow"}</MenuItem>
: null}
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => { <MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
copyWorkflow(data) copyWorkflow(data)
setOpen(false) setOpen(false)
+1 -1
View File
@@ -1,5 +1,5 @@
NAME=shuffle-orborus NAME=shuffle-orborus
VERSION=0.8.64 VERSION=0.8.70
echo "Running docker build with $NAME:$VERSION" echo "Running docker build with $NAME:$VERSION"
#docker rmi frikky/shuffle:$NAME --force #docker rmi frikky/shuffle:$NAME --force
+1 -1
View File
@@ -248,7 +248,7 @@ func initializeImages() {
log.Printf("[WARNING] SHUFFLE_APP_SDK_VERSION not defined. Defaulting to %s", appSdkVersion) log.Printf("[WARNING] SHUFFLE_APP_SDK_VERSION not defined. Defaulting to %s", appSdkVersion)
} }
if workerVersion == "" { if workerVersion == "" {
workerVersion = "0.8.64" workerVersion = "0.8.70"
log.Printf("[WARNING] SHUFFLE_WORKER_VERSION not defined. Defaulting to %s", workerVersion) log.Printf("[WARNING] SHUFFLE_WORKER_VERSION not defined. Defaulting to %s", workerVersion)
} }
+3 -2
View File
@@ -11,7 +11,8 @@ RUN go get github.com/docker/docker/api/types && \
go get github.com/docker/docker/client && \ go get github.com/docker/docker/client && \
go get github.com/gorilla/mux && \ go get github.com/gorilla/mux && \
go get github.com/patrickmn/go-cache && \ go get github.com/patrickmn/go-cache && \
go get github.com/frikky/shuffle-shared go get github.com/frikky/shuffle-shared && \
go get github.com/satori/go.uuid
RUN go build RUN go build
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker .
@@ -21,7 +22,7 @@ FROM alpine:3.12
ENV SHUFFLE_BASE_IMAGE_REGISTRY=docker.io ENV SHUFFLE_BASE_IMAGE_REGISTRY=docker.io
ENV SHUFFLE_BASE_IMAGE_NAME=frikky/shuffle ENV SHUFFLE_BASE_IMAGE_NAME=frikky/shuffle
ENV SHUFFLE_BASE_IMAGE_TAG_SUFFIX=0.8.5 ENV SHUFFLE_BASE_IMAGE_TAG_SUFFIX=0.8.70
RUN apk add --no-cache bash RUN apk add --no-cache bash
COPY --from=builder /app/ / COPY --from=builder /app/ /
+1 -1
View File
@@ -1,5 +1,5 @@
NAME=shuffle-worker NAME=shuffle-worker
VERSION=0.8.64 VERSION=0.8.70
echo "Running docker build with $NAME:$VERSION" echo "Running docker build with $NAME:$VERSION"
#CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin . #CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin .
+14 -11
View File
@@ -24,6 +24,7 @@ import (
//"github.com/docker/docker/api/types/filters" //"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/mount"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
"github.com/satori/go.uuid"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
@@ -278,7 +279,7 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env []
// Waiting to see if it exits.. Stupid, but stable(r) // Waiting to see if it exits.. Stupid, but stable(r)
if workflowExecution.ExecutionSource != "default" { if workflowExecution.ExecutionSource != "default" {
log.Printf("Handling NON-default execution source %s - NOT waiting and validating!", workflowExecution.ExecutionSource) log.Printf("[INFO] Handling NON-default execution source %s - NOT waiting and validating!", workflowExecution.ExecutionSource)
} else if workflowExecution.ExecutionSource == "default" { } else if workflowExecution.ExecutionSource == "default" {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
@@ -850,12 +851,13 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
appname = strings.Replace(appname, ".", "-", -1) appname = strings.Replace(appname, ".", "-", -1)
appversion = strings.Replace(appversion, ".", "-", -1) appversion = strings.Replace(appversion, ".", "-", -1)
image := fmt.Sprintf("%s:%s_%s", baseimagename, action.AppName, action.AppVersion) image := fmt.Sprintf("%s:%s_%s", baseimagename, strings.ToLower(action.AppName), action.AppVersion)
if strings.Contains(image, " ") { if strings.Contains(image, " ") {
image = strings.ReplaceAll(image, " ", "-") image = strings.ReplaceAll(image, " ", "-")
} }
identifier := fmt.Sprintf("%s_%s_%s_%s", appname, appversion, action.ID, workflowExecution.ExecutionId) // Added UUID to identifier just in case
identifier := fmt.Sprintf("%s_%s_%s_%s_%s", appname, appversion, action.ID, workflowExecution.ExecutionId, uuid.NewV4())
if strings.Contains(identifier, " ") { if strings.Contains(identifier, " ") {
identifier = strings.ReplaceAll(identifier, " ", "-") identifier = strings.ReplaceAll(identifier, " ", "-")
} }
@@ -938,15 +940,15 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
} }
// Uses a few ways of getting / checking if an app is available // Uses a few ways of getting / checking if an app is available
// 1. Try original // 1. Try original with lowercase
// 2. Go to lowercase // 2. Go to original
// 3. Add remote repo location // 3. Add remote repo location
// 4. Actually download last repo // 4. Actually download last repo
images := []string{ images := []string{
fmt.Sprintf("%s/%s:%s_%s", registryName, baseimagename, strings.ToLower(action.AppName), action.AppVersion),
image, image,
fmt.Sprintf("%s:%s_%s", baseimagename, strings.ToLower(action.AppName), action.AppVersion), fmt.Sprintf("%s:%s_%s", baseimagename, action.AppName, action.AppVersion),
fmt.Sprintf("%s/%s:%s_%s", registryName, baseimagename, strings.ToLower(action.AppName), action.AppVersion),
} }
// If cleanup is set, it should run for efficiency // If cleanup is set, it should run for efficiency
@@ -959,6 +961,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
} }
log.Printf("[WARNING] Failed CLEANUP execution. Downloading image remotely.") log.Printf("[WARNING] Failed CLEANUP execution. Downloading image remotely.")
image = images[2]
reader, err := dockercli.ImagePull(context.Background(), image, pullOptions) reader, err := dockercli.ImagePull(context.Background(), image, pullOptions)
if err != nil { if err != nil {
log.Printf("[ERROR] Failed getting %s. The couldn't be find locally, AND is missing.", image) log.Printf("[ERROR] Failed getting %s. The couldn't be find locally, AND is missing.", image)
@@ -996,7 +999,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
} }
} else { } else {
err = deployApp(dockercli, image, identifier, env, workflowExecution) err = deployApp(dockercli, images[0], identifier, env, workflowExecution)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "exited prematurely") { if strings.Contains(err.Error(), "exited prematurely") {
shutdown(workflowExecution, action.ID, err.Error(), true) shutdown(workflowExecution, action.ID, err.Error(), true)
@@ -1004,7 +1007,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
// Trying to replace with lowercase to deploy again. This seems to work with Dockerhub well. // Trying to replace with lowercase to deploy again. This seems to work with Dockerhub well.
// FIXME: Should try to remotely download directly if this persists. // FIXME: Should try to remotely download directly if this persists.
image = fmt.Sprintf("%s:%s_%s", baseimagename, strings.ToLower(action.AppName), action.AppVersion) image = images[1]
if strings.Contains(image, " ") { if strings.Contains(image, " ") {
image = strings.ReplaceAll(image, " ", "-") image = strings.ReplaceAll(image, " ", "-")
} }
@@ -1015,7 +1018,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
shutdown(workflowExecution, action.ID, err.Error(), true) shutdown(workflowExecution, action.ID, err.Error(), true)
} }
image = fmt.Sprintf("%s/%s:%s_%s", registryName, baseimagename, strings.ToLower(action.AppName), action.AppVersion) image = images[2]
if strings.Contains(image, " ") { if strings.Contains(image, " ") {
image = strings.ReplaceAll(image, " ", "-") image = strings.ReplaceAll(image, " ", "-")
} }
@@ -1026,7 +1029,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
shutdown(workflowExecution, action.ID, err.Error(), true) shutdown(workflowExecution, action.ID, err.Error(), true)
} }
log.Printf("[WARNING] Failed deploying image THRICE. Attempting to download the latter as last resort.") log.Printf("[WARNING] Failed deploying image THREE TIMES. Attempting to download the latter as last resort.")
reader, err := dockercli.ImagePull(context.Background(), image, pullOptions) reader, err := dockercli.ImagePull(context.Background(), image, pullOptions)
if err != nil { if err != nil {
log.Printf("[ERROR] Failed getting %s. The couldn't be find locally, AND is missing.", image) log.Printf("[ERROR] Failed getting %s. The couldn't be find locally, AND is missing.", image)