Fixed no-path issue with requirement of leading /
This commit is contained in:
@@ -7,15 +7,12 @@ WORKDIR /app
|
||||
ADD ./go-app/main.go /app
|
||||
ADD ./go-app/walkoff.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/go.mod /app
|
||||
|
||||
# Required files for code generation
|
||||
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/static_baseline.py /app_sdk_kali
|
||||
ADD ./app_sdk_blackarch/app_base.py /app_sdk_blackarch
|
||||
|
||||
@@ -2,7 +2,7 @@ module shuffle
|
||||
|
||||
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
|
||||
|
||||
require (
|
||||
@@ -18,7 +18,7 @@ require (
|
||||
github.com/docker/docker v1.13.1
|
||||
github.com/docker/go-connections v0.4.0
|
||||
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/go-git/go-billy/v5 v5.0.0
|
||||
github.com/go-git/go-git/v5 v5.0.0
|
||||
|
||||
+137
-2
@@ -77,6 +77,8 @@ var registryName = "registry.hub.docker.com"
|
||||
var runningEnvironment = "onprem"
|
||||
|
||||
var syncUrl = "https://shuffler.io"
|
||||
|
||||
//var syncUrl = "http://localhost:5002"
|
||||
var syncSubUrl = "https://shuffler.io"
|
||||
|
||||
//var syncUrl = "http://localhost:5002"
|
||||
@@ -5463,12 +5465,12 @@ func runInit(ctx context.Context) {
|
||||
}
|
||||
|
||||
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")
|
||||
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)
|
||||
var workflows []shuffle.Workflow
|
||||
_, err = dbclient.GetAll(ctx, q, &workflows)
|
||||
@@ -5918,6 +5920,138 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
|
||||
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() {
|
||||
var err error
|
||||
ctx := context.Background()
|
||||
@@ -6041,6 +6175,7 @@ func initHandlers() {
|
||||
r.HandleFunc("/api/v1/get_openapi/{key}", getOpenapi).Methods("GET", "OPTIONS")
|
||||
|
||||
// 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/orgs", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/orgs/", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
|
||||
|
||||
@@ -981,7 +981,7 @@ func validateNewWorkerExecution(body []byte) error {
|
||||
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
|
||||
@@ -4782,6 +4782,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
|
||||
workflowapp.Sharing = true
|
||||
workflowapp.Downloaded = true
|
||||
workflowapp.Hash = md5
|
||||
workflowapp.Public = true
|
||||
|
||||
err = shuffle.SetWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID)
|
||||
if err != nil {
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
version: '3'
|
||||
services:
|
||||
frontend:
|
||||
#build: ./frontend
|
||||
image: ghcr.io/frikky/shuffle-frontend:0.8.64
|
||||
build: ./frontend
|
||||
image: ghcr.io/frikky/shuffle-frontend:0.8.70
|
||||
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.64
|
||||
build: ./backend
|
||||
image: ghcr.io/frikky/shuffle-backend:0.8.70
|
||||
container_name: shuffle-backend
|
||||
hostname: ${BACKEND_HOSTNAME}
|
||||
# Here for debugging:
|
||||
@@ -47,7 +47,7 @@ services:
|
||||
- database
|
||||
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
|
||||
hostname: shuffle-orborus
|
||||
networks:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- SHUFFLE_APP_SDK_VERSION=0.8.60
|
||||
- SHUFFLE_WORKER_VERSION=0.8.63
|
||||
- SHUFFLE_WORKER_VERSION=0.8.70
|
||||
- ORG_ID=${ORG_ID}
|
||||
- ENVIRONMENT_NAME=${ENVIRONMENT_NAME}
|
||||
- BASE_URL=http://${OUTER_HOSTNAME}:${BACKEND_PORT}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ COPY ./*.json /usr/src/app/
|
||||
RUN yarn build
|
||||
|
||||
# Production environment
|
||||
FROM nginx:latest
|
||||
FROM nginx:1.19
|
||||
|
||||
RUN mkdir -p /usr/share/nginx/html/build
|
||||
RUN mkdir -p /usr/share/nginx/html/css
|
||||
|
||||
@@ -39,6 +39,23 @@ const data = [{
|
||||
'border-color': '#81c784',
|
||||
'background-width': '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: {
|
||||
'background-color': '#77b0d0',
|
||||
'border-color': '#77b0d0',
|
||||
@@ -187,6 +204,8 @@ const data = [{
|
||||
'border-width': '12px',
|
||||
'transition-property': 'border-width',
|
||||
'transition-duration': '0.25s',
|
||||
'font-size': '30px',
|
||||
'label': 'data(label)',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -92,7 +92,6 @@ const AngularWorkflow = (props) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const [bodyWidth, bodyHeight] = useWindowSize();
|
||||
const appBarSize = 75
|
||||
|
||||
var to_be_copied = ""
|
||||
const [cystyle, ] = useState(cytoscapestyle)
|
||||
@@ -190,18 +189,22 @@ const AngularWorkflow = (props) => {
|
||||
const [workflowExecutions, setWorkflowExecutions] = React.useState([]);
|
||||
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 triggerEnvironments = cloudSyncEnabled ? ["cloud", "onprem"] : environments
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"
|
||||
const appBarSize = isCloud ? 75 : 60
|
||||
const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"]
|
||||
|
||||
const unloadText = 'Are you sure you want to leave without saving (CTRL+S)?'
|
||||
|
||||
useBeforeunload(() => {
|
||||
if (!lastSaved) {
|
||||
return unloadText
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const [elements, setElements] = useState([])
|
||||
// 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
|
||||
@@ -1121,7 +1124,7 @@ const AngularWorkflow = (props) => {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -1215,9 +1218,36 @@ const AngularWorkflow = (props) => {
|
||||
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:
|
||||
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
|
||||
const onNodeSelect = (event, newAppAuth) => {
|
||||
|
||||
const data = event.target.data()
|
||||
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(() => {
|
||||
if (firstrequest) {
|
||||
setFirstrequest(false)
|
||||
@@ -1642,14 +1683,14 @@ const AngularWorkflow = (props) => {
|
||||
}
|
||||
|
||||
// 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)
|
||||
setupGraph()
|
||||
} 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 means we need everything else to happen first.
|
||||
console.log("AUTH IN HERE: ", appAuthentication)
|
||||
|
||||
//
|
||||
//console.log("IN THIS PART AGAIN")
|
||||
|
||||
setEstablished(true)
|
||||
cy.edgehandles({
|
||||
@@ -1677,6 +1718,9 @@ const AngularWorkflow = (props) => {
|
||||
cy.on('mouseover', 'node', (e) => onNodeHover(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('cxttapstart', 'node', (e) => edgeHandler.start(e.target))
|
||||
@@ -1711,7 +1755,7 @@ const AngularWorkflow = (props) => {
|
||||
const onNodeHover = (event) => {
|
||||
event.target.animate({
|
||||
style: {
|
||||
"border-width": "5px",
|
||||
"border-width": "7px",
|
||||
"border-opacity": ".7",
|
||||
}
|
||||
}, {
|
||||
@@ -1727,8 +1771,13 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
// This is here to have a proper transition for lines
|
||||
const onEdgeHover = (event) => {
|
||||
if (event === null || event === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const sourcecolor = cy.getElementById(event.target.data("source")).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({
|
||||
style: {
|
||||
"line-fill": "linear-gradient",
|
||||
@@ -1739,6 +1788,7 @@ const AngularWorkflow = (props) => {
|
||||
duration: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const setupGraph = () => {
|
||||
@@ -1799,6 +1849,31 @@ const AngularWorkflow = (props) => {
|
||||
conditions: conditions,
|
||||
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;
|
||||
})
|
||||
|
||||
@@ -4506,7 +4581,7 @@ const AngularWorkflow = (props) => {
|
||||
: null
|
||||
}
|
||||
onClick={() => {
|
||||
console.log("CHANGE FIELD")
|
||||
//console.log("CHANGE FIELD")
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
changeActionVariable(data.action_field, e.target.value)
|
||||
@@ -4803,6 +4878,7 @@ const AngularWorkflow = (props) => {
|
||||
onClick={() => {
|
||||
setSelectedEdge({})
|
||||
|
||||
|
||||
var data = {
|
||||
condition: conditionValue,
|
||||
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)
|
||||
workflow.branches[selectedEdgeIndex] = selectedEdge
|
||||
setWorkflow(workflow)
|
||||
@@ -6494,7 +6582,7 @@ const AngularWorkflow = (props) => {
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/* <FileMenu /> */}
|
||||
<WorkflowMenu />
|
||||
{workflow.configuration !== null && workflow.configuration !== undefined && workflow.configuration.exit_on_error !== undefined ? <WorkflowMenu /> : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -7211,6 +7299,7 @@ const AngularWorkflow = (props) => {
|
||||
stylesheet={cystyle}
|
||||
boxSelectionEnabled={true}
|
||||
autounselectify={false}
|
||||
showGrid={true}
|
||||
cy={(incy) => {
|
||||
// FIXME: There's something specific loading when
|
||||
// you do the first hover of a node. Why is this different?
|
||||
|
||||
@@ -1565,9 +1565,9 @@ const AppCreator = (props) => {
|
||||
}
|
||||
|
||||
// Url verification
|
||||
if (currentAction.url.length === 0) {
|
||||
errormessage.push("URL path can't be empty.")
|
||||
} else if (!currentAction.url.startsWith("/") && baseUrl.length > 0) {
|
||||
//if (currentAction.url.length === 0) {
|
||||
// errormessage.push("URL path can't be empty.")
|
||||
if (!currentAction.url.startsWith("/") && baseUrl.length > 0 && currentAction.url.length > 0) {
|
||||
errormessage.push("URL must start with /")
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,9 @@ const flexContainerStyle = {
|
||||
}
|
||||
|
||||
const flexBoxStyle = {
|
||||
width: "333px",
|
||||
height: "125px",
|
||||
margin: "10px",
|
||||
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)",
|
||||
width: 333,
|
||||
height: 125,
|
||||
borderRadius: 4,
|
||||
boxSizing: "border-box",
|
||||
letterSpacing: "0.4px",
|
||||
color: "#D6791E",
|
||||
@@ -299,37 +297,37 @@ const MyView = (props) => {
|
||||
}
|
||||
|
||||
const paperAppContainer = {
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
flexWrap: 'wrap',
|
||||
alignContent: "space-between",
|
||||
}
|
||||
|
||||
|
||||
|
||||
const paperAppStyle = {
|
||||
minHeight: "148px",
|
||||
width: "333px",
|
||||
margin: "10px",
|
||||
minHeight: 130,
|
||||
width: "100%",
|
||||
color: "white",
|
||||
backgroundColor: surfaceColor,
|
||||
padding: "12px 12px 0px 15px",
|
||||
borderRadius: 5,
|
||||
padding: "10px",
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
boxSizing: "border-box",
|
||||
position: "relative",
|
||||
}
|
||||
|
||||
const gridContainer = {
|
||||
cursor: "pointer",
|
||||
height: "auto",
|
||||
color: "white",
|
||||
margin: "10px",
|
||||
backgroundColor: surfaceColor,
|
||||
}
|
||||
|
||||
const workFlowActionStyle = {
|
||||
const workflowActionStyle = {
|
||||
flex: "1",
|
||||
display: "flex",
|
||||
width: "150px",
|
||||
width: 150,
|
||||
height: 44,
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden"
|
||||
}
|
||||
@@ -535,23 +533,28 @@ const MyView = (props) => {
|
||||
});
|
||||
}
|
||||
|
||||
const getWorkFlowMeta = (data) => {
|
||||
const getWorkflowMeta = (data) => {
|
||||
let triggers = 0
|
||||
let schedules = 0
|
||||
let webhooks = 0
|
||||
let webhookImg = ""
|
||||
let scheduleImg = ""
|
||||
let subflows = 0
|
||||
if (data.triggers !== undefined && data.triggers !== null && data.triggers.length > 0) {
|
||||
triggers = data.triggers.length
|
||||
for (let key in data.triggers) {
|
||||
|
||||
if (data.triggers[key].app_name === "Webhook") {
|
||||
webhooks += 1
|
||||
webhookImg = data.triggers[key].large_image
|
||||
//webhookImg = data.triggers[key].large_image
|
||||
} else if (data.triggers[key].app_name === "Schedule") {
|
||||
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
|
||||
@@ -565,9 +568,9 @@ const MyView = (props) => {
|
||||
boxWidth = "4px"
|
||||
}
|
||||
|
||||
var boxColor = "orange"
|
||||
var boxColor = "#FECC00"
|
||||
if (data.is_valid) {
|
||||
boxColor = "green"
|
||||
boxColor = "#86c142"
|
||||
}
|
||||
|
||||
const menuClick = (event) => {
|
||||
@@ -575,45 +578,57 @@ const MyView = (props) => {
|
||||
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 [triggers, schedules, webhooks, subflows] = getWorkflowMeta(data)
|
||||
|
||||
const [schedules, webhooks] = getWorkFlowMeta(data);
|
||||
|
||||
const imgSize = 25
|
||||
return (
|
||||
<Paper square style={paperAppStyle} onClick={(e) => {
|
||||
}}>
|
||||
<div style={{width: boxWidth, backgroundColor: boxColor,}} onClick={() => {
|
||||
if (selectedWorkflow.id !== data.id) {
|
||||
setSelectedWorkflow(data)
|
||||
//getWorkflowExecution(data.id)
|
||||
}
|
||||
}}/>
|
||||
<Grid container style={{margin: "0px 10px 0px 10px", flex: 1}}>
|
||||
<Grid item xs={4} spacing={4} style={{padding: 10,}}>
|
||||
<Paper square style={paperAppStyle} >
|
||||
<div style={{position: "absolute", bottom: 1, left: 1, height: 12, width: 12, backgroundColor: boxColor, borderRadius: "0 100px 0 0",}} />
|
||||
<Grid item style={{display: "flex", flexDirection: "column", width: "100%"}}>
|
||||
<Grid item style={{flex: 1, display: "flex"}}>
|
||||
<div onClick={() => {
|
||||
if (selectedWorkflow.id !== data.id) {
|
||||
setSelectedWorkflow(data)
|
||||
//getWorkflowExecution(data.id)
|
||||
}
|
||||
}}>
|
||||
<Typography variant="h6">
|
||||
{data.name}
|
||||
<Grid item style={{flex: 1, display: "flex", maxHeight: 34,}}>
|
||||
<Typography variant="h6" style={{marginBottom: 0, paddingBottom: 0, maxHeight: 30,}}>
|
||||
{parsedName}
|
||||
</Typography>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item style={workFlowActionStyle}>
|
||||
<Tooltip color="primary" title="Edit workflow" placement="bottom">
|
||||
<BubbleChartIcon/>
|
||||
<Grid item style={workflowActionStyle}>
|
||||
<Tooltip color="primary" title="Action amount" placement="bottom">
|
||||
<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 color="primary" title="Execute workflow" placement="bottom">
|
||||
<PlayArrowIcon color="secondary" disabled={!data.is_valid} onClick={() => executeWorkflow(data.id)} />
|
||||
<Tooltip color="primary" title="Trigger amount" placement="bottom">
|
||||
<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 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">
|
||||
<AppsIcon />
|
||||
</Tooltip>
|
||||
{webhooks > 0 ?
|
||||
<Tooltip color="primary" title={`Webhooks: ${webhooks}`} placement="bottom">
|
||||
<RestoreIcon />
|
||||
</Tooltip>
|
||||
@@ -623,8 +638,9 @@ const MyView = (props) => {
|
||||
<RestoreIcon />
|
||||
</Tooltip>
|
||||
: null}
|
||||
*/}
|
||||
</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.map((tag, index) => {
|
||||
if (index >= 3) {
|
||||
@@ -634,7 +650,7 @@ const MyView = (props) => {
|
||||
return (
|
||||
<Chip
|
||||
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}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
@@ -644,9 +660,8 @@ const MyView = (props) => {
|
||||
: null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{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>
|
||||
<IconButton
|
||||
aria-label="more"
|
||||
@@ -654,7 +669,7 @@ const MyView = (props) => {
|
||||
aria-haspopup="true"
|
||||
style={{color: "white"}}
|
||||
onClick={menuClick}
|
||||
style={{padding:"0px",color:"white"}}
|
||||
style={{padding:"0px",color:"white", color:"#979797"}}
|
||||
>
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
@@ -696,15 +711,14 @@ const MyView = (props) => {
|
||||
<Grid>
|
||||
<Link to={"/workflows/"+data.id}>
|
||||
<Tooltip title="Edit workflow" placement="bottom">
|
||||
<EditIcon style={{background: "#F85A3E",
|
||||
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"}} />
|
||||
<EditIcon style={{background: "#F85A3E", borderRadius: "4px", color: "black", height: 20, width: 20, padding: 7, fontSize: "small"}} />
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</Grid>
|
||||
</Grid>
|
||||
: null}
|
||||
</Paper>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -772,7 +786,6 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
|
||||
marginTop: "5px",
|
||||
color: "white",
|
||||
backgroundColor: surfaceColor,
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
}
|
||||
|
||||
@@ -1294,13 +1307,12 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
|
||||
let workflowData = "";
|
||||
if (workflows.length > 0) {
|
||||
const columns = [
|
||||
{ field: 'id', headerName: 'ID', width: 70, sortable: false, },
|
||||
{ field: 'title', headerName: 'Title', width: 330, },
|
||||
{ field: 'actions', headerName: 'Actions', width: 200, sortable: false,
|
||||
disableClickEventBubbling: true,
|
||||
renderCell: (params) => {
|
||||
const data = params.row.record;
|
||||
let [schedules, webhooks] = getWorkFlowMeta(data);
|
||||
let [triggers, schedules, webhooks, subflows] = getWorkflowMeta(data);
|
||||
|
||||
return <Grid item>
|
||||
<Link to={"/workflows/"+data.id}>
|
||||
@@ -1340,10 +1352,11 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
|
||||
if (index >= 3) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Chip
|
||||
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}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
@@ -1445,13 +1458,13 @@ borderRadius: "4px", color: "black", height: "30px", "width": "30px", fontSize:
|
||||
</div>
|
||||
|
||||
{view === "grid" && (
|
||||
<div style={paperAppContainer}>
|
||||
<Grid container spacing={4} style={paperAppContainer}>
|
||||
{workflows.map((data, index) => {
|
||||
return (
|
||||
<WorkflowPaper key={index} data={data} />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{view === "list" && (
|
||||
|
||||
@@ -447,12 +447,12 @@ const Workflows = (props) => {
|
||||
for (var branchkey in data.branches) {
|
||||
const branch = data.branches[branchkey]
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -505,10 +505,8 @@ const Workflows = (props) => {
|
||||
data = sanitizeWorkflow(data)
|
||||
alert.info("Sanitizing and publishing "+data.name)
|
||||
|
||||
const url = isCloud ? globalUrl : "https://shuffler.io"
|
||||
|
||||
// This ALWAYS talks to Shuffle cloud
|
||||
fetch(url+"/api/v1/workflows/"+data.id+"/publish", {
|
||||
fetch(globalUrl+"/api/v1/workflows/"+data.id+"/publish", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -521,7 +519,11 @@ const Workflows = (props) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for workflow publish :O!")
|
||||
} else {
|
||||
if (isCloud) {
|
||||
alert.success("Successfully published workflow")
|
||||
} else {
|
||||
alert.success("Successfully published workflow to https://shuffler.io")
|
||||
}
|
||||
}
|
||||
|
||||
return response.json()
|
||||
@@ -690,12 +692,10 @@ const Workflows = (props) => {
|
||||
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)))
|
||||
}
|
||||
}} key={"change"}>{"Change details"}</MenuItem>
|
||||
{isCloud ?
|
||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
|
||||
console.log("Should publish", data)
|
||||
publishWorkflow(data)
|
||||
}} key={"publish"}>{"Publish Workflow"}</MenuItem>
|
||||
: null}
|
||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
|
||||
copyWorkflow(data)
|
||||
setOpen(false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-orborus
|
||||
VERSION=0.8.64
|
||||
VERSION=0.8.70
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#docker rmi frikky/shuffle:$NAME --force
|
||||
|
||||
@@ -248,7 +248,7 @@ func initializeImages() {
|
||||
log.Printf("[WARNING] SHUFFLE_APP_SDK_VERSION not defined. Defaulting to %s", appSdkVersion)
|
||||
}
|
||||
if workerVersion == "" {
|
||||
workerVersion = "0.8.64"
|
||||
workerVersion = "0.8.70"
|
||||
log.Printf("[WARNING] SHUFFLE_WORKER_VERSION not defined. Defaulting to %s", workerVersion)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ RUN go get github.com/docker/docker/api/types && \
|
||||
go get github.com/docker/docker/client && \
|
||||
go get github.com/gorilla/mux && \
|
||||
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 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_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
|
||||
COPY --from=builder /app/ /
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-worker
|
||||
VERSION=0.8.64
|
||||
VERSION=0.8.70
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin .
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
//"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"github.com/satori/go.uuid"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"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)
|
||||
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" {
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
@@ -850,12 +851,13 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
appname = strings.Replace(appname, ".", "-", -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, " ") {
|
||||
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, " ") {
|
||||
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
|
||||
// 1. Try original
|
||||
// 2. Go to lowercase
|
||||
// 1. Try original with lowercase
|
||||
// 2. Go to original
|
||||
// 3. Add remote repo location
|
||||
// 4. Actually download last repo
|
||||
|
||||
images := []string{
|
||||
fmt.Sprintf("%s/%s:%s_%s", registryName, baseimagename, strings.ToLower(action.AppName), action.AppVersion),
|
||||
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
|
||||
@@ -959,6 +961,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
}
|
||||
|
||||
log.Printf("[WARNING] Failed CLEANUP execution. Downloading image remotely.")
|
||||
image = images[2]
|
||||
reader, err := dockercli.ImagePull(context.Background(), image, pullOptions)
|
||||
if err != nil {
|
||||
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 {
|
||||
|
||||
err = deployApp(dockercli, image, identifier, env, workflowExecution)
|
||||
err = deployApp(dockercli, images[0], identifier, env, workflowExecution)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exited prematurely") {
|
||||
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.
|
||||
// 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, " ") {
|
||||
image = strings.ReplaceAll(image, " ", "-")
|
||||
}
|
||||
@@ -1015,7 +1018,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
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, " ") {
|
||||
image = strings.ReplaceAll(image, " ", "-")
|
||||
}
|
||||
@@ -1026,7 +1029,7 @@ func handleExecutionResult(workflowExecution shuffle.WorkflowExecution) {
|
||||
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)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed getting %s. The couldn't be find locally, AND is missing.", image)
|
||||
|
||||
Reference in New Issue
Block a user