Tons of priority management fixes - both frontend & backend
This commit is contained in:
@@ -385,170 +385,6 @@ func buildImage(tags []string, dockerfileFolder string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - very specific for webhooks. Make it easier?
|
|
||||||
func stopWebhook(image string, identifier string) error {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
containername := fmt.Sprintf("%s-%s", image, identifier)
|
|
||||||
|
|
||||||
cli, err := client.NewEnvClient()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to create docker client")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// containers, err := cli.ContainerList(ctx, types.ContainerListOptions{
|
|
||||||
// All: true,
|
|
||||||
// })
|
|
||||||
|
|
||||||
if err := cli.ContainerStop(ctx, containername, nil); err != nil {
|
|
||||||
log.Printf("Unable to stop container %s - running removal anyway, just in case: %s", containername, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeOptions := types.ContainerRemoveOptions{
|
|
||||||
RemoveVolumes: true,
|
|
||||||
Force: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cli.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
|
||||||
log.Printf("Unable to remove container: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts a new webhook
|
|
||||||
func handleStopHookDocker(resp http.ResponseWriter, request *http.Request) {
|
|
||||||
cors := shuffle.HandleCors(resp, request)
|
|
||||||
if cors {
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fileId) != 32 {
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
hook, err := shuffle.GetHook(ctx, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed getting hook %s (stop docker): %s", fileId, err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Status: %s", hook.Status)
|
|
||||||
log.Printf("Running: %t", hook.Running)
|
|
||||||
if !hook.Running {
|
|
||||||
message := fmt.Sprintf("Error: %s isn't running", hook.Id)
|
|
||||||
log.Println(message)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hook.Status = "stopped"
|
|
||||||
hook.Running = false
|
|
||||||
hook.Actions = []shuffle.HookAction{}
|
|
||||||
err = shuffle.SetHook(ctx, *hook)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed setting hook: %s", err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
image := "webhook"
|
|
||||||
|
|
||||||
// This is here to force stop and remove the old webhook
|
|
||||||
err = stopWebhook(image, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write([]byte(`{"success": true, "message": "Stopped webhook"}`))
|
|
||||||
}
|
|
||||||
|
|
||||||
// THis is an example
|
|
||||||
// Can also be used as base data?
|
|
||||||
var webhook = `{
|
|
||||||
"id": "d6ef8912e8bd37776e654cbc14c2629c",
|
|
||||||
"info": {
|
|
||||||
"url": "http://localhost:5001",
|
|
||||||
"name": "TheHive",
|
|
||||||
"description": "Webhook for TheHive"
|
|
||||||
},
|
|
||||||
"transforms": {},
|
|
||||||
"actions": {},
|
|
||||||
"type": "webhook",
|
|
||||||
"running": false,
|
|
||||||
"status": "stopped"
|
|
||||||
}`
|
|
||||||
|
|
||||||
// Starts a new webhook
|
|
||||||
func handleDeleteHookDocker(resp http.ResponseWriter, request *http.Request) {
|
|
||||||
ctx := context.Background()
|
|
||||||
cors := shuffle.HandleCors(resp, request)
|
|
||||||
if cors {
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fileId) != 32 {
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := shuffle.DeleteKey(ctx, "hooks", fileId)
|
|
||||||
if err != nil {
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "message": "Can't delete"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
image := "webhook"
|
|
||||||
|
|
||||||
// This is here to force stop and remove the old webhook
|
|
||||||
err = stopWebhook(image, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
|
||||||
resp.Write([]byte(`{"success": false, "message": "Couldn't stop webhook"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write([]byte(`{"success": true, "message": "Deleted webhook"}`))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if an image exists
|
// Checks if an image exists
|
||||||
func imageCheckBuilder(images []string) error {
|
func imageCheckBuilder(images []string) error {
|
||||||
//log.Printf("[FIXME] ImageNames to check: %#v", images)
|
//log.Printf("[FIXME] ImageNames to check: %#v", images)
|
||||||
@@ -594,31 +430,6 @@ func imageCheckBuilder(images []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hookTest() {
|
|
||||||
var hook shuffle.Hook
|
|
||||||
err := json.Unmarshal([]byte(webhook), &hook)
|
|
||||||
log.Println(webhook)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed hook unmarshaling: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
err = shuffle.SetHook(ctx, hook)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed setting hook: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
returnHook, err := shuffle.GetHook(ctx, hook.Id)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed getting hook %s (test): %s", hook.Id, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(returnHook.Id) > 0 {
|
|
||||||
log.Printf("Success! - %s", returnHook.Id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository
|
// https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository
|
||||||
func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := shuffle.HandleCors(resp, request)
|
cors := shuffle.HandleCors(resp, request)
|
||||||
|
|||||||
+50
-45
@@ -1,100 +1,105 @@
|
|||||||
module main
|
module shuffle-shared
|
||||||
|
|
||||||
|
replace github.com/shuffle/shuffle-shared => ../../../../git/shuffle-shared
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/datastore v1.10.0
|
cloud.google.com/go/datastore v1.11.0
|
||||||
cloud.google.com/go/pubsub v1.28.0
|
cloud.google.com/go/pubsub v1.31.0
|
||||||
cloud.google.com/go/storage v1.28.1
|
cloud.google.com/go/storage v1.30.1
|
||||||
github.com/basgys/goxml2json v1.1.0
|
github.com/basgys/goxml2json v1.1.0
|
||||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
||||||
github.com/docker/docker v20.10.21+incompatible
|
github.com/docker/docker v24.0.2+incompatible
|
||||||
github.com/frikky/kin-openapi v0.42.0
|
github.com/frikky/kin-openapi v0.42.0
|
||||||
github.com/fsouza/go-dockerclient v1.9.0
|
github.com/fsouza/go-dockerclient v1.9.7
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/go-git/go-billy/v5 v5.3.1
|
github.com/go-git/go-billy/v5 v5.4.1
|
||||||
github.com/go-git/go-git/v5 v5.5.0
|
github.com/go-git/go-git/v5 v5.7.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.4.19
|
github.com/shuffle/shuffle-shared v0.4.19
|
||||||
golang.org/x/crypto v0.3.0
|
golang.org/x/crypto v0.9.0
|
||||||
google.golang.org/api v0.103.0
|
google.golang.org/api v0.125.0
|
||||||
google.golang.org/appengine v1.6.7
|
google.golang.org/appengine v1.6.7
|
||||||
google.golang.org/grpc v1.51.0
|
google.golang.org/grpc v1.55.0
|
||||||
gopkg.in/src-d/go-git.v4 v4.13.1
|
gopkg.in/src-d/go-git.v4 v4.13.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.105.0 // indirect
|
cloud.google.com/go v0.110.2 // indirect
|
||||||
cloud.google.com/go/compute v1.13.0 // indirect
|
cloud.google.com/go/compute v1.19.3 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
cloud.google.com/go/iam v0.7.0 // indirect
|
cloud.google.com/go/iam v1.0.1 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/Microsoft/hcsshim v0.9.3 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect
|
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
|
||||||
github.com/adrg/strutil v0.2.3 // indirect
|
github.com/adrg/strutil v0.2.3 // indirect
|
||||||
github.com/algolia/algoliasearch-client-go/v3 v3.18.1 // indirect
|
github.com/algolia/algoliasearch-client-go/v3 v3.18.1 // indirect
|
||||||
|
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 // indirect
|
||||||
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013 // indirect
|
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013 // indirect
|
||||||
github.com/cloudflare/circl v1.1.0 // indirect
|
github.com/cloudflare/circl v1.3.3 // indirect
|
||||||
github.com/containerd/cgroups v1.0.3 // indirect
|
github.com/containerd/containerd v1.6.18 // indirect
|
||||||
github.com/containerd/containerd v1.6.6 // indirect
|
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/frikky/go-elasticsearch/v8 v8.13.1 // indirect
|
github.com/frikky/go-elasticsearch/v8 v8.13.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.0 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/swag v0.19.5 // indirect
|
github.com/go-openapi/swag v0.19.5 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/go-github/v28 v28.1.1 // indirect
|
github.com/google/go-github/v28 v28.1.1 // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.0.0 // indirect
|
||||||
|
github.com/google/s2a-go v0.1.4 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.10.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.13 // indirect
|
github.com/imdario/mergo v0.3.15 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.0 // indirect
|
github.com/klauspost/compress v1.11.13 // indirect
|
||||||
github.com/moby/sys/mount v0.3.3 // indirect
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
|
||||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
github.com/moby/patternmatcher v0.5.0 // indirect
|
||||||
|
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
||||||
github.com/opencontainers/runc v1.1.2 // indirect
|
github.com/opencontainers/runc v1.1.5 // indirect
|
||||||
|
github.com/opensearch-project/opensearch-go v1.1.0 // indirect
|
||||||
|
github.com/opensearch-project/opensearch-go/v2 v2.3.0 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pjbgf/sha1cd v0.2.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sergi/go-diff v1.1.0 // indirect
|
github.com/sergi/go-diff v1.1.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
github.com/skeema/knownhosts v1.1.1 // indirect
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||||
github.com/src-d/gcfg v1.4.0 // indirect
|
github.com/src-d/gcfg v1.4.0 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.2 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/net v0.2.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
golang.org/x/oauth2 v0.8.0 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.2.0 // indirect
|
||||||
golang.org/x/sys v0.2.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
|
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ import (
|
|||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
"google.golang.org/appengine/mail"
|
"google.golang.org/appengine/mail"
|
||||||
|
|
||||||
//"github.com/elastic/go-elasticsearch/v7"
|
|
||||||
//"github.com/elastic/go-elasticsearch/v8/esapi"
|
|
||||||
|
|
||||||
"github.com/frikky/kin-openapi/openapi2"
|
"github.com/frikky/kin-openapi/openapi2"
|
||||||
"github.com/frikky/kin-openapi/openapi2conv"
|
"github.com/frikky/kin-openapi/openapi2conv"
|
||||||
"github.com/frikky/kin-openapi/openapi3"
|
"github.com/frikky/kin-openapi/openapi3"
|
||||||
@@ -3908,8 +3905,8 @@ func runInitEs(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(os.Getenv("SHUFFLE_OPENSEARCH_URL"), "https") {
|
if strings.Contains(os.Getenv("SHUFFLE_OPENSEARCH_URL"), "https") {
|
||||||
log.Printf("[INFO] Waiting 10 seconds during init to make sure the opensearch instance is up and running with security features properly")
|
log.Printf("[INFO] Waiting during init to make sure the opensearch instance is up and running with security features properly")
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = setUsers
|
_ = setUsers
|
||||||
@@ -6055,7 +6052,9 @@ func initHandlers() {
|
|||||||
r.HandleFunc("/api/v1/orgs/{orgId}/list_cache", shuffle.HandleListCacheKeys).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/orgs/{orgId}/list_cache", shuffle.HandleListCacheKeys).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/orgs/{orgId}/get_cache", shuffle.HandleGetCacheKey).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/orgs/{orgId}/get_cache", shuffle.HandleGetCacheKey).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/orgs/{orgId}/set_cache", shuffle.HandleSetCacheKey).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/orgs/{orgId}/set_cache", shuffle.HandleSetCacheKey).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/orgs/{orgId}/cache/{cache_key}", shuffle.HandleDeleteCacheKey).Methods("DELETE", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/orgs/{orgId}/stats", shuffle.HandleGetStatistics).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/orgs/{orgId}/stats", shuffle.HandleGetStatistics).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/orgs/{orgId}/revisions", shuffle.GetWorkflowRevisions).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
// Docker orborus specific - downloads an image
|
// Docker orborus specific - downloads an image
|
||||||
r.HandleFunc("/api/v1/get_docker_image", getDockerImage).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/get_docker_image", getDockerImage).Methods("POST", "OPTIONS")
|
||||||
|
|||||||
+87
-68
@@ -165,7 +165,7 @@ func handleGetWorkflowqueueConfirm(resp http.ResponseWriter, request *http.Reque
|
|||||||
executionRequests, err := shuffle.GetWorkflowQueue(ctx, id, 100)
|
executionRequests, err := shuffle.GetWorkflowQueue(ctx, id, 100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] (1) Failed reading body for workflowqueue: %s", err)
|
log.Printf("[WARNING] (1) Failed reading body for workflowqueue: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(500)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Entity parsing error - confirm"}`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Entity parsing error - confirm"}`)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -179,8 +179,8 @@ func handleGetWorkflowqueueConfirm(resp http.ResponseWriter, request *http.Reque
|
|||||||
|
|
||||||
body, err := ioutil.ReadAll(request.Body)
|
body, err := ioutil.ReadAll(request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Failed reading body for stream result queue")
|
log.Println("[WARNING] Failed reading body for stream result queue")
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(500)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -190,16 +190,16 @@ func handleGetWorkflowqueueConfirm(resp http.ResponseWriter, request *http.Reque
|
|||||||
var removeExecutionRequests shuffle.ExecutionRequestWrapper
|
var removeExecutionRequests shuffle.ExecutionRequestWrapper
|
||||||
err = json.Unmarshal(body, &removeExecutionRequests)
|
err = json.Unmarshal(body, &removeExecutionRequests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed executionrequest in queue unmarshaling: %s", err)
|
log.Printf("[WARNING] Failed executionrequest in queue unmarshaling: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(400)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(removeExecutionRequests.Data) == 0 {
|
if len(removeExecutionRequests.Data) == 0 {
|
||||||
log.Printf("No requests to fix remove from DB")
|
log.Printf("[WARNING] No requests to fix remove from DB")
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Some removal error"}`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Queue removal error"}`)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,7 +636,6 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//log.Printf("Actionresult unmarshal: %s", string(body))
|
//log.Printf("Actionresult unmarshal: %s", string(body))
|
||||||
log.Printf("[DEBUG] Got workflow result from %s of length %d.", request.RemoteAddr, len(body))
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err = shuffle.ValidateNewWorkerExecution(ctx, body)
|
err = shuffle.ValidateNewWorkerExecution(ctx, body)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -647,6 +646,8 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
log.Printf("[DEBUG] Handling other execution variant (subflow?): %s", err)
|
log.Printf("[DEBUG] Handling other execution variant (subflow?): %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Got workflow result from %s of length %d.", request.RemoteAddr, len(body))
|
||||||
|
|
||||||
var actionResult shuffle.ActionResult
|
var actionResult shuffle.ActionResult
|
||||||
err = json.Unmarshal(body, &actionResult)
|
err = json.Unmarshal(body, &actionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -698,60 +699,63 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if actionResult.Status == "WAITING" && actionResult.Action.AppName == "User Input" {
|
/*
|
||||||
log.Printf("[INFO] SHOULD WAIT A BIT AND RUN CLOUD STUFF WITH USER INPUT! WAITING!")
|
// Removed as UserInput is now handled as an app
|
||||||
|
if actionResult.Status == "WAITING" && actionResult.Action.AppName == "User Input" {
|
||||||
|
log.Printf("[INFO] SHOULD WAIT A BIT AND RUN USER INPUT! WAITING!")
|
||||||
|
|
||||||
var trigger shuffle.Trigger
|
var trigger shuffle.Trigger
|
||||||
err = json.Unmarshal([]byte(actionResult.Result), &trigger)
|
err = json.Unmarshal([]byte(actionResult.Result), &trigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed unmarshaling actionresult for user input: %s", err)
|
log.Printf("[WARNING] Failed unmarshaling actionresult for user input: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false}`))
|
resp.Write([]byte(`{"success": false}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
orgId := workflowExecution.ExecutionOrg
|
orgId := workflowExecution.ExecutionOrg
|
||||||
if len(workflowExecution.OrgId) == 0 && len(workflowExecution.Workflow.OrgId) > 0 {
|
if len(workflowExecution.OrgId) == 0 && len(workflowExecution.Workflow.OrgId) > 0 {
|
||||||
orgId = workflowExecution.Workflow.OrgId
|
orgId = workflowExecution.Workflow.OrgId
|
||||||
}
|
}
|
||||||
|
|
||||||
err := handleUserInput(trigger, orgId, workflowExecution.Workflow.ID, workflowExecution.ExecutionId)
|
err := handleUserInput(trigger, orgId, workflowExecution.Workflow.ID, workflowExecution.ExecutionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed userinput handler: %s", err)
|
log.Printf("[WARNING] Failed userinput handler: %s", err)
|
||||||
|
|
||||||
actionResult.Result = fmt.Sprintf(`{"success": False, "reason": "%s"}`, err)
|
actionResult.Result = fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)
|
||||||
|
|
||||||
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
||||||
workflowExecution.Status = "ABORTED"
|
workflowExecution.Status = "ABORTED"
|
||||||
err = shuffle.SetWorkflowExecution(ctx, *workflowExecution, true)
|
err = shuffle.SetWorkflowExecution(ctx, *workflowExecution, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed to set execution during wait: %s", err)
|
log.Printf("[WARNING] Failed to set execution during wait: %s", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[INFO] Successfully set the execution %s to waiting.", workflowExecution.ExecutionId)
|
log.Printf("[INFO] Successfully set the execution %s to waiting.", workflowExecution.ExecutionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error: %s"}`, err)))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
log.Printf("[INFO] Successful userinput handler")
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "CLOUD IS DONE"}`)))
|
||||||
|
|
||||||
|
actionResult.Result = `{"success": True, "reason": "Waiting for user feedback based on configuration"}`
|
||||||
|
|
||||||
|
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
||||||
|
workflowExecution.Status = actionResult.Status
|
||||||
|
err = shuffle.SetWorkflowExecution(ctx, *workflowExecution, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[WARNING] Failed setting userinput: %s", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Successfully set the execution to waiting.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error: %s"}`, err)))
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
log.Printf("[INFO] Successful userinput handler")
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "CLOUD IS DONE"}`)))
|
|
||||||
|
|
||||||
actionResult.Result = `{"success": True, "reason": "Waiting for user feedback based on configuration"}`
|
|
||||||
|
|
||||||
workflowExecution.Results = append(workflowExecution.Results, actionResult)
|
|
||||||
workflowExecution.Status = actionResult.Status
|
|
||||||
err = shuffle.SetWorkflowExecution(ctx, *workflowExecution, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARNING] Failed setting userinput: %s", err)
|
|
||||||
} else {
|
|
||||||
log.Printf("[DEBUG] Successfully set the execution to waiting.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
runWorkflowExecutionTransaction(ctx, 0, workflowExecution.ExecutionId, actionResult, resp)
|
runWorkflowExecutionTransaction(ctx, 0, workflowExecution.ExecutionId, actionResult, resp)
|
||||||
}
|
}
|
||||||
@@ -1049,14 +1053,16 @@ func handleExecution(id string, workflow shuffle.Workflow, request *http.Request
|
|||||||
workflow = *tmpworkflow
|
workflow = *tmpworkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(workflow.ExecutingOrg.Id) == 0 {
|
/*
|
||||||
if len(orgId) > 0 {
|
if len(workflow.ExecutingOrg.Id) == 0 {
|
||||||
workflow.ExecutingOrg.Id = orgId
|
if len(orgId) > 0 {
|
||||||
} else {
|
workflow.ExecutingOrg.Id = orgId
|
||||||
log.Printf("[INFO] Stopped execution because there is no executing org for workflow %s", workflow.ID)
|
} else {
|
||||||
return shuffle.WorkflowExecution{}, fmt.Sprintf("Workflow has no executing org defined"), errors.New("Workflow has no executing org defined")
|
log.Printf("[INFO] Stopped execution because there is no executing org for workflow %s", workflow.ID)
|
||||||
|
return shuffle.WorkflowExecution{}, fmt.Sprintf("Workflow has no executing org defined"), errors.New("Workflow has no executing org defined")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
|
|
||||||
if len(workflow.Actions) == 0 {
|
if len(workflow.Actions) == 0 {
|
||||||
workflow.Actions = []shuffle.Action{}
|
workflow.Actions = []shuffle.Action{}
|
||||||
@@ -1100,8 +1106,13 @@ func handleExecution(id string, workflow shuffle.Workflow, request *http.Request
|
|||||||
|
|
||||||
workflowExecution, execInfo, _, err := shuffle.PrepareWorkflowExecution(ctx, workflow, request, 10)
|
workflowExecution, execInfo, _, err := shuffle.PrepareWorkflowExecution(ctx, workflow, request, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed in prepareExecution for execution Id '%s': %s", workflowExecution.ExecutionId, err)
|
if strings.Contains(fmt.Sprintf("%s", err), "User Input") {
|
||||||
return workflowExecution, fmt.Sprintf("Failed preparration: %s", err), err
|
// Special for user input callbacks
|
||||||
|
return workflowExecution, fmt.Sprintf("%s", err), nil
|
||||||
|
} else {
|
||||||
|
log.Printf("[WARNING] Failed in prepareExecution: %s", err)
|
||||||
|
return shuffle.WorkflowExecution{}, fmt.Sprintf("Failed starting workflow: %s", err), err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = imageCheckBuilder(execInfo.ImageNames)
|
err = imageCheckBuilder(execInfo.ImageNames)
|
||||||
@@ -1293,7 +1304,8 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//memcacheName := fmt.Sprintf("%s_%s", user.Username, fileId)
|
log.Printf("[INFO] Inside execute workflow for ID %s", fileId)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
workflow, err := shuffle.GetWorkflow(ctx, fileId)
|
workflow, err := shuffle.GetWorkflow(ctx, fileId)
|
||||||
if err != nil && workflow.ID == "" {
|
if err != nil && workflow.ID == "" {
|
||||||
@@ -1310,6 +1322,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
// 1. Parent workflow contains this workflow ID in the source trigger?
|
// 1. Parent workflow contains this workflow ID in the source trigger?
|
||||||
// 2. Parent workflow's owner is same org?
|
// 2. Parent workflow's owner is same org?
|
||||||
// 3. Parent execution auth is correct
|
// 3. Parent execution auth is correct
|
||||||
|
log.Printf("[INFO] Inside execute workflow access validation!")
|
||||||
|
|
||||||
executionAuthValid, newOrgId = shuffle.RunExecuteAccessValidation(request, workflow)
|
executionAuthValid, newOrgId = shuffle.RunExecuteAccessValidation(request, workflow)
|
||||||
if !executionAuthValid {
|
if !executionAuthValid {
|
||||||
@@ -1344,6 +1357,12 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
workflow.ExecutingOrg = user.ActiveOrg
|
workflow.ExecutingOrg = user.ActiveOrg
|
||||||
workflowExecution, executionResp, err := handleExecution(fileId, *workflow, request, user.ActiveOrg.Id)
|
workflowExecution, executionResp, err := handleExecution(fileId, *workflow, request, user.ActiveOrg.Id)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if strings.Contains(executionResp, "User Input:") {
|
||||||
|
resp.WriteHeader(400)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, executionResp)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "execution_id": "%s", "authorization": "%s"}`, workflowExecution.ExecutionId, workflowExecution.Authorization)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": true, "execution_id": "%s", "authorization": "%s"}`, workflowExecution.ExecutionId, workflowExecution.Authorization)))
|
||||||
return
|
return
|
||||||
@@ -2691,7 +2710,7 @@ func handleUserInput(trigger shuffle.Trigger, organizationId string, workflowId
|
|||||||
|
|
||||||
if len(triggerType) == 0 {
|
if len(triggerType) == 0 {
|
||||||
log.Printf("[WARNING] No type specified for user input node")
|
log.Printf("[WARNING] No type specified for user input node")
|
||||||
return errors.New("No type specified for user input node")
|
//return errors.New("No type specified for user input node")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This is not the right time to send them, BUT it's well served for testing. Save -> send email / sms
|
// FIXME: This is not the right time to send them, BUT it's well served for testing. Save -> send email / sms
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ services:
|
|||||||
container_name: shuffle-opensearch
|
container_name: shuffle-opensearch
|
||||||
environment:
|
environment:
|
||||||
- bootstrap.memory_lock=true
|
- bootstrap.memory_lock=true
|
||||||
- "OPENSEARCH_JAVA_OPTS=-Xms2048m -Xmx2048m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
|
- "OPENSEARCH_JAVA_OPTS=-Xms1024m -Xmx1024m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
|
||||||
- cluster.initial_master_nodes=shuffle-opensearch
|
- cluster.initial_master_nodes=shuffle-opensearch
|
||||||
- cluster.routing.allocation.disk.threshold_enabled=false
|
- cluster.routing.allocation.disk.threshold_enabled=false
|
||||||
- cluster.name=shuffle-cluster
|
- cluster.name=shuffle-cluster
|
||||||
|
|||||||
@@ -503,6 +503,7 @@ const App = (message, props) => {
|
|||||||
path="/workflows"
|
path="/workflows"
|
||||||
element={
|
element={
|
||||||
<Workflows
|
<Workflows
|
||||||
|
checkLogin={checkLogin}
|
||||||
cookies={cookies}
|
cookies={cookies}
|
||||||
removeCookie={removeCookie}
|
removeCookie={removeCookie}
|
||||||
isLoaded={isLoaded}
|
isLoaded={isLoaded}
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ const AppGrid = props => {
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
<span style={{position: "absolute", display: "flex", textAlign: "right", float: "right", right: 0, bottom: 120, }}>
|
<span style={{position: "absolute", display: "flex", textAlign: "right", float: "right", right: 0, bottom: isMobile?"":120, }}>
|
||||||
<Typography variant="body2" color="textSecondary" style={{}}>
|
<Typography variant="body2" color="textSecondary" style={{}}>
|
||||||
Search by
|
Search by
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -39,8 +39,9 @@ const AppSearchPopout = (props) => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <Paper style={{width: 275, maxHeight: 400, zIndex: 100000, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, }}>
|
||||||
return (
|
return (
|
||||||
<Paper style={{width: 275, maxHeight: 400, zIndex: 12500, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, overflow: "hidden", }}>
|
<Paper style={{minWidth: 275, width: 275, minHeight: 400, maxHeight: 400, zIndex: 100000, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, }}>
|
||||||
{paperTitle !== undefined && paperTitle.length > 0 ?
|
{paperTitle !== undefined && paperTitle.length > 0 ?
|
||||||
<span>
|
<span>
|
||||||
<Typography variant="h6" style={{textAlign: "center"}}>
|
<Typography variant="h6" style={{textAlign: "center"}}>
|
||||||
|
|||||||
@@ -79,6 +79,17 @@ const ConfigureWorkflow = (props) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ONLY when component is being unloaded, run stop() function
|
||||||
|
// This is to prevent the interval from running when the component is not being used
|
||||||
|
|
||||||
|
/*
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
*/
|
||||||
|
|
||||||
// Where is this from?
|
// Where is this from?
|
||||||
if (workflow === undefined || workflow === null) {
|
if (workflow === undefined || workflow === null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -2729,10 +2729,7 @@ const ParsedAction = (props) => {
|
|||||||
// Look for the ID
|
// Look for the ID
|
||||||
const found = false;
|
const found = false;
|
||||||
for (let [key,keyval] in Object.entries(workflowExecutions)) {
|
for (let [key,keyval] in Object.entries(workflowExecutions)) {
|
||||||
if (
|
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
|
||||||
workflowExecutions[key].results === undefined ||
|
|
||||||
workflowExecutions[key].results === null
|
|
||||||
) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import Priority from "../components/Priority.jsx";
|
|||||||
import { useAlert } from "react-alert";
|
import { useAlert } from "react-alert";
|
||||||
|
|
||||||
const Priorities = (props) => {
|
const Priorities = (props) => {
|
||||||
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, checkLogin, } = props;
|
const { globalUrl, userdata, serverside, billingInfo, stripeKey, checkLogin, } = props;
|
||||||
const [showDismissed, setShowDismissed] = React.useState(false);
|
const [showDismissed, setShowDismissed] = React.useState(false);
|
||||||
const [showRead, setShowRead] = React.useState(false);
|
const [showRead, setShowRead] = React.useState(false);
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ const Priorities = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{maxWidth: 1000, }}>
|
<div style={{maxWidth: 1000, }}>
|
||||||
<h2 style={{ display: "inline" }}>Priorities</h2>
|
<h2 style={{ display: "inline" }}>Suggestions</h2>
|
||||||
<span style={{ marginLeft: 25 }}>
|
<span style={{ marginLeft: 25 }}>
|
||||||
Priorities identified by Shuffle to help you discover ways to protect yourself.
|
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. These range from simple configurations in Shuffle to Usecases you may have missed.
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
@@ -46,7 +46,7 @@ const Priorities = (props) => {
|
|||||||
/> Show dismissed
|
/> Show dismissed
|
||||||
{userdata.priorities === null || userdata.priorities === undefined || userdata.priorities.length === 0 ?
|
{userdata.priorities === null || userdata.priorities === undefined || userdata.priorities.length === 0 ?
|
||||||
<Typography variant="h4">
|
<Typography variant="h4">
|
||||||
No Priorities found
|
No Suggestions found
|
||||||
</Typography>
|
</Typography>
|
||||||
:
|
:
|
||||||
userdata.priorities.map((priority, index) => {
|
userdata.priorities.map((priority, index) => {
|
||||||
@@ -67,7 +67,7 @@ const Priorities = (props) => {
|
|||||||
<Divider style={{marginTop: 50, marginBottom: 50, }} />
|
<Divider style={{marginTop: 50, marginBottom: 50, }} />
|
||||||
<h2 style={{ display: "inline" }}>Notifications</h2>
|
<h2 style={{ display: "inline" }}>Notifications</h2>
|
||||||
<span style={{ marginLeft: 25 }}>
|
<span style={{ marginLeft: 25 }}>
|
||||||
Notifications help you find potential problems with your workflows and apps
|
Notifications help you find potential problems with your workflows and apps.
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
|
||||||
|
// import magic wand icon from material ui icons
|
||||||
|
import {
|
||||||
|
AutoFixHigh as AutoFixHighIcon,
|
||||||
|
ArrowForward as ArrowForwardIcon,
|
||||||
|
} from '@mui/icons-material';
|
||||||
import { useAlert } from "react-alert";
|
import { useAlert } from "react-alert";
|
||||||
|
|
||||||
const Priority = (props) => {
|
const Priority = (props) => {
|
||||||
@@ -60,18 +65,51 @@ const Priority = (props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{border: priority.active === false ? "1px solid #000000" : priority.severity === 1 ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette.borderRadius, marginTop: 10, marginBottom: 10, padding: 15, textAlign: "center", height: 70, textAlign: "left", backgroundColor: theme.palette.surfaceColor, display: "flex", }}>
|
<div style={{border: priority.active === false ? "1px solid #000000" : priority.severity === 1 ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette.borderRadius, marginTop: 10, marginBottom: 10, padding: 15, textAlign: "center", height: 70, textAlign: "left", backgroundColor: theme.palette.surfaceColor, display: "flex", }}>
|
||||||
<div style={{flex: 2, overflow: "hidden",}}>
|
<div style={{flex: 2, overflow: "hidden",}}>
|
||||||
<Typography variant="body1" >
|
<span style={{display: "flex", }}>
|
||||||
{priority.name}
|
{priority.type === "usecase" || priority.type == "apps" ? <AutoFixHighIcon style={{height: 19, width: 19, marginLeft: 3, marginRight: 10, }}/> : null}
|
||||||
</Typography>
|
<Typography variant="body1" >
|
||||||
<Typography variant="body2" color="textSecondary">
|
{priority.name}
|
||||||
{priority.description}
|
</Typography>
|
||||||
</Typography>
|
</span>
|
||||||
|
{priority.type === "usecase" && priority.description.includes("&") ?
|
||||||
|
<span style={{display: "flex", marginTop: 10, }}>
|
||||||
|
<img src={priority.description.split("&")[1]} alt={priority.name} style={{height: 30, width: 30, marginRight: 5, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
|
||||||
|
<Typography variant="body2" color="textSecondary" style={{marginTop: 3, }}>
|
||||||
|
{priority.description.split("&")[0]}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{priority.description.split("&").length > 3 ?
|
||||||
|
<span style={{display: "flex", }}>
|
||||||
|
<ArrowForwardIcon style={{marginLeft: 15, marginRight: 15, }}/>
|
||||||
|
<img src={priority.description.split("&")[3]} alt={priority.name+"2"} style={{height: 30, width: 30, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
|
||||||
|
<Typography variant="body2" color="textSecondary" style={{marginTop: 3}}>
|
||||||
|
{priority.description.split("&")[2]}
|
||||||
|
</Typography>
|
||||||
|
</span>
|
||||||
|
: null}
|
||||||
|
|
||||||
|
</span>
|
||||||
|
:
|
||||||
|
<Typography variant="body2" color="textSecondary">
|
||||||
|
{priority.description}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
|
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
|
||||||
<Button style={{height: 50, borderRadius: 25, marginTop: 8, width: 200, marginRight: 10, color: priority.active === false ? "white" : "black", backgroundColor: priority.active === false ? theme.palette.inputColor : "white", }} variant="contained" color="secondary" onClick={() => {navigate(priority.url)}}>
|
<Button style={{height: 50, borderRadius: 25, marginTop: 8, width: 175, marginRight: 10, color: priority.active === false ? "white" : "black", backgroundColor: priority.active === false ? theme.palette.inputColor : "white", }} variant="contained" color="secondary" onClick={() => {
|
||||||
|
/*
|
||||||
|
ReactGA.event({
|
||||||
|
category: "",
|
||||||
|
action: `partner_${partner.name}_click`,
|
||||||
|
label: "",
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
navigate(priority.url)
|
||||||
|
}}>
|
||||||
explore
|
explore
|
||||||
</Button>
|
</Button>
|
||||||
{priority.active === true ?
|
{priority.active === true ?
|
||||||
|
|||||||
@@ -693,52 +693,8 @@ const WelcomeForm = (props) => {
|
|||||||
<Typography variant="body1" style={{marginTop: 15, marginBottom: 0, maxWidth: 500, margin: "auto", marginBottom: 15, }} color="textSecondary">
|
<Typography variant="body1" style={{marginTop: 15, marginBottom: 0, maxWidth: 500, margin: "auto", marginBottom: 15, }} color="textSecondary">
|
||||||
These are some of our Workflow templates, used to start new Workflows. Use the right and left buttons to find <a href="/usecases" target="_blank" rel="norefferer" style={{color: "#f86a3e", textDecoration: "none", }}>new Usecases</a>, and click the orange button to build it.
|
These are some of our Workflow templates, used to start new Workflows. Use the right and left buttons to find <a href="/usecases" target="_blank" rel="norefferer" style={{color: "#f86a3e", textDecoration: "none", }}>new Usecases</a>, and click the orange button to build it.
|
||||||
</Typography>
|
</Typography>
|
||||||
{/*<Divider />*/}
|
|
||||||
{/*
|
|
||||||
<div style={{width: 475, margin: "auto",}}>
|
|
||||||
{usecaseButtons.map((usecase, index) => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Chip
|
|
||||||
key={usecase.name}
|
|
||||||
style={{
|
|
||||||
backgroundColor: defaultSearch === usecase.name ? usecase.color : theme.palette.surfaceColor,
|
|
||||||
marginRight: 10,
|
|
||||||
paddingLeft: 5,
|
|
||||||
paddingRight: 5,
|
|
||||||
height: 28,
|
|
||||||
cursor: "pointer",
|
|
||||||
border: `1px solid ${usecase.color}`,
|
|
||||||
color: "white",
|
|
||||||
borderRadius: theme.palette.borderRadius,
|
|
||||||
}}
|
|
||||||
label={`${index+1}. ${usecase.name}`}
|
|
||||||
onClick={() => {
|
|
||||||
console.log("Clicked: ", usecase.name)
|
|
||||||
if (defaultSearch === usecase.name) {
|
|
||||||
//setSelectedUsecaseCategory("")
|
|
||||||
} else {
|
|
||||||
handleSetSearch(usecase.name, usecase.usecase)
|
|
||||||
}
|
|
||||||
//addFilter(usecase.name.slice(3,usecase.name.length))
|
|
||||||
}}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
*/}
|
|
||||||
<div style={{marginTop: 0, }}>
|
<div style={{marginTop: 0, }}>
|
||||||
{/*
|
|
||||||
<UsecaseSearch
|
|
||||||
globalUrl={globalUrl}
|
|
||||||
defaultSearch={defaultSearch}
|
|
||||||
appFramework={appFramework}
|
|
||||||
apps={apps}
|
|
||||||
/>
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<div className="thumbs" style={{display: "flex"}}>
|
<div className="thumbs" style={{display: "flex"}}>
|
||||||
<Tooltip title={"Previous usecase"}>
|
<Tooltip title={"Previous usecase"}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|||||||
+214
-33
@@ -177,7 +177,7 @@ const Admin = (props) => {
|
|||||||
const [secret2FA, setSecret2FA] = React.useState("");
|
const [secret2FA, setSecret2FA] = React.useState("");
|
||||||
const [show2faSetup, setShow2faSetup] = useState(false);
|
const [show2faSetup, setShow2faSetup] = useState(false);
|
||||||
|
|
||||||
const [adminTab, setAdminTab] = React.useState(1);
|
const [adminTab, setAdminTab] = React.useState(2);
|
||||||
const [showApiKey, setShowApiKey] = useState(false);
|
const [showApiKey, setShowApiKey] = useState(false);
|
||||||
const [billingInfo, setBillingInfo] = React.useState({});
|
const [billingInfo, setBillingInfo] = React.useState({});
|
||||||
const [selectedStatus, setSelectedStatus] = React.useState([]);
|
const [selectedStatus, setSelectedStatus] = React.useState([]);
|
||||||
@@ -189,8 +189,6 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
}, [isDropzone]);
|
}, [isDropzone]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 get2faCode = (userId) => {
|
const get2faCode = (userId) => {
|
||||||
@@ -299,6 +297,165 @@ const Admin = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Basically just a simple way to get a generated email
|
||||||
|
// This also may help understand how to communicate with users
|
||||||
|
// both inside and outside Shuffle
|
||||||
|
// This could also be generated on the backend
|
||||||
|
const mailsendingButton = (org) => {
|
||||||
|
if (org === undefined || org === null) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 mail based on users that have only apps
|
||||||
|
// Another based on those doing workflows
|
||||||
|
// Another based on those trying usecases(?) or templates
|
||||||
|
//
|
||||||
|
// Start based on edr, siem & ticketing
|
||||||
|
// Talk about enrichment?
|
||||||
|
// Check suggested usecases
|
||||||
|
// Check suggested workflows
|
||||||
|
var your_apps = "- Connecting "
|
||||||
|
|
||||||
|
var subject_add = 0
|
||||||
|
var subject = "Want to automate "
|
||||||
|
|
||||||
|
if (org.security_framework !== undefined && org.security_framework !== null) {
|
||||||
|
if (org.security_framework.cases.name !== undefined && org.security_framework.cases.name !== null && org.security_framework.cases.name !== "") {
|
||||||
|
your_apps += org.security_framework.cases.name.replace("_", " ", -1) + ", "
|
||||||
|
|
||||||
|
if (subject_add < 2) {
|
||||||
|
if (subject_add === 1) {
|
||||||
|
subject += " & "
|
||||||
|
}
|
||||||
|
|
||||||
|
subject_add += 1
|
||||||
|
subject += org.security_framework.cases.name.replace("_", " ", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.security_framework.siem.name !== undefined && org.security_framework.siem.name !== null && org.security_framework.siem.name !== "") {
|
||||||
|
your_apps += org.security_framework.siem.name.replace("_", " ", -1) + ", "
|
||||||
|
|
||||||
|
if (subject_add < 2) {
|
||||||
|
if (subject_add === 1) {
|
||||||
|
subject += " & "
|
||||||
|
}
|
||||||
|
|
||||||
|
subject_add += 1
|
||||||
|
subject += org.security_framework.siem.name.replace("_", " ", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.security_framework.communication.name !== undefined && org.security_framework.communication.name !== null && org.security_framework.communication.name !== "") {
|
||||||
|
your_apps += org.security_framework.communication.name.replace("_", " ", -1) + ", "
|
||||||
|
|
||||||
|
if (subject_add < 2) {
|
||||||
|
if (subject_add === 1) {
|
||||||
|
subject += " & "
|
||||||
|
}
|
||||||
|
|
||||||
|
subject_add += 1
|
||||||
|
subject += org.security_framework.communication.name.replace("_", " ", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.security_framework.edr.name !== undefined && org.security_framework.edr.name !== null && org.security_framework.edr.name !== "") {
|
||||||
|
your_apps += org.security_framework.edr.name.replace("_", " ", -1) + ", "
|
||||||
|
|
||||||
|
if (subject_add < 2) {
|
||||||
|
if (subject_add === 1) {
|
||||||
|
subject += " & "
|
||||||
|
}
|
||||||
|
|
||||||
|
subject_add += 1
|
||||||
|
subject += org.security_framework.edr.name.replace("_", " ", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.security_framework.intel.name !== undefined && org.security_framework.intel.name !== null && org.security_framework.intel.name !== "") {
|
||||||
|
your_apps += org.security_framework.intel.name.replace("_", " ", -1) + ", "
|
||||||
|
|
||||||
|
if (subject_add < 2) {
|
||||||
|
if (subject_add === 1) {
|
||||||
|
subject += " & "
|
||||||
|
}
|
||||||
|
|
||||||
|
subject_add += 1
|
||||||
|
subject += org.security_framework.intel.name.replace("_", " ", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Remove comma
|
||||||
|
subject += "?"
|
||||||
|
your_apps = your_apps.substring(0, your_apps.length - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add usecases they may not have tried (from recommendations): org.priorities where item type is usecase
|
||||||
|
var usecases = "- Building usecases like "
|
||||||
|
const active_usecase = org.priorities.filter((item) => item.type === "usecase" && item.active === true)
|
||||||
|
if (active_usecase.length > 0) {
|
||||||
|
for (var i = 0; i < active_usecase.length; i++) {
|
||||||
|
if (active_usecase[i].name.includes("Suggested Usecase: ")) {
|
||||||
|
usecases += active_usecase[i].name.replace("Suggested Usecase: ", "", -1) + ", "
|
||||||
|
} else {
|
||||||
|
usecases += active_usecase[i].name + ", "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usecases = usecases.substring(0, usecases.length - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (your_apps.length <= 15) {
|
||||||
|
your_apps = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usecases.length <= 30) {
|
||||||
|
usecases = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var workflow_amount = "a few"
|
||||||
|
var admins = ""
|
||||||
|
|
||||||
|
// Loop users
|
||||||
|
for (var i = 0; i < users.length; i++) {
|
||||||
|
if (users[i].role === "admin") {
|
||||||
|
admins += users[i].username + ","
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove last comma
|
||||||
|
admins = admins.substring(0, admins.length - 1)
|
||||||
|
|
||||||
|
if (your_apps.length > 5) {
|
||||||
|
your_apps += "%0D%0A"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usecases.length > 5) {
|
||||||
|
usecases += "%0D%0A"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get drift username from userdata.username before @ in email
|
||||||
|
const username = userdata.username.substring(0, userdata.username.indexOf("@"))
|
||||||
|
|
||||||
|
var body = `Hey,%0D%0AI saw you trying to use Shuffle, and thought we may be able to help. Right now, it looks like you have ${workflow_amount} workflows made, but I'm not sure if you're getting the most out of Shuffle.%0D%0A%0D%0AIf you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A
|
||||||
|
|
||||||
|
Some of the things we can help with:%0D%0A
|
||||||
|
${your_apps}
|
||||||
|
- Properly authenticating and custom building apps%0D%0A
|
||||||
|
${usecases}
|
||||||
|
- Creating special usecases%0D%0A%0D%0A
|
||||||
|
|
||||||
|
Let me know if you're interested, or set up a call here: https://drift.me/${username}`
|
||||||
|
|
||||||
|
return `mailto:${admins}?subject=${subject}&body=${body}`
|
||||||
|
}
|
||||||
|
|
||||||
const deleteAuthentication = (data) => {
|
const deleteAuthentication = (data) => {
|
||||||
alert.info("Deleting auth " + data.label);
|
alert.info("Deleting auth " + data.label);
|
||||||
|
|
||||||
@@ -367,6 +524,13 @@ const Admin = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (userdata.support === true && selectedOrganization.id !== "" && selectedOrganization.id !== undefined && selectedOrganization.id !== null && selectedOrganization.id !== userdata.active_org.id) {
|
||||||
|
alert.info("Refreshing window to fix org support access")
|
||||||
|
window.location.reload()
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const handleVerify2FA = (userId, code) => {
|
const handleVerify2FA = (userId, code) => {
|
||||||
const data = {
|
const data = {
|
||||||
code: code,
|
code: code,
|
||||||
@@ -799,6 +963,10 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
if (responseJson.lead_info !== undefined && responseJson.lead_info !== null) {
|
if (responseJson.lead_info !== undefined && responseJson.lead_info !== null) {
|
||||||
var leads = []
|
var leads = []
|
||||||
|
if (responseJson.lead_info.contacted) {
|
||||||
|
leads.push("contacted")
|
||||||
|
}
|
||||||
|
|
||||||
if (responseJson.lead_info.customer) {
|
if (responseJson.lead_info.customer) {
|
||||||
leads.push("customer")
|
leads.push("customer")
|
||||||
}
|
}
|
||||||
@@ -1181,11 +1349,6 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
var localData = "";
|
var localData = "";
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// console.log('confirm', fileContent);
|
|
||||||
// }, [fileContent])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getSchedules = () => {
|
const getSchedules = () => {
|
||||||
fetch(globalUrl + "/api/v1/workflows/schedules", {
|
fetch(globalUrl + "/api/v1/workflows/schedules", {
|
||||||
@@ -1322,6 +1485,10 @@ const Admin = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUsers()
|
||||||
|
}, []);
|
||||||
|
|
||||||
const getSettings = () => {
|
const getSettings = () => {
|
||||||
fetch(globalUrl + "/api/v1/getsettings", {
|
fetch(globalUrl + "/api/v1/getsettings", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -2189,27 +2356,45 @@ const Admin = (props) => {
|
|||||||
*/}
|
*/}
|
||||||
|
|
||||||
{userdata.support === true ?
|
{userdata.support === true ?
|
||||||
<FormControl sx={{ m: 1, width: 300, }} style={{top: -10, right: 50, position: "absolute" }}>
|
<span style={{display: "flex", top: -10, right: 50, position: "absolute"}}>
|
||||||
<InputLabel id="">Status</InputLabel>
|
<a href={mailsendingButton(selectedOrganization)} target="_blank" rel="noopener noreferrer" style={{textDecoration: "none"}} disabled={selectedStatus.length !== 0}>
|
||||||
<Select
|
<Button
|
||||||
style={{minWidth: 150, maxWidth: 150, }}
|
variant="outlined"
|
||||||
labelId="multiselect-status"
|
color="primary"
|
||||||
id="multiselect-status"
|
disabled={selectedStatus.length !== 0}
|
||||||
multiple
|
style={{ minWidth: 80, maxWidth: 80, height: "100%", }}
|
||||||
value={selectedStatus}
|
onClick={() => {
|
||||||
onChange={handleStatusChange}
|
console.log("Should send mail to admins of org with context")
|
||||||
input={<OutlinedInput label="Status" />}
|
handleStatusChange({target: {value: ["contacted"]}})
|
||||||
renderValue={(selected) => selected.join(', ')}
|
|
||||||
MenuProps={MenuProps}
|
// open a mailto with subject "hello" and sender "frikky@shuffler.io"
|
||||||
>
|
}}
|
||||||
{["lead", "pov", "demo done", "customer", "student", ].map((name) => (
|
>
|
||||||
<MenuItem key={name} value={name}>
|
Sales mail
|
||||||
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
|
</Button>
|
||||||
<ListItemText primary={name} />
|
</a>
|
||||||
</MenuItem>
|
<FormControl sx={{ m: 1, width: 300, }} style={{}}>
|
||||||
))}
|
<InputLabel id="">Status</InputLabel>
|
||||||
</Select>
|
<Select
|
||||||
</FormControl>
|
style={{minWidth: 150, maxWidth: 150, }}
|
||||||
|
labelId="multiselect-status"
|
||||||
|
id="multiselect-status"
|
||||||
|
multiple
|
||||||
|
value={selectedStatus}
|
||||||
|
onChange={handleStatusChange}
|
||||||
|
input={<OutlinedInput label="Status" />}
|
||||||
|
renderValue={(selected) => selected.join(', ')}
|
||||||
|
MenuProps={MenuProps}
|
||||||
|
>
|
||||||
|
{["contacted", "lead", "pov", "demo done", "customer", "student", ].map((name) => (
|
||||||
|
<MenuItem key={name} value={name}>
|
||||||
|
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
|
||||||
|
<ListItemText primary={name} />
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -2588,10 +2773,6 @@ const Admin = (props) => {
|
|||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
adminTab={adminTab}
|
adminTab={adminTab}
|
||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
handleGetOrg={handleGetOrg}
|
|
||||||
selectedOrganization={selectedOrganization}
|
|
||||||
selectedOrganization={selectedOrganization}
|
|
||||||
setSelectedOrganization={setSelectedOrganization}
|
|
||||||
checkLogin={checkLogin}
|
checkLogin={checkLogin}
|
||||||
/>
|
/>
|
||||||
: adminTab === 3 ?
|
: adminTab === 3 ?
|
||||||
|
|||||||
@@ -11484,7 +11484,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<div style={{ flex: "1" }}>
|
<div style={{ flex: "1" }}>
|
||||||
<h3 style={{ marginBottom: "5px" }}>
|
<h3 style={{ marginBottom: "5px" }}>
|
||||||
{selectedTrigger.app_name}: {selectedTrigger.status}
|
{selectedTrigger.app_name}
|
||||||
</h3>
|
</h3>
|
||||||
<a
|
<a
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
@@ -11526,7 +11526,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
onChange={selectedTriggerChange}
|
onChange={selectedTriggerChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ marginTop: "20px" }}>
|
{/*<div style={{ marginTop: "20px" }}>
|
||||||
Environment:
|
Environment:
|
||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
@@ -11549,6 +11549,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
value={selectedTrigger.environment}
|
value={selectedTrigger.environment}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
*/}
|
||||||
<Divider
|
<Divider
|
||||||
style={{
|
style={{
|
||||||
marginTop: "20px",
|
marginTop: "20px",
|
||||||
@@ -13697,7 +13698,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
||||||
<DirectionsRunIcon style={{ marginRight: 10 }} />
|
<DirectionsRunIcon style={{ marginRight: 10 }} />
|
||||||
All Executions
|
All Workflow Runs
|
||||||
</h2>
|
</h2>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<Button
|
<Button
|
||||||
@@ -13710,7 +13711,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
<CachedIcon style={{ marginRight: 10 }} />
|
<CachedIcon style={{ marginRight: 10 }} />
|
||||||
Refresh executions
|
Refresh Runs
|
||||||
</Button>
|
</Button>
|
||||||
<Divider
|
<Divider
|
||||||
style={{
|
style={{
|
||||||
@@ -13956,7 +13957,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
|
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
|
||||||
onClick={() => { }}
|
onClick={() => { }}
|
||||||
>
|
>
|
||||||
See other Executions
|
See more runs
|
||||||
</h2>
|
</h2>
|
||||||
</span>
|
</span>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
@@ -14781,7 +14782,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
{curapp === null ? null : (
|
{curapp === null ? null : (
|
||||||
<img
|
<img
|
||||||
alt={selectedResult.action.app_name}
|
alt={selectedResult.action.app_name}
|
||||||
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult.action.app_name === "shuffle-subflow" ? triggers[4].large_image : selectedResult.action.app_name === "User Input" ? triggers[5].large_image : selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp.large_image}
|
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult.action.app_name === "shuffle-subflow" ? triggers[4].large_image : selectedResult.action.app_name === "User Input" ? triggers[5].large_image : selectedResult.action !== undefined && selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp !== undefined ? curapp.large_image : theme.palette.defaultImage}
|
||||||
style={{
|
style={{
|
||||||
marginRight: 20,
|
marginRight: 20,
|
||||||
width: imgsize,
|
width: imgsize,
|
||||||
@@ -15509,7 +15510,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
<div>
|
<div>
|
||||||
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
||||||
<div style={{ color: "white" }}>
|
<div style={{ color: "white" }}>
|
||||||
Authentication for {selectedApp.name}
|
Authentication for {selectedApp.name.replace("_", " ", -1)}
|
||||||
</div>
|
</div>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -127,6 +127,8 @@ const Search = (props) => {
|
|||||||
textColor="secondary"
|
textColor="secondary"
|
||||||
onChange={setConfig}
|
onChange={setConfig}
|
||||||
aria-label="disabled tabs example"
|
aria-label="disabled tabs example"
|
||||||
|
variant="scrollable"
|
||||||
|
scrollButtons="auto"
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
label=<span>
|
label=<span>
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ const Welcome = (props) => {
|
|||||||
const defaultImage = "/images/experienced.png"
|
const defaultImage = "/images/experienced.png"
|
||||||
const experienced_image = userdata !== undefined && userdata !== null && userdata.active_org !== undefined && userdata.active_org.image !== undefined && userdata.active_org.image !== null && userdata.active_org.image !== "" ? userdata.active_org.image : defaultImage
|
const experienced_image = userdata !== undefined && userdata !== null && userdata.active_org !== undefined && userdata.active_org.image !== undefined && userdata.active_org.image !== null && userdata.active_org.image !== "" ? userdata.active_org.image : defaultImage
|
||||||
return (
|
return (
|
||||||
<div style={{width: 1000, margin: "auto", paddingBottom: 150, minHeight: 1500, }}>
|
<div style={{width: 1000, margin: "auto", paddingBottom: 150, minHeight: 1500, marginTop: 50, }}>
|
||||||
{/*
|
{/*
|
||||||
<div style={{position: "fixed", bottom: 110, right: 110, display: "flex", }}>
|
<div style={{position: "fixed", bottom: 110, right: 110, display: "flex", }}>
|
||||||
<img src="/images/Arrow.png" style={{width: 250, height: "100%",}} />
|
<img src="/images/Arrow.png" style={{width: 250, height: "100%",}} />
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Navigate } from "react-router-dom";
|
|||||||
import SecurityFramework from '../components/SecurityFramework.jsx';
|
import SecurityFramework from '../components/SecurityFramework.jsx';
|
||||||
import EditWorkflow from "../components/EditWorkflow.jsx"
|
import EditWorkflow from "../components/EditWorkflow.jsx"
|
||||||
import { ShepherdTour, ShepherdTourContext } from 'react-shepherd'
|
import { ShepherdTour, ShepherdTourContext } from 'react-shepherd'
|
||||||
|
import Priority from "../components/Priority.jsx";
|
||||||
|
|
||||||
import { isMobile } from "react-device-detect"
|
import { isMobile } from "react-device-detect"
|
||||||
|
|
||||||
@@ -524,7 +525,7 @@ export const validateJson = (showResult) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Workflows = (props) => {
|
const Workflows = (props) => {
|
||||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
const { globalUrl, isLoggedIn, isLoaded, userdata, checkLogin } = props;
|
||||||
document.title = "Shuffle - Workflows";
|
document.title = "Shuffle - Workflows";
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
@@ -585,6 +586,7 @@ const Workflows = (props) => {
|
|||||||
const [drawerOpen, setDrawerOpen] = React.useState(false)
|
const [drawerOpen, setDrawerOpen] = React.useState(false)
|
||||||
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
|
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
|
||||||
const [gettingStartedItems, setGettingStartedItems] = React.useState([])
|
const [gettingStartedItems, setGettingStartedItems] = React.useState([])
|
||||||
|
|
||||||
const drawerWidth = drawerOpen ? 325 : 0
|
const drawerWidth = drawerOpen ? 325 : 0
|
||||||
|
|
||||||
const sidebarKey = "getting_started_sidebar"
|
const sidebarKey = "getting_started_sidebar"
|
||||||
@@ -618,7 +620,6 @@ const Workflows = (props) => {
|
|||||||
setDrawerOpen(true)
|
setDrawerOpen(true)
|
||||||
} else {
|
} else {
|
||||||
if (sidebar === "open") {
|
if (sidebar === "open") {
|
||||||
console.log("OPEN the thingy!")
|
|
||||||
setDrawerOpen(true)
|
setDrawerOpen(true)
|
||||||
} else {
|
} else {
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
@@ -1126,6 +1127,11 @@ const Workflows = (props) => {
|
|||||||
var newcategories = []
|
var newcategories = []
|
||||||
for (var key in categorydata) {
|
for (var key in categorydata) {
|
||||||
var category = categorydata[key]
|
var category = categorydata[key]
|
||||||
|
// Check if category is bool
|
||||||
|
if (typeof category === "boolean") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
category.matches = []
|
category.matches = []
|
||||||
|
|
||||||
for (var subcategorykey in category.list) {
|
for (var subcategorykey in category.list) {
|
||||||
@@ -1216,8 +1222,8 @@ const Workflows = (props) => {
|
|||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
minWidth: isMobile ? "100%" : drawerWidth > 0 ? 824 : 1024,
|
minWidth: isMobile ? "100%" : 1024,
|
||||||
maxWidth: isMobile ? "100%" : drawerWidth > 0 ? 824 : 1024,
|
maxWidth: isMobile ? "100%" : 1024,
|
||||||
margin: drawerWidth === 0 ? "auto" : `auto ${drawerWidth+100} auto auto`,
|
margin: drawerWidth === 0 ? "auto" : `auto ${drawerWidth+100} auto auto`,
|
||||||
paddingBottom: 200,
|
paddingBottom: 200,
|
||||||
};
|
};
|
||||||
@@ -1583,7 +1589,8 @@ const Workflows = (props) => {
|
|||||||
const innerColor = "rgba(255,255,255,0.3)";
|
const innerColor = "rgba(255,255,255,0.3)";
|
||||||
const setupPaperStyle = {
|
const setupPaperStyle = {
|
||||||
minHeight: paperAppStyle.minHeight,
|
minHeight: paperAppStyle.minHeight,
|
||||||
width: paperAppStyle.width,
|
maxWidth: "100%",
|
||||||
|
minWidth: paperAppStyle.width,
|
||||||
color: innerColor,
|
color: innerColor,
|
||||||
padding: paperAppStyle.padding,
|
padding: paperAppStyle.padding,
|
||||||
borderRadius: paperAppStyle.borderRadius,
|
borderRadius: paperAppStyle.borderRadius,
|
||||||
@@ -1612,7 +1619,7 @@ const Workflows = (props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip title={`New Workflow`} placement="bottom">
|
<Tooltip title={`New Workflow`} placement="bottom">
|
||||||
<span style={{ textAlign: "center", width: 300, margin: "auto" }}>
|
<span style={{ textAlign: "center", minWidth: 300, margin: "auto" }}>
|
||||||
<AddCircleIcon style={{ height: 65, width: 65 }} />
|
<AddCircleIcon style={{ height: 65, width: 65 }} />
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -3197,7 +3204,7 @@ const Workflows = (props) => {
|
|||||||
var workflowDelay = -150
|
var workflowDelay = -150
|
||||||
var appDelay = -75
|
var appDelay = -75
|
||||||
|
|
||||||
|
const foundPriority = userdata === undefined || userdata === null ? null : userdata.priorities.find(prio => prio.type === "usecase" && prio.active === true)
|
||||||
return (
|
return (
|
||||||
<div style={viewStyle}>
|
<div style={viewStyle}>
|
||||||
<div style={workflowViewStyle}>
|
<div style={workflowViewStyle}>
|
||||||
@@ -3470,9 +3477,17 @@ const Workflows = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<div style={{marginTop: 15, }}>
|
{foundPriority != null && workflows.length < 6 ?
|
||||||
|
<Priority
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
priority={foundPriority}
|
||||||
|
checkLogin={checkLogin}
|
||||||
|
/>
|
||||||
|
: null}
|
||||||
|
|
||||||
|
<div style={{marginTop: 15, marginBottom: 50, }}>
|
||||||
{view === "grid" ? (
|
{view === "grid" ? (
|
||||||
<Grid container spacing={4} style={paperAppContainer}>
|
<Grid container spacing={filteredWorkflows.length === 0 ? 12 : filteredWorkflows.length === 1 ? 6 : 4} style={paperAppContainer}>
|
||||||
<Zoom in={true} style={{ transitionDelay: `${workflowDelay}ms` }}>
|
<Zoom in={true} style={{ transitionDelay: `${workflowDelay}ms` }}>
|
||||||
<NewWorkflowPaper />
|
<NewWorkflowPaper />
|
||||||
</Zoom>
|
</Zoom>
|
||||||
@@ -3507,6 +3522,15 @@ const Workflows = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{foundPriority != null && filteredWorkflows.length > 6 ?
|
||||||
|
<Priority
|
||||||
|
style={{marginTop: 15, }}
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
priority={foundPriority}
|
||||||
|
checkLogin={checkLogin}
|
||||||
|
/>
|
||||||
|
: null}
|
||||||
|
|
||||||
<div style={{ marginBottom: 100 }} />
|
<div style={{ marginBottom: 100 }} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
NAME=shuffle-orborus
|
NAME=shuffle-orborus
|
||||||
VERSION=1.2.0
|
VERSION=1.2.1
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -207,10 +207,6 @@ func deployServiceWorkers(image string) {
|
|||||||
// Looks for and cleans up all existing items in swarm we can't re-use (Shuffle only)
|
// Looks for and cleans up all existing items in swarm we can't re-use (Shuffle only)
|
||||||
|
|
||||||
// frikky@debian:~/git/shuffle/functions/onprem/worker$ docker service create --replicas 5 --name shuffle-workers --env SHUFFLE_SWARM_CONFIG=run --publish published=33333,target=33333 ghcr.io/shuffle/shuffle-worker:nightly
|
// frikky@debian:~/git/shuffle/functions/onprem/worker$ docker service create --replicas 5 --name shuffle-workers --env SHUFFLE_SWARM_CONFIG=run --publish published=33333,target=33333 ghcr.io/shuffle/shuffle-worker:nightly
|
||||||
networkName := "shuffle_swarm_executions"
|
|
||||||
if len(swarmNetworkName) > 0 {
|
|
||||||
networkName = swarmNetworkName
|
|
||||||
}
|
|
||||||
|
|
||||||
ingressOptions := types.NetworkCreate{
|
ingressOptions := types.NetworkCreate{
|
||||||
Driver: "overlay",
|
Driver: "overlay",
|
||||||
@@ -239,6 +235,11 @@ func deployServiceWorkers(image string) {
|
|||||||
|
|
||||||
//docker network create --driver=overlay workers
|
//docker network create --driver=overlay workers
|
||||||
// Specific subnet?
|
// Specific subnet?
|
||||||
|
networkName := "shuffle_swarm_executions"
|
||||||
|
if len(swarmNetworkName) > 0 {
|
||||||
|
networkName = swarmNetworkName
|
||||||
|
}
|
||||||
|
|
||||||
networkCreateOptions := types.NetworkCreate{
|
networkCreateOptions := types.NetworkCreate{
|
||||||
Driver: "overlay",
|
Driver: "overlay",
|
||||||
Attachable: true,
|
Attachable: true,
|
||||||
@@ -313,15 +314,6 @@ func deployServiceWorkers(image string) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
//serviceOptions := types.ServiceCreateOptions{}
|
|
||||||
//service, err := dockercli.ServiceCreate(
|
|
||||||
// context.Background(),
|
|
||||||
// serviceSpec,
|
|
||||||
// serviceOptions,
|
|
||||||
//)
|
|
||||||
|
|
||||||
//containerName := fmt.Sprintf("shuffle-worker-%s", parsedUuid)
|
|
||||||
|
|
||||||
replicas := uint64(1)
|
replicas := uint64(1)
|
||||||
scaleReplicas := os.Getenv("SHUFFLE_SCALE_REPLICAS")
|
scaleReplicas := os.Getenv("SHUFFLE_SCALE_REPLICAS")
|
||||||
if len(scaleReplicas) > 0 {
|
if len(scaleReplicas) > 0 {
|
||||||
@@ -336,7 +328,6 @@ func deployServiceWorkers(image string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
innerContainerName := fmt.Sprintf("shuffle-workers")
|
innerContainerName := fmt.Sprintf("shuffle-workers")
|
||||||
|
|
||||||
cnt, _ := findActiveSwarmNodes()
|
cnt, _ := findActiveSwarmNodes()
|
||||||
nodeCount := uint64(1)
|
nodeCount := uint64(1)
|
||||||
if cnt > 0 {
|
if cnt > 0 {
|
||||||
@@ -372,8 +363,12 @@ func deployServiceWorkers(image string) {
|
|||||||
swarm.NetworkAttachmentConfig{
|
swarm.NetworkAttachmentConfig{
|
||||||
Target: networkName,
|
Target: networkName,
|
||||||
},
|
},
|
||||||
|
swarm.NetworkAttachmentConfig{
|
||||||
|
Target: "ingress",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
EndpointSpec: &swarm.EndpointSpec{
|
EndpointSpec: &swarm.EndpointSpec{
|
||||||
|
Mode: "vip",
|
||||||
Ports: []swarm.PortConfig{
|
Ports: []swarm.PortConfig{
|
||||||
swarm.PortConfig{
|
swarm.PortConfig{
|
||||||
Protocol: swarm.PortConfigProtocolTCP,
|
Protocol: swarm.PortConfigProtocolTCP,
|
||||||
@@ -403,9 +398,9 @@ func deployServiceWorkers(image string) {
|
|||||||
fmt.Sprintf("TZ=%s", timezone),
|
fmt.Sprintf("TZ=%s", timezone),
|
||||||
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
|
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
|
||||||
},
|
},
|
||||||
Hosts: []string{
|
//Hosts: []string{
|
||||||
innerContainerName,
|
// innerContainerName,
|
||||||
},
|
//},
|
||||||
},
|
},
|
||||||
RestartPolicy: &swarm.RestartPolicy{
|
RestartPolicy: &swarm.RestartPolicy{
|
||||||
Condition: swarm.RestartPolicyConditionOnFailure,
|
Condition: swarm.RestartPolicyConditionOnFailure,
|
||||||
@@ -725,8 +720,8 @@ func initializeImages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if baseimagename == "" {
|
if baseimagename == "" {
|
||||||
baseimagename = "shuffle/shuffle" // Dockerhub
|
baseimagename = "frikky/shuffle" // Dockerhub
|
||||||
baseimagename = "shuffle" // Github (ghcr.io)
|
baseimagename = "shuffle" // Github (ghcr.io)
|
||||||
log.Printf("[DEBUG] Setting baseimagename")
|
log.Printf("[DEBUG] Setting baseimagename")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1560,6 +1555,6 @@ func sendWorkerRequest(workflowExecution shuffle.ExecutionRequest) error {
|
|||||||
|
|
||||||
_ = body
|
_ = body
|
||||||
|
|
||||||
log.Printf("[DEBUG] Ran worker from request with execution ID: %s. Worker URL: %s. DEBUGGING: docker service logs shuffle-workers | grep %s", workflowExecution.ExecutionId, streamUrl, workflowExecution.ExecutionId)
|
log.Printf("[DEBUG] Ran worker from request with execution ID: %s. Worker URL: %s. DEBUGGING: docker service logs shuffle-workers 2&>1 | grep %s", workflowExecution.ExecutionId, streamUrl, workflowExecution.ExecutionId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user