Added fixes towards new worker deployment
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
### DEFAULT
|
### DEFAULT
|
||||||
NAME=shuffle-app_sdk
|
NAME=shuffle-app_sdk
|
||||||
VERSION=0.9.34
|
VERSION=0.9.35
|
||||||
|
|
||||||
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
||||||
docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION -t ghcr.io/frikky/$NAME:nightly
|
docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION -t ghcr.io/frikky/$NAME:nightly
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/h2non/filetype v1.1.1
|
github.com/h2non/filetype v1.1.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.1.35
|
github.com/shuffle/shuffle-shared v0.1.36
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||||
|
|||||||
+66
-1
@@ -3809,6 +3809,7 @@ func runInitEs(ctx context.Context) {
|
|||||||
|
|
||||||
log.Printf("[DEBUG] Getting organizations")
|
log.Printf("[DEBUG] Getting organizations")
|
||||||
activeOrgs, err := shuffle.GetAllOrgs(ctx)
|
activeOrgs, err := shuffle.GetAllOrgs(ctx)
|
||||||
|
|
||||||
setUsers := false
|
setUsers := false
|
||||||
//log.Printf("ORGS: %d", len(activeOrgs))
|
//log.Printf("ORGS: %d", len(activeOrgs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -3896,6 +3897,7 @@ func runInitEs(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = setUsers
|
||||||
schedules, err := shuffle.GetAllSchedules(ctx, "ALL")
|
schedules, err := shuffle.GetAllSchedules(ctx, "ALL")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed getting schedules during service init: %s", err)
|
log.Printf("[WARNING] Failed getting schedules during service init: %s", err)
|
||||||
@@ -3937,6 +3939,7 @@ func runInitEs(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parsedApikey := ""
|
||||||
users, err := shuffle.GetAllUsers(ctx)
|
users, err := shuffle.GetAllUsers(ctx)
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
log.Printf("[INFO] Trying to set up user based on environments SHUFFLE_DEFAULT_USERNAME & SHUFFLE_DEFAULT_PASSWORD")
|
log.Printf("[INFO] Trying to set up user based on environments SHUFFLE_DEFAULT_USERNAME & SHUFFLE_DEFAULT_PASSWORD")
|
||||||
@@ -3948,6 +3951,10 @@ func runInitEs(ctx context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
apikey := os.Getenv("SHUFFLE_DEFAULT_APIKEY")
|
apikey := os.Getenv("SHUFFLE_DEFAULT_APIKEY")
|
||||||
|
|
||||||
|
if len(parsedApikey) == 0 {
|
||||||
|
parsedApikey = apikey
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Creating org for default user %s", username)
|
log.Printf("[DEBUG] Creating org for default user %s", username)
|
||||||
orgId := uuid.NewV4().String()
|
orgId := uuid.NewV4().String()
|
||||||
orgSetupName := "default"
|
orgSetupName := "default"
|
||||||
@@ -3996,8 +4003,15 @@ func runInitEs(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for _, user := range users {
|
||||||
|
if user.Role == "admin" && len(user.ApiKey) > 0 {
|
||||||
|
parsedApikey = user.ApiKey
|
||||||
|
log.Printf("[DEBUG] Using apikey of %s (%s) for cleanup", user.Username, user.Id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ = setUsers
|
|
||||||
|
|
||||||
log.Printf("[INFO] Starting cloud schedules for orgs if enabled!")
|
log.Printf("[INFO] Starting cloud schedules for orgs if enabled!")
|
||||||
type requestStruct struct {
|
type requestStruct struct {
|
||||||
@@ -4041,6 +4055,57 @@ func runInitEs(ctx context.Context) {
|
|||||||
forceUpdate = true
|
forceUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Have this for all envs in all orgs (loop and find).
|
||||||
|
if len(parsedApikey) > 0 {
|
||||||
|
cleanupSchedule := 3600
|
||||||
|
environments := []string{"Shuffle"}
|
||||||
|
log.Printf("[DEBUG] Starting schedule setup for execution cleanup every %d seconds. Running first immediately.", cleanupSchedule)
|
||||||
|
cleanupJob := func() func() {
|
||||||
|
return func() {
|
||||||
|
log.Printf("[INFO] Running schedule for cleaning up or re-running unfinished workflows in %d environments.", len(environments))
|
||||||
|
|
||||||
|
for _, environment := range environments {
|
||||||
|
url := fmt.Sprintf("http://localhost:5001/api/v1/environments/%s/stop", environment)
|
||||||
|
httpClient := &http.Client{}
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
"GET",
|
||||||
|
url,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
req.Header.Add("Authorization", fmt.Sprintf(`Bearer %s`, parsedApikey))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed CREATING environment request for %s: %s", environment, err)
|
||||||
|
continue
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
newresp, err := httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed running environment request %s: %s", environment, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
respBody, err := ioutil.ReadAll(newresp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed setting respbody %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] Successfully ran workflow cleanup request for %s. Body: %s", environment, string(respBody))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jobret, err := newscheduler.Every(cleanupSchedule).Seconds().Run(cleanupJob())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed to schedule Cleanup: %s", err)
|
||||||
|
} else {
|
||||||
|
_ = jobret
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Couldn't find a valid API-key, hence couldn't run cleanup")
|
||||||
|
}
|
||||||
|
|
||||||
// Getting apps to see if we should initialize a test
|
// Getting apps to see if we should initialize a test
|
||||||
// FIXME: Isn't this a little backwards?
|
// FIXME: Isn't this a little backwards?
|
||||||
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 1000)
|
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 1000)
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
#build: ./frontend
|
build: ./frontend
|
||||||
image: ghcr.io/frikky/shuffle-frontend:nightly
|
image: ghcr.io/frikky/shuffle-frontend:nightly
|
||||||
container_name: shuffle-frontend
|
container_name: shuffle-frontend
|
||||||
hostname: shuffle-frontend
|
hostname: shuffle-frontend
|
||||||
@@ -16,7 +16,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
backend:
|
backend:
|
||||||
build: ./backend
|
#build: ./backend
|
||||||
image: ghcr.io/frikky/shuffle-backend:nightly
|
image: ghcr.io/frikky/shuffle-backend:nightly
|
||||||
container_name: shuffle-backend
|
container_name: shuffle-backend
|
||||||
hostname: ${BACKEND_HOSTNAME}
|
hostname: ${BACKEND_HOSTNAME}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import { createMuiTheme, MuiThemeProvider } from "@material-ui/core/styles";
|
|||||||
|
|
||||||
import ScrollToTop from "./components/ScrollToTop";
|
import ScrollToTop from "./components/ScrollToTop";
|
||||||
import AlertTemplate from "./components/AlertTemplate";
|
import AlertTemplate from "./components/AlertTemplate";
|
||||||
import { positions, Provider } from "react-alert";
|
import { useAlert, positions, Provider } from "react-alert";
|
||||||
import { isMobile } from "react-device-detect";
|
import { isMobile } from "react-device-detect";
|
||||||
|
|
||||||
import detectEthereumProvider from "@metamask/detect-provider";
|
import detectEthereumProvider from "@metamask/detect-provider";
|
||||||
@@ -51,16 +51,17 @@ if (window.location.port === "3000") {
|
|||||||
|
|
||||||
const App = (message, props) => {
|
const App = (message, props) => {
|
||||||
const [userdata, setUserData] = useState({});
|
const [userdata, setUserData] = useState({});
|
||||||
const [notifications, setNotifications] = useState([]);
|
const [notifications, setNotifications] = useState([])
|
||||||
const [cookies, setCookie, removeCookie] = useCookies([]);
|
const [cookies, setCookie, removeCookie] = useCookies([])
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
const [isLoggedIn, setIsLoggedIn] = useState(false)
|
||||||
const [dataset, setDataset] = useState(false);
|
const [dataset, setDataset] = useState(false)
|
||||||
const [isLoaded, setIsLoaded] = useState(false);
|
const [isLoaded, setIsLoaded] = useState(false)
|
||||||
const [curpath, setCurpath] = useState(
|
const [curpath, setCurpath] = useState(
|
||||||
typeof window === "undefined" || window.location === undefined
|
typeof window === "undefined" || window.location === undefined
|
||||||
? ""
|
? ""
|
||||||
: window.location.pathname
|
: window.location.pathname
|
||||||
);
|
)
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dataset === false) {
|
if (dataset === false) {
|
||||||
@@ -468,6 +469,7 @@ const App = (message, props) => {
|
|||||||
path="/workflows/:key"
|
path="/workflows/:key"
|
||||||
render={(props) => (
|
render={(props) => (
|
||||||
<AngularWorkflow
|
<AngularWorkflow
|
||||||
|
alert={alert}
|
||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
isLoaded={isLoaded}
|
isLoaded={isLoaded}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Fade,
|
Fade,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HelpOutline as HelpOutlineIcon,
|
HelpOutline as HelpOutlineIcon,
|
||||||
Description as DescriptionIcon,
|
Description as DescriptionIcon,
|
||||||
@@ -424,8 +425,8 @@ const ParsedAction = (props) => {
|
|||||||
type: "Shuffle DB",
|
type: "Shuffle DB",
|
||||||
name: "Shuffle DB",
|
name: "Shuffle DB",
|
||||||
value: "$shuffle_cache",
|
value: "$shuffle_cache",
|
||||||
highlight: "shuffle",
|
highlight: "shuffle_cache",
|
||||||
autocomplete: "shuffle",
|
autocomplete: "shuffle_cache",
|
||||||
example: "",
|
example: "",
|
||||||
});
|
});
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -53,17 +53,18 @@ const data = [
|
|||||||
selector: `node[type="COMMENT"]`,
|
selector: `node[type="COMMENT"]`,
|
||||||
css: {
|
css: {
|
||||||
shape: "roundrectangle",
|
shape: "roundrectangle",
|
||||||
"background-color": "data(backgroundcolor)",
|
|
||||||
"border-color": "#ffffff",
|
|
||||||
color: "data(color)",
|
color: "data(color)",
|
||||||
width: "data(width)",
|
width: "data(width)",
|
||||||
height: "data(height)",
|
height: "data(height)",
|
||||||
"border-radius": "5px",
|
|
||||||
"background-opacity": "0.5",
|
|
||||||
padding: "0px",
|
padding: "0px",
|
||||||
margin: "0px",
|
margin: "0px",
|
||||||
|
"background-color": "data(backgroundcolor)",
|
||||||
|
"border-color": "#ffffff",
|
||||||
"text-margin-x": "0px",
|
"text-margin-x": "0px",
|
||||||
"z-index": 4999,
|
"z-index": 4999,
|
||||||
|
"border-radius": "5px",
|
||||||
|
"background-opacity": "0.5",
|
||||||
|
"text-wrap": "wrap",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ const theme = createMuiTheme({
|
|||||||
surfaceColor: "#27292d",
|
surfaceColor: "#27292d",
|
||||||
inputColor: "#383B40",
|
inputColor: "#383B40",
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
|
jsonTheme: "brewer",
|
||||||
|
reactJsonStyle: {
|
||||||
|
borderRadius: 5,
|
||||||
|
border: "1px solid rgba(255,255,255,0.7)",
|
||||||
|
padding: 5,
|
||||||
|
},
|
||||||
textFieldStyle: {
|
textFieldStyle: {
|
||||||
backgroundColor: "#383B40",
|
backgroundColor: "#383B40",
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import { useBeforeunload } from "react-beforeunload";
|
|||||||
import ReactJson from "react-json-view";
|
import ReactJson from "react-json-view";
|
||||||
import NestedMenuItem from "material-ui-nested-menu-item";
|
import NestedMenuItem from "material-ui-nested-menu-item";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import { useAlert } from "react-alert";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Popover,
|
||||||
TextField,
|
TextField,
|
||||||
Drawer,
|
Drawer,
|
||||||
Button,
|
Button,
|
||||||
@@ -85,7 +87,6 @@ import Draggable from "react-draggable";
|
|||||||
import cytoscapestyle from "../defaultCytoscapeStyle";
|
import cytoscapestyle from "../defaultCytoscapeStyle";
|
||||||
import cxtmenu from "cytoscape-cxtmenu";
|
import cxtmenu from "cytoscape-cxtmenu";
|
||||||
|
|
||||||
import { useAlert } from "react-alert";
|
|
||||||
import { validateJson, GetIconInfo } from "./Workflows.jsx";
|
import { validateJson, GetIconInfo } from "./Workflows.jsx";
|
||||||
import { GetParsedPaths } from "./Apps.jsx";
|
import { GetParsedPaths } from "./Apps.jsx";
|
||||||
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
||||||
@@ -182,7 +183,7 @@ const svgSize = 24;
|
|||||||
const AngularWorkflow = (props) => {
|
const AngularWorkflow = (props) => {
|
||||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
||||||
const referenceUrl = globalUrl + "/api/v1/hooks/";
|
const referenceUrl = globalUrl + "/api/v1/hooks/";
|
||||||
const alert = useAlert();
|
const alert = useAlert()
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const green = "#86c142";
|
const green = "#86c142";
|
||||||
const yellow = "#FECC00";
|
const yellow = "#FECC00";
|
||||||
@@ -190,6 +191,7 @@ const AngularWorkflow = (props) => {
|
|||||||
const [bodyWidth, bodyHeight] = useWindowSize();
|
const [bodyWidth, bodyHeight] = useWindowSize();
|
||||||
|
|
||||||
var to_be_copied = "";
|
var to_be_copied = "";
|
||||||
|
const [firstrequest, setFirstrequest] = React.useState(true);
|
||||||
const [cystyle] = useState(cytoscapestyle);
|
const [cystyle] = useState(cytoscapestyle);
|
||||||
const [cy, setCy] = React.useState();
|
const [cy, setCy] = React.useState();
|
||||||
|
|
||||||
@@ -274,7 +276,6 @@ const AngularWorkflow = (props) => {
|
|||||||
const [apps, setApps] = React.useState([]);
|
const [apps, setApps] = React.useState([]);
|
||||||
const [filteredApps, setFilteredApps] = React.useState([]);
|
const [filteredApps, setFilteredApps] = React.useState([]);
|
||||||
const [prioritizedApps, setPrioritizedApps] = React.useState([]);
|
const [prioritizedApps, setPrioritizedApps] = React.useState([]);
|
||||||
const [firstrequest, setFirstrequest] = React.useState(true);
|
|
||||||
|
|
||||||
const [environments, setEnvironments] = React.useState([]);
|
const [environments, setEnvironments] = React.useState([]);
|
||||||
const [established, setEstablished] = React.useState(false);
|
const [established, setEstablished] = React.useState(false);
|
||||||
@@ -992,12 +993,28 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
var curworkflowComment = useworkflow.comments.find(
|
var curworkflowComment = useworkflow.comments.find(
|
||||||
(a) => a.id === cyelements[key].data()["id"]
|
(a) => a.id === cyelements[key].data()["id"]
|
||||||
);
|
)
|
||||||
|
|
||||||
if (curworkflowComment === undefined) {
|
if (curworkflowComment === undefined) {
|
||||||
curworkflowComment = cyelements[key].data();
|
curworkflowComment = cyelements[key].data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parsedHeight = parseInt(curworkflowComment["height"])
|
||||||
|
if (!isNaN(parsedHeight)) {
|
||||||
|
curworkflowComment.height = parsedHeight
|
||||||
|
} else {
|
||||||
|
curworkflowComment.width = 150
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedWidth = parseInt(curworkflowComment["width"])
|
||||||
|
if (!isNaN(parsedWidth)) {
|
||||||
|
curworkflowComment.width = parsedWidth
|
||||||
|
} else {
|
||||||
|
curworkflowComment.width = 200
|
||||||
|
}
|
||||||
|
|
||||||
curworkflowComment.position = cyelements[key].position();
|
curworkflowComment.position = cyelements[key].position();
|
||||||
|
console.log(curworkflowComment)
|
||||||
|
|
||||||
newComments.push(curworkflowComment);
|
newComments.push(curworkflowComment);
|
||||||
} else {
|
} else {
|
||||||
@@ -1935,6 +1952,7 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
// Nodeselectbatching:
|
// Nodeselectbatching:
|
||||||
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
|
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
|
||||||
|
// onNodeClick
|
||||||
const onNodeSelect = (event, newAppAuth) => {
|
const onNodeSelect = (event, newAppAuth) => {
|
||||||
const data = event.target.data();
|
const data = event.target.data();
|
||||||
if (data.isButton) {
|
if (data.isButton) {
|
||||||
@@ -2076,9 +2094,13 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === "ACTION") {
|
if (data.type === "ACTION") {
|
||||||
|
//var curaction = JSON.parse(JSON.stringify(data))
|
||||||
|
// FIXME: Trust it to just work?
|
||||||
|
//event.target.data()
|
||||||
var curaction = workflow.actions.find((a) => a.id === data.id);
|
var curaction = workflow.actions.find((a) => a.id === data.id);
|
||||||
if (!curaction || curaction === undefined) {
|
if (!curaction || curaction === undefined) {
|
||||||
alert.error("Action not found. Please remake it.");
|
alert.error("Action not found. Please remake it.");
|
||||||
|
event.target.remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2632,10 +2654,12 @@ const AngularWorkflow = (props) => {
|
|||||||
setLastSaved(false);
|
setLastSaved(false);
|
||||||
const node = event.target;
|
const node = event.target;
|
||||||
const nodedata = event.target.data();
|
const nodedata = event.target.data();
|
||||||
|
console.log("Node added: ", nodedata)
|
||||||
if (
|
if (
|
||||||
nodedata.finished === false ||
|
nodedata.finished === false ||
|
||||||
(nodedata.id !== undefined && nodedata.is_valid === undefined)
|
(nodedata.id !== undefined && nodedata.is_valid === undefined)
|
||||||
) {
|
) {
|
||||||
|
console.log("Returning because node is not valid: ", nodedata)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2645,6 +2669,7 @@ const AngularWorkflow = (props) => {
|
|||||||
nodedata.isStartNode = true;
|
nodedata.isStartNode = true;
|
||||||
} else {
|
} else {
|
||||||
if (workflow.actions === null) {
|
if (workflow.actions === null) {
|
||||||
|
console.log("Returning because node has no value")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2658,6 +2683,13 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nodedata.type === "ACTION") {
|
if (nodedata.type === "ACTION") {
|
||||||
|
/*
|
||||||
|
var curaction = workflow.actions.find((a) => a.id === nodedata.id);
|
||||||
|
if (curaction === null || curaction === undefined) {
|
||||||
|
alert.error("Node not found. Please remake it.")
|
||||||
|
event.target.remove();
|
||||||
|
}
|
||||||
|
*/
|
||||||
if (
|
if (
|
||||||
workflow.actions.length === 1 &&
|
workflow.actions.length === 1 &&
|
||||||
workflow.actions[0].id === workflow.start
|
workflow.actions[0].id === workflow.start
|
||||||
@@ -2894,7 +2926,6 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 67:
|
case 67:
|
||||||
console.log(event);
|
|
||||||
if (event.ctrlKey && !event.shiftKey) {
|
if (event.ctrlKey && !event.shiftKey) {
|
||||||
if (
|
if (
|
||||||
event.path !== undefined &&
|
event.path !== undefined &&
|
||||||
@@ -3121,6 +3152,7 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
// App length necessary cus of cy initialization
|
// App length necessary cus of cy initialization
|
||||||
if (
|
if (
|
||||||
|
// First load - gets the workflow
|
||||||
elements.length === 0 &&
|
elements.length === 0 &&
|
||||||
workflow.actions !== undefined &&
|
workflow.actions !== undefined &&
|
||||||
!graphSetup &&
|
!graphSetup &&
|
||||||
@@ -3129,6 +3161,8 @@ const AngularWorkflow = (props) => {
|
|||||||
setGraphSetup(true);
|
setGraphSetup(true);
|
||||||
setupGraph();
|
setupGraph();
|
||||||
} else if (
|
} else if (
|
||||||
|
// 2nd load - configures cytoscape
|
||||||
|
//
|
||||||
!established &&
|
!established &&
|
||||||
cy !== undefined &&
|
cy !== undefined &&
|
||||||
apps !== null &&
|
apps !== null &&
|
||||||
@@ -3143,11 +3177,16 @@ const AngularWorkflow = (props) => {
|
|||||||
setEstablished(true);
|
setEstablished(true);
|
||||||
// Validate if the node is just a node lol
|
// Validate if the node is just a node lol
|
||||||
cy.edgehandles({
|
cy.edgehandles({
|
||||||
handleNodes: (el) =>
|
handleNodes: (el) => {
|
||||||
el.isNode() &&
|
if (el.isNode() &&
|
||||||
!el.data("isButton") &&
|
!el.data("isButton") &&
|
||||||
!el.data("isDescriptor") &&
|
!el.data("isDescriptor") &&
|
||||||
!el.data("type") === "COMMENT",
|
el.data("type") !== "COMMENT") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
preview: false,
|
preview: false,
|
||||||
toggleOffOnLeave: false,
|
toggleOffOnLeave: false,
|
||||||
loopAllowed: function (node) {
|
loopAllowed: function (node) {
|
||||||
@@ -3175,7 +3214,7 @@ const AngularWorkflow = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cy.on("select", "node", (e) => {
|
cy.on("select", "node", (e) => {
|
||||||
onNodeSelect(e, appAuthentication);
|
onNodeSelect(e, appAuthentication);
|
||||||
});
|
});
|
||||||
cy.on("select", "edge", (e) => onEdgeSelect(e));
|
cy.on("select", "edge", (e) => onEdgeSelect(e));
|
||||||
|
|
||||||
@@ -3734,8 +3773,8 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedNode.data().decorator === true) {
|
if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") {
|
||||||
alert.info("This edge can't be deleted.");
|
alert.info("This node can't be deleted.");
|
||||||
} else {
|
} else {
|
||||||
selectedNode.remove();
|
selectedNode.remove();
|
||||||
}
|
}
|
||||||
@@ -5307,8 +5346,16 @@ const AngularWorkflow = (props) => {
|
|||||||
value: "$exec",
|
value: "$exec",
|
||||||
highlight: "exec",
|
highlight: "exec",
|
||||||
autocomplete: "exec",
|
autocomplete: "exec",
|
||||||
example: "hello",
|
example: "tmp",
|
||||||
});
|
})
|
||||||
|
actionlist.push({
|
||||||
|
type: "Shuffle DB",
|
||||||
|
name: "Shuffle DB",
|
||||||
|
value: "shuffle_cache",
|
||||||
|
highlight: "shuffle_cache",
|
||||||
|
autocomplete: "shuffle_cache",
|
||||||
|
example: "tmp",
|
||||||
|
})
|
||||||
|
|
||||||
if (
|
if (
|
||||||
workflow.workflow_variables !== null &&
|
workflow.workflow_variables !== null &&
|
||||||
@@ -6761,7 +6808,7 @@ const AngularWorkflow = (props) => {
|
|||||||
highlight: "exec",
|
highlight: "exec",
|
||||||
autocomplete: "exec",
|
autocomplete: "exec",
|
||||||
example: "hello",
|
example: "hello",
|
||||||
});
|
})
|
||||||
if (
|
if (
|
||||||
workflow.workflow_variables !== null &&
|
workflow.workflow_variables !== null &&
|
||||||
workflow.workflow_variables !== undefined &&
|
workflow.workflow_variables !== undefined &&
|
||||||
@@ -7757,6 +7804,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
color="primary"
|
color="primary"
|
||||||
|
placeholder={"150"}
|
||||||
defaultValue={selectedComment.height}
|
defaultValue={selectedComment.height}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
selectedComment.height = event.target.value;
|
selectedComment.height = event.target.value;
|
||||||
@@ -7764,7 +7812,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style={{marginLeft: 5 }}>
|
||||||
<div>Width</div>
|
<div>Width</div>
|
||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
@@ -7782,6 +7830,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
color="primary"
|
color="primary"
|
||||||
|
placeholder={"200"}
|
||||||
defaultValue={selectedComment.width}
|
defaultValue={selectedComment.width}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
selectedComment.width = event.target.value;
|
selectedComment.width = event.target.value;
|
||||||
@@ -7809,6 +7858,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
color="primary"
|
color="primary"
|
||||||
|
placeholder={"#1f2023"}
|
||||||
defaultValue={selectedComment["backgroundcolor"]}
|
defaultValue={selectedComment["backgroundcolor"]}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
selectedComment.backgroundcolor = event.target.value;
|
selectedComment.backgroundcolor = event.target.value;
|
||||||
@@ -7816,7 +7866,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style={{marginLeft: 5}}>
|
||||||
<div>Text Color</div>
|
<div>Text Color</div>
|
||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
@@ -7834,6 +7884,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
color="primary"
|
color="primary"
|
||||||
|
placeholder={"#ffffff"}
|
||||||
defaultValue={selectedComment.color}
|
defaultValue={selectedComment.color}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
selectedComment.color = event.target.value;
|
selectedComment.color = event.target.value;
|
||||||
@@ -9550,7 +9601,6 @@ const AngularWorkflow = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (Object.getOwnPropertyNames(selectedComment).length > 0) {
|
} else if (Object.getOwnPropertyNames(selectedComment).length > 0) {
|
||||||
console.log("Returning comment field");
|
|
||||||
return (
|
return (
|
||||||
<div style={rightsidebarStyle}>
|
<div style={rightsidebarStyle}>
|
||||||
<CommentSidebar />
|
<CommentSidebar />
|
||||||
@@ -9675,21 +9725,57 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactJson
|
<div style={{display: "flex"}}>
|
||||||
src={validate.result}
|
<IconButton
|
||||||
theme="solarized"
|
style={{
|
||||||
collapsed={true}
|
marginTop: "auto",
|
||||||
displayDataTypes={false}
|
marginBottom: "auto",
|
||||||
enableClipboard={(copy) => {
|
height: 30,
|
||||||
handleReactJsonClipboard(copy);
|
paddingLeft: 0,
|
||||||
}}
|
width: 30,
|
||||||
onSelect={(select) => {
|
}}
|
||||||
HandleJsonCopy(showResult, select, "exec");
|
onClick={() => {
|
||||||
console.log("SELECTED!: ", select);
|
setSelectedResult({
|
||||||
}}
|
"action": {
|
||||||
name={"Execution Argument"}
|
"label": "Execution Argument",
|
||||||
/>
|
"name": "Execution Argument",
|
||||||
);
|
"large_image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACOCAMAAADkWgEmAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAWlBMVEX4Wj69TDgmKCvkVTwlJyskJiokJikkJSkjJSn4Ykf+6+f5h3L////8xLr5alH/9fT7nYz4Wz/919H5cVn/+vr8qpv4XUL94d35e2X//v38t6v4YUbkVDy8SzcVIzHLAAAAAWJLR0QMgbNRYwAAAAlwSFlzAAARsAAAEbAByCf1VAAAAAd0SU1FB+QGGgsvBZ/GkmwAAAFKSURBVHja7dlrTgMxDEXhFgpTiukL2vLc/zbZQH5N7MmReu4KPmlGN4m9WgGzfhgtaOZxM1rQztNoQDvPowHtTKMB7WxHA2TJkiVLlixIZMmSRYgsWbIIkSVLFiGyZMkiRNZirBcma/eKZEW87ZGsOBxPRFbE+R3Jio/LlciKuH0iWfH1/UNkRSR3RRYruSvyWKldkcjK7IpUVl5X5LLSuiKbldQV6aycrihgZXRFCau/K2pY3V1RxersijJWX1cUsnq6opLV0RW1rNldUc2a2RXlrHldsQBrTlfcLwv5EZm/PLIgkHXKPHyQRzXzYoO8BjIvzcgnBvJBxny+Ih/7zNEIcpDEHLshh5TIkS5zAI5cFzCXK8hVFHNxh1xzQpfC0BV6XWTJkkWILFmyCJElSxYhsmTJIkSWLFmEyJIlixBZsmQB8stk/U3/Yb49pVcDMg4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDYtMjZUMTE6NDc6MDUrMDI6MDD8QCPmAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA2LTI2VDExOjQ3OjA1KzAyOjAwjR2bWgAAAABJRU5ErkJggg==",
|
||||||
|
},
|
||||||
|
"result": validate.valid ? JSON.stringify(validate.result) : validate.result,
|
||||||
|
"status": "SUCCESS"
|
||||||
|
})
|
||||||
|
setCodeModalOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
color="primary"
|
||||||
|
title="Expand result window"
|
||||||
|
placement="top"
|
||||||
|
style={{ zIndex: 10011 }}
|
||||||
|
>
|
||||||
|
<ArrowLeftIcon style={{ color: "white" }} />
|
||||||
|
</Tooltip>
|
||||||
|
</IconButton>
|
||||||
|
{/*
|
||||||
|
<ShowReactJsonField jsonValue={showResult} validate={validate} collapsed={true} label={"Execution Argument"} autocomplete={"exec"} />
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<ReactJson
|
||||||
|
src={validate.result}
|
||||||
|
theme={theme.palette.jsonTheme}
|
||||||
|
style={theme.palette.reactJsonStyle}
|
||||||
|
collapsed={true}
|
||||||
|
enableClipboard={(copy) => {
|
||||||
|
handleReactJsonClipboard(copy);
|
||||||
|
}}
|
||||||
|
displayDataTypes={false}
|
||||||
|
onSelect={(select) => {
|
||||||
|
HandleJsonCopy(validate.result, select, "exec");
|
||||||
|
}}
|
||||||
|
name={"Execution Argument"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -9879,10 +9965,124 @@ const AngularWorkflow = (props) => {
|
|||||||
/* Copy the text inside the text field */
|
/* Copy the text inside the text field */
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
console.log("COPYING!");
|
console.log("COPYING!");
|
||||||
|
alert.info("Copied value to clipboard.")
|
||||||
} else {
|
} else {
|
||||||
console.log("Couldn't find element ", elementName);
|
console.log("Couldn't find element ", elementName);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// Not used because of issue with state updates.
|
||||||
|
const ShowReactJsonField = (props) => {
|
||||||
|
const { validate, jsonValue, collapsed, label, autocomplete } = props
|
||||||
|
|
||||||
|
const [parsedCollapse, setParsedCollapse] = React.useState(collapsed)
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [anchorPosition, setAnchorPosition] = React.useState({
|
||||||
|
top: 750,
|
||||||
|
left: 16,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isFirstRender = React.useRef(true)
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("IN useeffectt "+autocomplete)
|
||||||
|
|
||||||
|
if (isFirstRender.current) {
|
||||||
|
isFirstRender.current = false;
|
||||||
|
console.log("IN useeffectt (2)"+collapsed)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
/*
|
||||||
|
componentWillUpdate = (nextProps, nextState) => {
|
||||||
|
console.log(nextProps, nextState)
|
||||||
|
//nextState.value = nextProps.a + nextProps.b;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const jsonRef = React.useRef()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<ReactJson
|
||||||
|
ref={jsonRef}
|
||||||
|
src={validate.result}
|
||||||
|
theme={theme.palette.jsonTheme}
|
||||||
|
style={theme.palette.reactJsonStyle}
|
||||||
|
collapsed={parsedCollapse}
|
||||||
|
shouldCollapse={(field) => {
|
||||||
|
console.log("FIELD: ", field)
|
||||||
|
}}
|
||||||
|
enableClipboard={(copy) => {
|
||||||
|
handleReactJsonClipboard(copy);
|
||||||
|
}}
|
||||||
|
displayDataTypes={false}
|
||||||
|
onClick={(event) => {
|
||||||
|
const pos = {
|
||||||
|
top: event.screenX,
|
||||||
|
left: event.screenY,
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("POS CLICK: ", pos)
|
||||||
|
|
||||||
|
setAnchorPosition(pos)
|
||||||
|
}}
|
||||||
|
onSelect={(select) => {
|
||||||
|
setOpen(true)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setOpen(false)
|
||||||
|
}, 2500)
|
||||||
|
|
||||||
|
//setAnchorPosition({
|
||||||
|
// top: 300,
|
||||||
|
// right: 300,
|
||||||
|
//})
|
||||||
|
//setAnchorEl(jsonRef.current)
|
||||||
|
HandleJsonCopy(jsonValue, select, autocomplete);
|
||||||
|
console.log("SELECTED!: ", select);
|
||||||
|
}}
|
||||||
|
name={label}
|
||||||
|
/>
|
||||||
|
{anchorPosition !== null ?
|
||||||
|
<Popover
|
||||||
|
id="mouse-over-popover-right"
|
||||||
|
sx={{
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
open={open}
|
||||||
|
anchorReference="anchorPosition"
|
||||||
|
anchorPosition={anchorPosition}
|
||||||
|
style={{zIndex: 50000,}}
|
||||||
|
onClose={(event) => {
|
||||||
|
setAnchorPosition({
|
||||||
|
top: 750,
|
||||||
|
left: 16,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
disableRestoreFocus
|
||||||
|
>
|
||||||
|
<Typography style={{padding: 5 }}>
|
||||||
|
Copying
|
||||||
|
</Typography>
|
||||||
|
</Popover>
|
||||||
|
: null}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowCopyingTooltip = () => {
|
||||||
|
const [showCopying, setShowCopying] = React.useState(true)
|
||||||
|
|
||||||
|
if (!showCopying) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={"Copying"} placement="left-start">
|
||||||
|
<div />
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const executionModal = (
|
const executionModal = (
|
||||||
<Drawer
|
<Drawer
|
||||||
@@ -10127,7 +10327,7 @@ const AngularWorkflow = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
title="Rerun workflow"
|
title="Rerun workflow"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 50000}}
|
||||||
>
|
>
|
||||||
<span style={{}}>
|
<span style={{}}>
|
||||||
<Button
|
<Button
|
||||||
@@ -10152,7 +10352,7 @@ const AngularWorkflow = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
title="Abort workflow"
|
title="Abort workflow"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<span style={{}}>
|
<span style={{}}>
|
||||||
<Button
|
<Button
|
||||||
@@ -10485,7 +10685,7 @@ const AngularWorkflow = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
title="Expand result window"
|
title="Expand result window"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<ArrowLeftIcon style={{ color: "white" }} />
|
<ArrowLeftIcon style={{ color: "white" }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -10561,20 +10761,26 @@ const AngularWorkflow = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
{validate.valid ? (
|
{validate.valid ? (
|
||||||
<span>
|
<span>
|
||||||
<ReactJson
|
{/*
|
||||||
src={validate.result}
|
<ShowReactJsonField jsonValue={showResult} validate={validate} collapsed={true} label={"Results for "+data.action.label} autocomplete={data.action.label} />
|
||||||
theme="solarized"
|
*/}
|
||||||
collapsed={true}
|
|
||||||
enableClipboard={(copy) => {
|
<ReactJson
|
||||||
handleReactJsonClipboard(copy);
|
src={validate.result}
|
||||||
}}
|
theme={theme.palette.jsonTheme}
|
||||||
displayDataTypes={false}
|
style={theme.palette.reactJsonStyle}
|
||||||
onSelect={(select) => {
|
collapsed={true}
|
||||||
HandleJsonCopy(showResult, select, data.action.label);
|
enableClipboard={(copy) => {
|
||||||
console.log("SELECTED!: ", select);
|
handleReactJsonClipboard(copy);
|
||||||
}}
|
}}
|
||||||
name={"Results for " + data.action.label}
|
displayDataTypes={false}
|
||||||
/>
|
onSelect={(select) => {
|
||||||
|
HandleJsonCopy(showResult, select, data.action.label);
|
||||||
|
console.log("SELECTED!: ", select);
|
||||||
|
}}
|
||||||
|
name={"Results for " + data.action.label}
|
||||||
|
/>
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -10645,7 +10851,7 @@ const AngularWorkflow = (props) => {
|
|||||||
console.log(event.srcElement);
|
console.log(event.srcElement);
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
console.log("START");
|
console.log("START");
|
||||||
setDragging(true);
|
//setDragging(true);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={draggingDisabled}
|
disabled={draggingDisabled}
|
||||||
@@ -10701,7 +10907,7 @@ const AngularWorkflow = (props) => {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
title="Find successful execution"
|
title="Find successful execution"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{
|
style={{
|
||||||
@@ -10733,7 +10939,7 @@ const AngularWorkflow = (props) => {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
title="Find failed execution"
|
title="Find failed execution"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{
|
style={{
|
||||||
@@ -10834,23 +11040,20 @@ const AngularWorkflow = (props) => {
|
|||||||
<b>Status </b> {selectedResult.status}
|
<b>Status </b> {selectedResult.status}
|
||||||
</div>
|
</div>
|
||||||
{validate.valid ? (
|
{validate.valid ? (
|
||||||
<ReactJson
|
<ReactJson
|
||||||
src={validate.result}
|
src={validate.result}
|
||||||
theme="solarized"
|
theme={theme.palette.jsonTheme}
|
||||||
collapsed={selectedResult.result.length < 10000 ? false : true}
|
style={theme.palette.reactJsonStyle}
|
||||||
displayDataTypes={false}
|
collapsed={selectedResult.result.length < 10000 ? false : true}
|
||||||
enableClipboard={(copy) => {
|
enableClipboard={(copy) => {
|
||||||
handleReactJsonClipboard(copy);
|
handleReactJsonClipboard(copy);
|
||||||
}}
|
}}
|
||||||
onSelect={(select) => {
|
displayDataTypes={false}
|
||||||
HandleJsonCopy(
|
onSelect={(select) => {
|
||||||
JSON.stringify(validate.result),
|
HandleJsonCopy(validate.result, select, selectedResult.action.label);
|
||||||
select,
|
}}
|
||||||
selectedResult.action.label
|
name={"Results for " + selectedResult.action.label}
|
||||||
);
|
/>
|
||||||
}}
|
|
||||||
name={"Results for " + selectedResult.action.label}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<b>Result</b>
|
<b>Result</b>
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ const LoginDialog = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
{MFAField === true ? (
|
{MFAField === true ? (
|
||||||
<div style={{ marginTop: 15 }}>
|
<div style={{ marginTop: 15 }}>
|
||||||
5-factor code
|
2-factor code
|
||||||
<TextField
|
<TextField
|
||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
NAME=shuffle-orborus
|
NAME=shuffle-orborus
|
||||||
VERSION=0.9.34
|
VERSION=0.9.35
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -236,7 +236,6 @@ func deployServiceWorkers(image string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
innerContainerName := fmt.Sprintf("shuffle-workers")
|
innerContainerName := fmt.Sprintf("shuffle-workers")
|
||||||
parsedConcurrent := uint64(50)
|
|
||||||
|
|
||||||
cnt, _ := findActiveSwarmNodes()
|
cnt, _ := findActiveSwarmNodes()
|
||||||
nodeCount := uint64(1)
|
nodeCount := uint64(1)
|
||||||
@@ -253,6 +252,10 @@ func deployServiceWorkers(image string) {
|
|||||||
|
|
||||||
log.Printf("[DEBUG] Deploying %d containers for worker with swarm to each node. Service name: %s. Image: %s", replicas, innerContainerName, image)
|
log.Printf("[DEBUG] Deploying %d containers for worker with swarm to each node. Service name: %s. Image: %s", replicas, innerContainerName, image)
|
||||||
|
|
||||||
|
if timezone == "" {
|
||||||
|
timezone = "Europe/Amsterdam"
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: May not need ingress ports. Could use internal services and DNS of swarm itself
|
// FIXME: May not need ingress ports. Could use internal services and DNS of swarm itself
|
||||||
// https://github.com/moby/moby/blob/e2f740de442bac52b280bc485a3ca5b31567d938/api/types/swarm/service.go#L46
|
// https://github.com/moby/moby/blob/e2f740de442bac52b280bc485a3ca5b31567d938/api/types/swarm/service.go#L46
|
||||||
serviceSpec := swarm.ServiceSpec{
|
serviceSpec := swarm.ServiceSpec{
|
||||||
@@ -264,9 +267,6 @@ func deployServiceWorkers(image string) {
|
|||||||
Replicated: &swarm.ReplicatedService{
|
Replicated: &swarm.ReplicatedService{
|
||||||
Replicas: &replicatedJobs,
|
Replicas: &replicatedJobs,
|
||||||
},
|
},
|
||||||
ReplicatedJob: &swarm.ReplicatedJob{
|
|
||||||
MaxConcurrent: &parsedConcurrent,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Networks: []swarm.NetworkAttachmentConfig{
|
Networks: []swarm.NetworkAttachmentConfig{
|
||||||
swarm.NetworkAttachmentConfig{
|
swarm.NetworkAttachmentConfig{
|
||||||
@@ -294,6 +294,7 @@ func deployServiceWorkers(image string) {
|
|||||||
fmt.Sprintf("SHUFFLE_SWARM_CONFIG=%s", os.Getenv("SHUFFLE_SWARM_CONFIG")),
|
fmt.Sprintf("SHUFFLE_SWARM_CONFIG=%s", os.Getenv("SHUFFLE_SWARM_CONFIG")),
|
||||||
fmt.Sprintf("SHUFFLE_SWARM_NETWORK_NAME=%s", networkName),
|
fmt.Sprintf("SHUFFLE_SWARM_NETWORK_NAME=%s", networkName),
|
||||||
fmt.Sprintf("SHUFFLE_APP_REPLICAS=%d", cnt),
|
fmt.Sprintf("SHUFFLE_APP_REPLICAS=%d", cnt),
|
||||||
|
fmt.Sprintf("TZ=%s", timezone),
|
||||||
},
|
},
|
||||||
Mounts: []mount.Mount{
|
Mounts: []mount.Mount{
|
||||||
mount.Mount{
|
mount.Mount{
|
||||||
@@ -331,7 +332,7 @@ func deployServiceWorkers(image string) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Printf("[DEBUG] Successfully deployed workers with %d replica(s)", replicas)
|
log.Printf("[DEBUG] Successfully deployed workers with %d replica(s) on %d nodes", replicas, cnt)
|
||||||
//time.Sleep(time.Duration(10) * time.Second)
|
//time.Sleep(time.Duration(10) * time.Second)
|
||||||
//log.Printf("[DEBUG] Servicecreate request: %#v %#v", service, err)
|
//log.Printf("[DEBUG] Servicecreate request: %#v %#v", service, err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
NAME=shuffle-worker
|
NAME=shuffle-worker
|
||||||
VERSION=0.9.34
|
VERSION=0.9.35
|
||||||
|
|
||||||
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 .
|
||||||
|
|||||||
@@ -236,14 +236,17 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env []
|
|||||||
log.Printf("[INFO] New appname: %s, image: %s", appName, image)
|
log.Printf("[INFO] New appname: %s, image: %s", appName, image)
|
||||||
|
|
||||||
if !shuffle.ArrayContains(downloadedImages, image) {
|
if !shuffle.ArrayContains(downloadedImages, image) {
|
||||||
log.Printf("[DEBUG] Downloading image %s from backend as it's first iteration", image)
|
log.Printf("[DEBUG] Downloading image %s from backend as it's first iteration for this image on the worker.", image)
|
||||||
// FIXME: Not caring if it's ok or not. Just continuing
|
// FIXME: Not caring if it's ok or not. Just continuing
|
||||||
// This is working as intended, just designed to download an updated
|
// This is working as intended, just designed to download an updated
|
||||||
// image on every Orborus/new worker restart.
|
// image on every Orborus/new worker restart.
|
||||||
downloadedImages = append(downloadedImages, image)
|
downloadedImages = append(downloadedImages, image)
|
||||||
|
|
||||||
// Running as coroutine for eventual completeness
|
// Running as coroutine for eventual completeness
|
||||||
go downloadDockerImageBackend(&http.Client{}, image)
|
//go downloadDockerImageBackend(&http.Client{}, image)
|
||||||
|
// FIXME: With goroutines it got too much trouble of deploying with an older version
|
||||||
|
// Allowing slow startups, as long as it's eventually fast, and uses the same registry as on host.
|
||||||
|
downloadDockerImageBackend(&http.Client{}, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
exposedPort, err := findAppInfo(image, appName)
|
exposedPort, err := findAppInfo(image, appName)
|
||||||
@@ -2246,7 +2249,6 @@ func deploySwarmService(dockercli *dockerclient.Client, name, image string, depl
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Deploying app with name %s with image %s", name, image)
|
log.Printf("[DEBUG] Deploying app with name %s with image %s", name, image)
|
||||||
parsedConcurrent := uint64(50)
|
|
||||||
|
|
||||||
containerName := fmt.Sprintf(strings.Replace(name, ".", "-", -1))
|
containerName := fmt.Sprintf(strings.Replace(name, ".", "-", -1))
|
||||||
serviceSpec := swarm.ServiceSpec{
|
serviceSpec := swarm.ServiceSpec{
|
||||||
@@ -2259,9 +2261,6 @@ func deploySwarmService(dockercli *dockerclient.Client, name, image string, depl
|
|||||||
// Max total
|
// Max total
|
||||||
Replicas: &replicatedJobs,
|
Replicas: &replicatedJobs,
|
||||||
},
|
},
|
||||||
ReplicatedJob: &swarm.ReplicatedJob{
|
|
||||||
MaxConcurrent: &parsedConcurrent,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Networks: []swarm.NetworkAttachmentConfig{
|
Networks: []swarm.NetworkAttachmentConfig{
|
||||||
swarm.NetworkAttachmentConfig{
|
swarm.NetworkAttachmentConfig{
|
||||||
@@ -2317,6 +2316,13 @@ func deploySwarmService(dockercli *dockerclient.Client, name, image string, depl
|
|||||||
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
|
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Required for certain apps
|
||||||
|
if timezone == "" {
|
||||||
|
timezone = "Europe/Amsterdam"
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("TZ=%s", timezone))
|
||||||
|
|
||||||
serviceOptions := types.ServiceCreateOptions{}
|
serviceOptions := types.ServiceCreateOptions{}
|
||||||
service, err := dockercli.ServiceCreate(
|
service, err := dockercli.ServiceCreate(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
|
|||||||
Reference in New Issue
Block a user