Merge pull request #30 from frikky/dev

Updates to fix HTTPS, app actions, easier deployment and more
This commit is contained in:
Frikkylikeme
2020-05-23 18:02:18 +09:00
committed by GitHub
33 changed files with 928 additions and 649 deletions
+6
View File
@@ -2,8 +2,14 @@
ORG_ID=Shuffle
ENVIRONMENT_NAME=Shuffle
# Different locations etc
APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps
APP_DOWNLOAD_AUTH_USERNAME=""
APP_DOWNLOAD_AUTH_PASSWORD=""
# Other configs
BACKEND_HOSTNAME=shuffle-backend
BACKEND_PORT=5001
FRONTEND_PORT=3001
FRONTEND_PORT_HTTPS=3443
OUTER_HOSTNAME=shuffle-backend
+1
View File
@@ -28,6 +28,7 @@ require (
google.golang.org/api v0.23.0
google.golang.org/appengine v1.6.6
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31
gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86
)
+14
View File
@@ -46,6 +46,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -146,6 +147,7 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -153,6 +155,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -160,9 +163,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@@ -178,6 +186,7 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
@@ -289,6 +298,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -385,6 +395,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+89 -47
View File
@@ -51,6 +51,7 @@ import (
// Web
// "github.com/gorilla/handlers"
"github.com/gorilla/mux"
http2 "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
// Old items (cloud)
// "google.golang.org/appengine"
// "google.golang.org/appengine/memcache"
@@ -1980,7 +1981,7 @@ func handleLogin(resp http.ResponseWriter, request *http.Request) {
})
loginData = fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, Userdata.Session, expiration.Unix())
log.Printf("SESSION LENGTH MORE THAN 0 IN LOGIN: %s", Userdata.Session)
//log.Printf("SESSION LENGTH MORE THAN 0 IN LOGIN: %s", Userdata.Session)
err = SetSession(ctx, *Userdata, Userdata.Session)
if err != nil {
@@ -3921,6 +3922,14 @@ func setBadMemcache(ctx context.Context, path string) {
//}
}
type Result struct {
Success bool `json:"success"`
Reason string `json:"reason"`
List []string `json:"list"`
}
var docs_list = Result{List: []string{}}
func getDocList(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
@@ -3939,11 +3948,24 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
// return
//}
if len(docs_list.List) > 0 {
b, err := json.Marshal(docs_list)
if err != nil {
log.Printf("Failed marshaling result: %s", err)
//http.Error(resp, err.Error(), 500)
} else {
resp.WriteHeader(200)
resp.Write(b)
return
}
}
client := github.NewClient(nil)
_, item1, _, err := client.Repositories.GetContents(ctx, "shaffuru", "shuffle-docs", "docs", nil)
_, item1, _, err := client.Repositories.GetContents(ctx, "frikky", "shuffle-docs", "docs", nil)
if err != nil {
log.Printf("Github error: %s", err)
resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error listing directory"`)))
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error listing directory: %s"`, err)))
return
}
@@ -3964,16 +3986,12 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
log.Println(names)
type Result struct {
Success bool `json:"success"`
Reason string `json:"reason"`
List []string `json:"list"`
}
var result Result
result.Success = true
result.Reason = "Success"
result.List = names
docs_list = result
b, err := json.Marshal(result)
if err != nil {
http.Error(resp, err.Error(), 500)
@@ -4001,6 +4019,8 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
}
// r.HandleFunc("/api/v1/docs/{key}", getDocs).Methods("GET", "OPTIONS")
var alldocs = map[string][]byte{}
func getDocs(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
@@ -4016,16 +4036,15 @@ func getDocs(resp http.ResponseWriter, request *http.Request) {
//ctx := context.Background()
docPath := fmt.Sprintf("https://raw.githubusercontent.com/shaffuru/shuffle-docs/master/docs/%s.md", location[4])
//if item, err := memcache.Get(ctx, docPath); err == memcache.ErrCacheMiss {
// // Not in cache
//} else if err != nil {
// // Error with cache
// log.Printf("Error getting item: %v", err)
//} else {
// resp.WriteHeader(200)
// resp.Write([]byte(item.Value))
// return
//}
//location[4]
//var, ok := alldocs["asd"]
key, ok := alldocs[fmt.Sprintf("%s", location[4])]
// Custom cache for github issues lol
if ok {
resp.WriteHeader(200)
resp.Write(key)
return
}
client := &http.Client{}
req, err := http.NewRequest(
@@ -4078,6 +4097,8 @@ func getDocs(resp http.ResponseWriter, request *http.Request) {
return
}
alldocs[location[4]] = b
// Add to cache if it doesn't exist
//item := &memcache.Item{
// Key: docPath,
@@ -5601,30 +5622,6 @@ func runInit(ctx context.Context) {
}
}
// Getting apps to see if we should initialize a test
workflowapps, err := getAllWorkflowApps(ctx)
if err != nil {
log.Printf("Failed getting apps: %s", err)
} else if err == nil && len(workflowapps) == 0 {
log.Printf("Apps: loading TEST")
fs := memfs.New()
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, &git.CloneOptions{
URL: "https://github.com/frikky/shuffle-apps",
})
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
}
dir, err := fs.ReadDir("")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
}
_ = r
iterateAppGithubFolders(fs, dir, "", "testing")
}
// Gets schedules and starts them
schedules, err := getAllSchedules(ctx)
if err != nil {
@@ -5654,6 +5651,51 @@ func runInit(ctx context.Context) {
}
}
// Getting apps to see if we should initialize a test
workflowapps, err := getAllWorkflowApps(ctx)
if err != nil {
log.Printf("Failed getting apps: %s", err)
} else if err == nil && len(workflowapps) == 0 {
log.Printf("Apps: loading TEST")
fs := memfs.New()
storer := memory.NewStorage()
url := os.Getenv("APP_DOWNLOAD_LOCATION")
if len(url) == 0 {
url = "https://github.com/frikky/shuffle-apps"
}
username := os.Getenv("APP_DOWNLOAD_AUTH_USERNAME")
password := os.Getenv("APP_DOWNLOAD_AUTH_PASSWORD")
cloneOptions := &git.CloneOptions{
URL: url,
}
if len(username) > 0 && len(password) > 0 {
cloneOptions.Auth = &http2.BasicAuth{
Username: username,
Password: password,
}
}
log.Printf("Getting apps from %s", url)
r, err := git.Clone(storer, fs, cloneOptions)
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
}
dir, err := fs.ReadDir("")
if err != nil {
log.Printf("Failed reading folder: %s", err)
}
_ = r
//iterateAppGithubFolders(fs, dir, "", "testing")
// FIXME: Get all the apps?
iterateAppGithubFolders(fs, dir, "", "")
}
log.Printf("Finished INIT")
}
@@ -5701,16 +5743,16 @@ func init() {
r.HandleFunc("/api/v1/streams", handleWorkflowQueue).Methods("POST")
r.HandleFunc("/api/v1/streams/results", handleGetStreamResults).Methods("POST", "OPTIONS")
// Apps
r.HandleFunc("/api/v1/apps/get_existing", loadExistingApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps/get_existing/{appname}", loadExistingApps).Methods("GET", "OPTIONS")
// App specific
r.HandleFunc("/api/v1/apps/get_existing", loadSpecificApps).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}", deleteWorkflowApp).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/apps/search", getSpecificApps).Methods("POST", "OPTIONS")
// Legacy things
// Legacy app things
r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/workflows/apps", getWorkflowApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
+120 -13
View File
@@ -26,6 +26,7 @@ import (
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
http2 "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
newscheduler "github.com/carlescere/scheduler"
"github.com/go-git/go-git/v5/storage/memory"
@@ -2916,6 +2917,51 @@ func handleGetfile(resp http.ResponseWriter, request *http.Request) ([]byte, err
return buf.Bytes(), nil
}
func getSpecificApps(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
// Just need to be logged in
// FIXME - should have some permissions?
_, err := handleApiAuthentication(resp, request)
if err != nil {
log.Printf("Api authentication failed in set new app: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error with body read: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
type tmpStruct struct {
Search string `json:"search"`
}
var tmpBody tmpStruct
err = json.Unmarshal(body, &tmpBody)
if err != nil {
log.Printf("Error with unmarshal tmpBody: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// FIXME - continue the search here with github repos etc.
// Caching might be smart :D
log.Printf("Body: %s", string(body))
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
}
func validateAppInput(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
@@ -3113,7 +3159,7 @@ func deployWebhookFunction(ctx context.Context, name, localization, applocation
return nil
}
func loadExistingApps(resp http.ResponseWriter, request *http.Request) {
func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
@@ -3129,22 +3175,83 @@ func loadExistingApps(resp http.ResponseWriter, request *http.Request) {
return
}
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error with body read: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// Field1 & 2 can be a lot of things..
type tmpStruct struct {
URL string `json:"url"`
Field1 string `json:"field_1"`
Field2 string `json:"field_2"`
}
//log.Printf("Body: %s", string(body))
var tmpBody tmpStruct
err = json.Unmarshal(body, &tmpBody)
if err != nil {
log.Printf("Error with unmarshal tmpBody: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
fs := memfs.New()
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, &git.CloneOptions{
URL: "https://github.com/frikky/shuffle-apps",
})
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
}
if strings.Contains(tmpBody.URL, "github") || strings.Contains(tmpBody.URL, "gitlab") || strings.Contains(tmpBody.URL, "bitbucket") {
cloneOptions := &git.CloneOptions{
URL: tmpBody.URL,
}
dir, err := fs.ReadDir("/")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
// FIXME: Better auth.
if len(tmpBody.Field1) > 0 && len(tmpBody.Field2) > 0 {
cloneOptions.Auth = &http2.BasicAuth{
Username: tmpBody.Field1,
Password: tmpBody.Field2,
}
}
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, cloneOptions)
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
}
dir, err := fs.ReadDir("/")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
}
_ = r
iterateAppGithubFolders(fs, dir, "", "")
} else if strings.Contains(tmpBody.URL, "s3") {
//https://docs.aws.amazon.com/sdk-for-go/api/service/s3/
//sess := session.Must(session.NewSession())
//downloader := s3manager.NewDownloader(sess)
//// Write the contents of S3 Object to the file
//storer := memory.NewStorage()
//n, err := downloader.Download(storer, &s3.GetObjectInput{
// Bucket: aws.String(myBucket),
// Key: aws.String(myString),
//})
//if err != nil {
// return fmt.Errorf("failed to download file, %v", err)
//}
//fmt.Printf("file downloaded, %d bytes\n", n)
} else {
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s is unsupported"}`, tmpBody.URL)))
return
}
_ = r
iterateAppGithubFolders(fs, dir, "", "")
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
+5 -1
View File
@@ -6,7 +6,8 @@ services:
container_name: shuffle-frontend
hostname: shuffle-frontend
ports:
- "3001:80"
- "${FRONTEND_PORT}:80"
- "${FRONTEND_PORT_HTTPS}:443"
networks:
- shuffle
restart: unless-stopped
@@ -17,6 +18,8 @@ services:
image: frikky/shuffle:database
container_name: shuffle-database
hostname: shuffle-database
ports:
- "8000:8000"
networks:
- shuffle
restart: unless-stopped
@@ -37,6 +40,7 @@ services:
environment:
- ORG_ID=${ORG_ID}
- DATASTORE_EMULATOR_HOST=shuffle-database:8000
- APP_DOWNLOAD_LOCATION=${APP_DOWNLOAD_LOCATION}
restart: unless-stopped
depends_on:
- database
+3 -3
View File
@@ -21,13 +21,13 @@ RUN mkdir -p /usr/share/nginx/html/js
RUN mkdir -p /usr/share/nginx/html/img
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
#Localhost certificate challenge: Y#XwrJ#DoZGz2w6x
COPY --from=builder /usr/src/app/certs/fullchain.pem /etc/nginx/fullchain.cert.pem
COPY --from=builder /usr/src/app/certs/privkey.pem /etc/nginx/privkey.pem
# Test
COPY --from=builder /usr/src/app/nginxtest.conf /etc/nginx/nginx.conf
# Prod
#COPY --from=builder /usr/src/app/nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /usr/src/app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 443
+8
View File
@@ -0,0 +1,8 @@
# Certificate:
Creating a localhost certificate:
```
openssl genrsa -out privkey.pem 2048
openssl req -new -key privkey.pem -out certreq.csr
openssl x509 -req -days 3650 -in certreq.csr -signkey privkey.pem -out fullchain.pem
```
-10
View File
@@ -1,10 +0,0 @@
This directory contains your keys and certificates.
`privkey.pem` : the private key for your certificate.
`fullchain.pem`: the certificate file used in most server software.
`chain.pem` : used for OCSP stapling in Nginx >=1.3.7.
`cert.pem` : will break many server configurations, and should not be used
without reading further documentation (see link below).
We recommend not moving these files. For more information, see the Certbot
User Guide at https://certbot.eff.org/docs/using.html#where-are-my-certificates.
-31
View File
@@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFRzCCBC+gAwIBAgISA2OOAaaFtVzoqzLXCBV19fpjMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTAyMDkxMjQxMzlaFw0x
OTA1MTAxMjQxMzlaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAr4nj/G0MxSEWHnD0oC+jS03ofE6hXC87z0h6iNh5
lRdVoh9o2H22iQNTmWOWB56oqdBQEOeCcNFexYOzL9S91IVy3Q+hDev5rkJ44uFP
0VtgKbTc/aKIpEcSYPda2b1lb1mAYpJ/HqvzMDrJ+izCpTLEs2h+mD+2LAx7Ie3Z
OE+mFhU7aYdJ7rbUob7BT9cxzbp4CLGjaZHFKrC1uafSSh3bFFlXJpYmleunGVS9
4BUuveZdWJGLFMN1cAJiMGLewsKp5YXKB9eiH6gAg90udRaanPz3NgFa/8qju9iA
64YJcDNr9Aj04EIntRbPJm286+TrJbaf57ESCS32cqaDEwIDAQABo4ICXDCCAlgw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTaQOYhr73PSHSd+P+b7FJhYcVPwDAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQB
gt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3Jn
MIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYA4mlLribo6UAJ6IYbtjuD1D7n/nSI
+6SPKJMBnd3x2/4AAAFo0n3+fgAABAMARzBFAiBebCfZn5HQoIloL8iS7Q2U9DE/
IlMLvhK0UFlhr1u5agIhAN84nfBT1slMt86E95tvvYbEHcAfapogmJmOxSoI5ati
AHUAY/Lbzeg7zCzPC3KEJ1drM6SNYXePvXWmOLHHaFRL2I0AAAFo0n4AegAABAMA
RjBEAiARET8ZHf3qcahgGa9O440U7/Zbfi5+WO0XRlN/cVQZBgIgKQpHRXv9urpk
MS+tz9jvsxERUYEEjRgsSnM1Bs3AF44wDQYJKoZIhvcNAQELBQADggEBADPUIj7w
z+He68As1CFu9tAwGMeLZDgXtPsybAOY9cWm9aL5sC5RldK+ob/5Xi2aa7YEeeij
VP44lOjXtr3EmGm34vN9pL7JyAhYAmEZToyJEt4dbyCbLhO0IT9Po4ropiXk7ze0
CRNEg2CCdXkG7KLHIxP6Am1vr1/TA8IC4lf0ocYJs5sU4/7Bj8eViuZ7F8ZcJo1t
O24jBw5m48fbmmDWkcc3YHVD55sIys3RDEQMLABgIxgN+kqRqfCslREpPYWa/o2T
jOt99S/zjdeRgGJfO8XKtI2TH8ZMHNyKaJYjmdX0CcZFmm2E8SZRYuB4j/KUdd8a
xje2fid5pAJf2Tk=
-----END CERTIFICATE-----
+19
View File
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIDBTCCAe0CAQAwgYYxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEOMAwG
A1UEBwwFVG9reW8xEDAOBgNVBAoMB1NodWZmbGUxEDAOBgNVBAsMB1NodWZmbGUx
EDAOBgNVBAMMB1NodWZmbGUxITAfBgkqhkiG9w0BCQEWEmZyaWtreUBzaHVmZmxl
ci5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLYQupj6hNpfKzy
km3qFkTvuPFed2s6HkBBqKwgpZ6C7wdDuUrMd9SXguw9yhtgxezg+ui1O735ZL4W
6ZpT/Pf3Staj7SHgXAGDnPwcTeWgbd9rZO02UlD70Bhj6SBKYdS8FHRFJvbCe6V0
tY+pJhaTUogwPr1jJTvuHIqRhXHmUl88jVkMIj27FPTnUDEEbr+E8Q6LDYUfSxpw
beZqpv8FRGP88H+WGb/CnbFsvJMbNkHbM2Wj9b6yYiHuw8WRuTODX5YOVefGSYn/
h3JgniT2AdQAsacdB3avdE/b4Mq1FUVqsYaUGSXZ+Iysdo9/7zhYmb0UtaFMSQDA
zsOlIrMCAwEAAaA5MBYGCSqGSIb3DQEJAjEJDAdTaHVmZmxlMB8GCSqGSIb3DQEJ
BzESDBBZI1h3ckojRG9aR3oydzZ4MA0GCSqGSIb3DQEBCwUAA4IBAQCinafabm9w
EqhWrgi0lXQ+iqcklvigSegaEZx5g8lr4qYADPqRWRnzZcq8Dzifx6HUsDs6Dv6/
7INF6cwGxvPFv2CBEvS/KkPtWxHaoATxRxwGw9Vh88OQy/cE6/Jiu8t94QtGMLRL
V0bUnLfc3OKqNM5YvRf8Z1jbO+tzZ4ul3lApHF7UGq01BIcna0D4JblnwP62M4MW
vY++wzYqqsHAOrUN94tJQaTP1nc4u03lme+4duKY7G5yxMYn1A0aDp0IFeDvela9
nylRCM3V5FK1aubXuQnVYoFnnwaM2hTBVTKJbaCCWQhM0e3XYd8mCQYmgf+qlXBN
OG4enppZCsAJ
-----END CERTIFICATE REQUEST-----
-27
View File
@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
+19 -56
View File
@@ -1,58 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIFRzCCBC+gAwIBAgISA2OOAaaFtVzoqzLXCBV19fpjMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTAyMDkxMjQxMzlaFw0x
OTA1MTAxMjQxMzlaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAr4nj/G0MxSEWHnD0oC+jS03ofE6hXC87z0h6iNh5
lRdVoh9o2H22iQNTmWOWB56oqdBQEOeCcNFexYOzL9S91IVy3Q+hDev5rkJ44uFP
0VtgKbTc/aKIpEcSYPda2b1lb1mAYpJ/HqvzMDrJ+izCpTLEs2h+mD+2LAx7Ie3Z
OE+mFhU7aYdJ7rbUob7BT9cxzbp4CLGjaZHFKrC1uafSSh3bFFlXJpYmleunGVS9
4BUuveZdWJGLFMN1cAJiMGLewsKp5YXKB9eiH6gAg90udRaanPz3NgFa/8qju9iA
64YJcDNr9Aj04EIntRbPJm286+TrJbaf57ESCS32cqaDEwIDAQABo4ICXDCCAlgw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTaQOYhr73PSHSd+P+b7FJhYcVPwDAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQB
gt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3Jn
MIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYA4mlLribo6UAJ6IYbtjuD1D7n/nSI
+6SPKJMBnd3x2/4AAAFo0n3+fgAABAMARzBFAiBebCfZn5HQoIloL8iS7Q2U9DE/
IlMLvhK0UFlhr1u5agIhAN84nfBT1slMt86E95tvvYbEHcAfapogmJmOxSoI5ati
AHUAY/Lbzeg7zCzPC3KEJ1drM6SNYXePvXWmOLHHaFRL2I0AAAFo0n4AegAABAMA
RjBEAiARET8ZHf3qcahgGa9O440U7/Zbfi5+WO0XRlN/cVQZBgIgKQpHRXv9urpk
MS+tz9jvsxERUYEEjRgsSnM1Bs3AF44wDQYJKoZIhvcNAQELBQADggEBADPUIj7w
z+He68As1CFu9tAwGMeLZDgXtPsybAOY9cWm9aL5sC5RldK+ob/5Xi2aa7YEeeij
VP44lOjXtr3EmGm34vN9pL7JyAhYAmEZToyJEt4dbyCbLhO0IT9Po4ropiXk7ze0
CRNEg2CCdXkG7KLHIxP6Am1vr1/TA8IC4lf0ocYJs5sU4/7Bj8eViuZ7F8ZcJo1t
O24jBw5m48fbmmDWkcc3YHVD55sIys3RDEQMLABgIxgN+kqRqfCslREpPYWa/o2T
jOt99S/zjdeRgGJfO8XKtI2TH8ZMHNyKaJYjmdX0CcZFmm2E8SZRYuB4j/KUdd8a
xje2fid5pAJf2Tk=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
MIIDijCCAnICCQCJ9DUcfuAjwzANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMC
SlAxDjAMBgNVBAgMBVRva3lvMQ4wDAYDVQQHDAVUb2t5bzEQMA4GA1UECgwHU2h1
ZmZsZTEQMA4GA1UECwwHU2h1ZmZsZTEQMA4GA1UEAwwHU2h1ZmZsZTEhMB8GCSqG
SIb3DQEJARYSZnJpa2t5QHNodWZmbGVyLmlvMB4XDTIwMDUyMzA4MjA1MVoXDTMw
MDUyMTA4MjA1MVowgYYxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEOMAwG
A1UEBwwFVG9reW8xEDAOBgNVBAoMB1NodWZmbGUxEDAOBgNVBAsMB1NodWZmbGUx
EDAOBgNVBAMMB1NodWZmbGUxITAfBgkqhkiG9w0BCQEWEmZyaWtreUBzaHVmZmxl
ci5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLYQupj6hNpfKzy
km3qFkTvuPFed2s6HkBBqKwgpZ6C7wdDuUrMd9SXguw9yhtgxezg+ui1O735ZL4W
6ZpT/Pf3Staj7SHgXAGDnPwcTeWgbd9rZO02UlD70Bhj6SBKYdS8FHRFJvbCe6V0
tY+pJhaTUogwPr1jJTvuHIqRhXHmUl88jVkMIj27FPTnUDEEbr+E8Q6LDYUfSxpw
beZqpv8FRGP88H+WGb/CnbFsvJMbNkHbM2Wj9b6yYiHuw8WRuTODX5YOVefGSYn/
h3JgniT2AdQAsacdB3avdE/b4Mq1FUVqsYaUGSXZ+Iysdo9/7zhYmb0UtaFMSQDA
zsOlIrMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAix08M+pdohlyL9/zeR20mGKp
njmJrako1vBrV2tTb2p/nv7GJ9jP6NPrsVMlphe/Eu0iezTF44GWa1tUI3Y1zN7K
4a21QGkHIyOUBy/uQCrRqM/C6kEP/vBheebCEtGxmF+J81aDBx9IOOoAFSWOjMHN
Yx1iSk4DMp5kfLhxtui7rlSrVqt9Xrm1i/aUly7BuYIvT42J6tnpEF0g/1phnudz
N0bgSb29+PtzyqbqPhVzxaUT4T9vD3qLIbiDSi1I5Zx1vX1LI222ceR1zrIWU+l7
X1p/CBkFpORaK3NCK7y3L8gReO6kO1eE81WR0993m1pwdmxoOiVlIQ7R1cfYGg==
-----END CERTIFICATE-----
-34
View File
@@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF+TCCBOGgAwIBAgISA8rwfiC3p89WYm/X9RR3XhzTMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODExMDkyMTEzNTNaFw0x
OTAyMDcyMTEzNTNaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA2NIGtVlzW3fktmv74YG23LKLM6xIxn/mIPt4PgZ+
K3407GryQueToAnG5iTXTox5UnyArvqxAe5cTonrlWTai9Do5CuhrKI22EMpwrSl
Uo38dtNu2AHLENrY+aFzEwsVvkWGpIQ8/Y63T8M9ohiInF/S5ZPojIJxy7OVQ3io
MdLbb1atYfBcnt0DFKyMC1yxDyYj8w1jvwQWlKGBYQeRd2MTWEjHO7CJPgiRwiLi
rFBlDWnFz8GKntXLHI2pYL6+X4WgG9XfwzSN/w+ju48JAgCc6yTxvaQxQDpHst3D
kv4CXNTP3gt2RSIOkQldBQzi/FgBLDv/qSuXAnLGsIgk5QIDAQABo4IDDjCCAwow
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBThSBGBk0ZSYT1ptylvWQGZqdkBDjAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsr
BgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25s
eSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4g
YWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQg
aHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wggECBgorBgEEAdZ5
AgQCBIHzBIHwAO4AdQB0ftqDMa0zEJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAA
AWb6ieWoAAAEAwBGMEQCIE8+auAtQOLY4U1yoEDvCTQULv4PS9Xdo1uJzQF5nhBA
AiBsfKR2UMxxIatzPOQPtuRrVEAv4+tX4o/ch5e6TAnOCAB1ACk8UZZUyDlluqpQ
/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZvqJ6BEAAAQDAEYwRAIgKj2gwlC/9AIF
hrx8nl2oEwxUoi/b4ZCCdQpz8JsJhOACIHRkuo56NErZR87lVtI0oZItZ6nzFPQz
BFaxx89eBJKPMA0GCSqGSIb3DQEBCwUAA4IBAQCFURbxUFKAF3CJRiaUsRrjFDuc
R25Dm86QgDqDLGkYf7/y5by2/amNzBbBLvcqUhScpjtalqO38Efw+2+c/UBGTQZ7
C8vU5KrjG6bnOmoHx/t+ml4E88omMlEmlRIEiL/6yfpOnCCv+3IHJjUw8iPuH7+j
57Vhwtq6mOvId2QfDfL86ELgXKvBKfbqac7YfzUHVyB4WeXagfpYiObpspTud0tZ
Yf5Qs7g8GLkXfpkOJHG1+91Hi7+Pb1cCAqkkgIwFG4oeBdxAkxkaIyBRk3ZfnXYw
9G1qofLrs2UbLUhIEyMgavI7kKwLg1pwsYs4Yn+RVR5hZPkj0ZUnc4gW7wCP
-----END CERTIFICATE-----
-12
View File
@@ -1,12 +0,0 @@
Traceback (most recent call last):
File "/usr/bin/certbot", line 11, in <module>
load_entry_point('certbot==0.10.2', 'console_scripts', 'certbot')()
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 836, in main
setup_logging(config)
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 700, in setup_logging
config, logfile=logfile, fmt=file_fmt)
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 667, in setup_log_file_handler
raise errors.Error(_PERM_ERR_FMT.format(error))
Error: The following error was encountered:
[Errno 13] Permission denied: '/var/log/letsencrypt/letsencrypt.log'
If running as non-root, set --config-dir, --logs-dir, and --work-dir to writeable paths.
-27
View File
@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-61
View File
@@ -1,61 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF+TCCBOGgAwIBAgISA8rwfiC3p89WYm/X9RR3XhzTMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODExMDkyMTEzNTNaFw0x
OTAyMDcyMTEzNTNaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA2NIGtVlzW3fktmv74YG23LKLM6xIxn/mIPt4PgZ+
K3407GryQueToAnG5iTXTox5UnyArvqxAe5cTonrlWTai9Do5CuhrKI22EMpwrSl
Uo38dtNu2AHLENrY+aFzEwsVvkWGpIQ8/Y63T8M9ohiInF/S5ZPojIJxy7OVQ3io
MdLbb1atYfBcnt0DFKyMC1yxDyYj8w1jvwQWlKGBYQeRd2MTWEjHO7CJPgiRwiLi
rFBlDWnFz8GKntXLHI2pYL6+X4WgG9XfwzSN/w+ju48JAgCc6yTxvaQxQDpHst3D
kv4CXNTP3gt2RSIOkQldBQzi/FgBLDv/qSuXAnLGsIgk5QIDAQABo4IDDjCCAwow
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBThSBGBk0ZSYT1ptylvWQGZqdkBDjAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsr
BgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25s
eSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4g
YWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQg
aHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wggECBgorBgEEAdZ5
AgQCBIHzBIHwAO4AdQB0ftqDMa0zEJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAA
AWb6ieWoAAAEAwBGMEQCIE8+auAtQOLY4U1yoEDvCTQULv4PS9Xdo1uJzQF5nhBA
AiBsfKR2UMxxIatzPOQPtuRrVEAv4+tX4o/ch5e6TAnOCAB1ACk8UZZUyDlluqpQ
/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZvqJ6BEAAAQDAEYwRAIgKj2gwlC/9AIF
hrx8nl2oEwxUoi/b4ZCCdQpz8JsJhOACIHRkuo56NErZR87lVtI0oZItZ6nzFPQz
BFaxx89eBJKPMA0GCSqGSIb3DQEBCwUAA4IBAQCFURbxUFKAF3CJRiaUsRrjFDuc
R25Dm86QgDqDLGkYf7/y5by2/amNzBbBLvcqUhScpjtalqO38Efw+2+c/UBGTQZ7
C8vU5KrjG6bnOmoHx/t+ml4E88omMlEmlRIEiL/6yfpOnCCv+3IHJjUw8iPuH7+j
57Vhwtq6mOvId2QfDfL86ELgXKvBKfbqac7YfzUHVyB4WeXagfpYiObpspTud0tZ
Yf5Qs7g8GLkXfpkOJHG1+91Hi7+Pb1cCAqkkgIwFG4oeBdxAkxkaIyBRk3ZfnXYw
9G1qofLrs2UbLUhIEyMgavI7kKwLg1pwsYs4Yn+RVR5hZPkj0ZUnc4gW7wCP
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-28
View File
@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDY0ga1WXNbd+S2
a/vhgbbcsoszrEjGf+Yg+3g+Bn4rfjTsavJC55OgCcbmJNdOjHlSfICu+rEB7lxO
ieuVZNqL0OjkK6GsojbYQynCtKVSjfx2027YAcsQ2tj5oXMTCxW+RYakhDz9jrdP
wz2iGIicX9Llk+iMgnHLs5VDeKgx0ttvVq1h8Fye3QMUrIwLXLEPJiPzDWO/BBaU
oYFhB5F3YxNYSMc7sIk+CJHCIuKsUGUNacXPwYqe1cscjalgvr5fhaAb1d/DNI3/
D6O7jwkCAJzrJPG9pDFAOkey3cOS/gJc1M/eC3ZFIg6RCV0FDOL8WAEsO/+pK5cC
csawiCTlAgMBAAECggEALGoxp5qQT+9qcZgDO/mnbORCMa6cJdVzXdRFmGcaF2y+
CKQLxnrLud/m16Q6WsPZ4nTQo4eFFQEv9YK5OJw1TKjZ3Eu3zbZZB8oSVulMaHHf
grPjI+qSH3zFL7XL7d26cYSqhS71k3dVw8gZ6wedjHLwr8ixvX7HMtQxwmWIBtRr
Sj9zYyqkoBLDWrhoGh7GlAHHiPw4cFY7XRaAbq36JYhkO+VUK7BRJMMPwSSMbmx1
S3O8PhXy5he893HVRAHhQq8xIup/Q+PktB39xgQX0M+mjMoqD9mJ0fgaKnff8K3U
C3ovU9YmAR9VTGE/1S4yeT5BreXGbCwXKGSHO4KBLQKBgQDtZWjbtUCHyuiNk8pp
17mgpWEZOHl7+hehO6uN2GwE4bdrBRxK3b+ZQRJqVRQnhQRkYA4x1vVOG05A0b2C
QJBERd66XWMZHs3820kexo+Lw0XgAaM5bIoW8VZxAhHL9J49piiboawp/sNlFPVl
HL0x5ztkP/7QHRwvInY9giVNAwKBgQDpz9S7N/wNwQf6NrqbboYpUkA8WcAjGdzi
gsgK47rm2Nvs5CTWgVykTVokN/HjUCnkzNcET2e0lwF3M2Z6f3wyWiwngrGCWVyL
YXgcMT080CPWvfpVZ/kjkOORsD4zhceVs/ECJDPwNH7rKderILxQld7BQ+PcY32n
5iu4L3Cd9wKBgQDIUWsjAhX6v+BuHwiNOYicoxCFHJ9+WvF3jwdbAQVdNS31s3FF
R0q2wi8M5M/F7Ttgi6FOswl5qBbnIVTdRSe3RJIGBmlpuBGvTUatHnXgRJ2AwUD/
YrQ/WdRMNafYx4iDkuLvOIQzR5OPhxjvAkovguQd2tZkvDudFmJZ0qkxCwKBgAKK
R31hNlPP7Q5C2fQmVz7Lrfb54qR++29ajGHR543qfTktoVjTPvZqALi0AuS9Ujcy
IoPhePb1TQbGgC6EhAzn/eLQAK2x2teIz40+27N1b2490iJrZsGEKXTDvWlB4tE1
i0DCs+3AJEDZy4YIbQNTHYBsBGW4jvzr+z2dBlQxAoGAZaQ8pL6wnaXqCQA/ULO+
lcF5c98pOLHpNTE19zodDEpG1OmavHgDhThOXJYfogkeAJaoovaQ5hHS/YLkXVOU
Xd2JN5FLbAwLN1jorB5tH1+c2SOOXaGoi7BTM9/mcUkJqYIthK4SoYw0oO2nphGZ
Mm8KDWDzu7D3r3XB8Xpl8ng=
-----END PRIVATE KEY-----
+27 -28
View File
@@ -1,28 +1,27 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvieP8bQzFIRYe
cPSgL6NLTeh8TqFcLzvPSHqI2HmVF1WiH2jYfbaJA1OZY5YHnqip0FAQ54Jw0V7F
g7Mv1L3UhXLdD6EN6/muQnji4U/RW2AptNz9ooikRxJg91rZvWVvWYBikn8eq/Mw
Osn6LMKlMsSzaH6YP7YsDHsh7dk4T6YWFTtph0nuttShvsFP1zHNungIsaNpkcUq
sLW5p9JKHdsUWVcmliaV66cZVL3gFS695l1YkYsUw3VwAmIwYt7CwqnlhcoH16If
qACD3S51Fpqc/Pc2AVr/yqO72IDrhglwM2v0CPTgQie1Fs8mbbzr5Osltp/nsRIJ
LfZypoMTAgMBAAECggEAVrRic0WeACTWmxSqEBFXtBN4WSYxl6oQ/dLMC5n5fAX5
m0mubPizV7vX6DUDXyIkJzSox6DCkl0oVaE2udJ4LWf5E23r3EeJnWRh95bY6Q0c
U51tZq6IlbQxRMoJCvH9D2IDAy1fMtQ2G8V+DF9diWGpPQDJPwSBRAKqM1kbaS9E
40zoKzzkYWQYHnNrgiLnUpT6LxVJrKQo4B/HxhoovlQ+Uu8oRbK+JdRvKTWQ7ELV
evRtXxHSeq+22TdTysDfalOVWudaUSe2CqzX90mGzxerA7Baorb0Fas9nhTPFZus
pqOYJPDUSU0SPj939lArlsAHCpUY2/NOK6tOeotQ0QKBgQDX7I/GmqiN4BXnmlBC
fvix1BSQNs0d1fVMWiVXhgjUnTWc7oyEnE5tDkS6OyUKFHiK+xYxhy9rjis8ch+h
CfyafADku6y3lG2QwktDA48cRavzmRZhwbbDqsRLIKRUqJyon8Xn4jsX0QTTHM75
jJPSFLny0nsvIbQgixz7D0FrmQKBgQDQHnOIRvcYYGWV9kxGw+l9I+JNnX8RZWmD
u9fZnqUQ01NtR6DHhmes73GtvRmhEeEQgICwpmBY65cUYHYkQ6WmhxdPGrSxLLCn
539nvAhVs5WgFbEGsV7alFob1A2kbMWxnmvtk/mmaXyFf1D7jgDn9mabtsXlUVzk
2OW+/mAviwKBgH0LGSQ5sn0fFXBflDU+FMXe/N2bbuPlYT4LQm7SR1DhjgfIugWe
A2jyh2iWEdgpjLlnuS2LjTGrTmyd5qU7BFdukpHkAZz6zwyzCCTR7dHAo1jaAfUw
2qerwCuFxsTkNH0Oseycvf4H5NRhbZdlCsHxkNIHhKEB0q+6AFmANzGZAoGBAK5r
Zu4mc34Fg/3Lfp+sH2oWgdoEjfL5aBXUfxFOaQ6R3ZBvgGrX1NnVjxNJsUoRXuti
lvf1aDf9sg+MzFaWLyVCgKF2Q0tdpewCEv/QUbfpmxOgOk3epx1PSbma3ZgY5RJ4
MAHbi1YRgB+t1SQOHepJ0jLcWjxXFSBiOyH3tIsDAoGANQ6zOvNV/Mjkj82AJZGa
bW21TcMWBZhCJZc7jI93S9oCJl+qp9eHjUVbsg6pf+8MWOmMtXFLgC/idJF8tB1E
OzsW2xoKKSstj8JdAPsx8vR2kkLfkXPMT6ymOA7Lbc4ZwKSDbwo5xdAR8qBAnkic
xIKG1OZD55i9MuHng2uBJBc=
-----END PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA0thC6mPqE2l8rPKSbeoWRO+48V53azoeQEGorCClnoLvB0O5
Ssx31JeC7D3KG2DF7OD66LU7vflkvhbpmlP89/dK1qPtIeBcAYOc/BxN5aBt32tk
7TZSUPvQGGPpIEph1LwUdEUm9sJ7pXS1j6kmFpNSiDA+vWMlO+4cipGFceZSXzyN
WQwiPbsU9OdQMQRuv4TxDosNhR9LGnBt5mqm/wVEY/zwf5YZv8KdsWy8kxs2Qdsz
ZaP1vrJiIe7DxZG5M4Nflg5V58ZJif+HcmCeJPYB1ACxpx0Hdq90T9vgyrUVRWqx
hpQZJdn4jKx2j3/vOFiZvRS1oUxJAMDOw6UiswIDAQABAoIBACvEQH+vJdPJvduY
rtSqFt1Qda+E0H0tn0HvXzf7vuVcgImdgUUJlIZIvSCU4vMz72HwgaT0meYhcswS
rYMflA9VAe/0LzEtBWw7Ccc7iN/1oVkTTev/rq6o1tV5R9cwGYazU/ueryvhyxDZ
XSbpEcL16dfjS+K8RepezwXklzLBIB6wfZ0aulbCoNYcqtD5Jyo4SLzqYPH95cQi
nN09xSnrS3tc9tMj0R2/5avGWEKUHXqKam+NIEc7y6AQJ/qjDaFn13emIB1mDVls
DiEwAyQBOW+1m77raFYFWCuHe30QgdP7SdB0I8XbPATUssnLLfBPj3K9Hh17n/vx
zAJKkiECgYEA8/EpPTpimOmOM3XsaWvFVbnWSFLAEXgn5c0Ch+uIDHr9DbYufn6K
hVXqgTcO83qVLyRD4WIJ7lgqKajHmCxXB4RsyCYaP80jKW0cYAD8sBokWfQTtbry
+Ka45AEPt1Mp1w45vry4RO4HFhfcFwxGRqADZE5Dtg1JNttkDM5FCW8CgYEA3URJ
upl/6+g3k7njxoXxfV8doS8NCdGF9yQsUVITaOrYUHJ71K8GOwlATG6y6uAjRRb4
GgzLCL+nGoSF79r1vWrwfMz1q+d8nBh+v+uqwS4KFSbs2AICVAkjYnNi3/3BAhBn
tmzcbUigyx7qRhlbFZk1OQCuzw3YNqk0kDO6MP0CgYApcl0eYRAliPE3Px723m+9
3ABTc3Pcw/yLZ+S5MUSBUlgyfzSxG1DvzKQ2ZiNtLPOx+chqv9yOGX64a0vWSBpV
VaOh8g9drb3+qOI8UY6dYSOyAO1kYCouIy2g16lS7ZdbSbh39tqcI5EiqNUlOVmr
YD6TSVTp1qIM5wO9xUInkwKBgD6H4vI6GR25NaOpAAcFqXaN39jCbEPfE6YBcgjV
UijvXYx2nipAAFnExogTLLsV9sG6uQjbnrFtQDNNSnC7h4EtbKNIZRFczSlr/r4M
QuhvM2hA5OQyxSesoXRcOZAlrVsA+d5jK3Qy90YQCZMf7U7QSms+lyhquDTSYslx
5OedAoGBAI/6DX5lNUNBcMNpVr/VnS4/A87Vj9vKW2kfTUNehbfSC1ix8oAdlsJF
UfzdH4KOLP80tOUn1L7d4agxqZ+SWomLZ/RVfiMhaiVxQLH+xTbNFObrvePnAXy/
1Bu/wbF4TGlPfcugYecRV1MhKV0uGRD/OQCqRQBUENJ7zMdCGstl
-----END RSA PRIVATE KEY-----
+45 -11
View File
@@ -27,29 +27,63 @@ http {
server {
listen 80;
server_name "shuffler.io";
return 301 https://$server_name$request_uri;
server_name "localhost";
location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
}
server {
listen 443 ssl;
server_name "shuffler.io";
server_name "localhost";
ssl_certificate fullchain.cert.pem;
ssl_certificate_key privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
# Get the hostname from environment here?
location /api/v1 {
proxy_pass http://192.168.239.142:5001;
proxy_pass http://shuffle-backend:5001;
}
}
}
-89
View File
@@ -1,89 +0,0 @@
user nobody nogroup;
worker_processes auto; # auto-detect number of logical CPU cores
events {
worker_connections 512; # set the max number of simultaneous connections (per worker process)
}
http {
client_max_body_size 250M;
include mime.types;
# thanks stackoverflow http://stackoverflow.com/a/5132440/2406040
gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
# make sure gzip does not lose large gzipped js or css files
# see http://blog.leetsoft.com/2007/07/25/nginx-gzip-ssl.html
gzip_buffers 16 8k;
# Disable gzip for certain browsers.
gzip_disable “MSIE [1-6].(?!.*SV1)”;
server {
listen 80;
server_name "localhost";
location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
}
server {
listen 443 ssl;
server_name "localhost";
ssl_certificate fullchain.cert.pem;
ssl_certificate_key privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
# Get the hostname from environment here?
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ echo "Starting server"
# Rerun build locally for it to update :)
docker run -it \
-p 3001:80 \
-p 3443:443 \
-p 3002:443 \
-v $(pwd)/build:/usr/share/nginx/html:ro \
--rm \
nginx
+1 -1
View File
@@ -141,7 +141,7 @@ const AdminAccount = props => {
const basedata =
<div style={bodyDivStyle}>
<Paper style={boxStyle}>
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}>
<form onSubmit={onSubmit} style={{color: "white", margin: "15px 15px 15px 15px"}}>
<h2>{formtitle}</h2>
Username
<div>
+131 -64
View File
@@ -90,8 +90,8 @@ const AngularWorkflow = (props) => {
const [cystyle, ] = useState(cytoscapestyle)
const [cy, setCy] = React.useState()
const [appSearch, setAppSearch] = React.useState("")
const [currentView, setCurrentView] = React.useState("apps")
const [, setAppSearchValue] = React.useState("")
const [triggerAuthentication, setTriggerAuthentication] = React.useState({})
const [triggerFolders, setTriggerFolders] = React.useState([])
@@ -1385,10 +1385,6 @@ const AngularWorkflow = (props) => {
});
}
const setAppSearch = (event) => {
setFilteredApps(apps.filter(app => app.name.includes(event.target.value)))
}
const appViewStyle = {
marginLeft: "5px",
marginRight: "5px",
@@ -1525,10 +1521,10 @@ const AngularWorkflow = (props) => {
<MoreVertIcon />
</IconButton>
<Menu
id="long-menu"
anchorEl={anchorEl}
keepMounted
open={open}
id="long-menu"
anchorEl={anchorEl}
keepMounted
open={open}
PaperProps={{
style: {
backgroundColor: surfaceColor,
@@ -1568,6 +1564,7 @@ const AngularWorkflow = (props) => {
}
const HandleLeftView = () => {
// Defaults to apps.
var thisview = <AppView />
if (currentView === "triggers") {
thisview = <TriggersView />
@@ -1577,14 +1574,6 @@ const AngularWorkflow = (props) => {
return(
<div>
<div style={{cursor: "pointer", height: 20, marginLeft: 10, marginTop: 10}} onClick={() => {
setLeftViewOpen(false)
setLeftBarSize(50)
}}>
<Tooltip color="primary" title="Minimize" placement="top">
<KeyboardArrowLeftIcon />
</Tooltip>
</div>
<Divider style={{marginTop: 10, height: 1, width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
<div style={{minHeight: bodyHeight-appBarSize-150, maxHeight: bodyHeight-appBarSize-100}}>
{thisview}
@@ -1981,11 +1970,36 @@ const AngularWorkflow = (props) => {
overflowX: "hidden",
}
const runAppSearch = (event) => {
setAppSearch(event.target.value)
setFilteredApps(apps.filter(app => app.name.toLowerCase().includes(event.target.value.trim().toLowerCase())))
}
const AppView = () => {
return(
<div style={appViewStyle}>
<div style={{flex: "1"}}>
<div style={appScrollStyle}>
{/*
<TextField
style={{backgroundColor: inputColor}}
InputProps={{
style:{
color: "white",
minHeight: "50px",
marginLeft: "5px",
maxWidth: "95%",
fontSize: "1em",
},
}}
fullWidth
color="primary"
placeholder={"Search apps"}
onChange={(event) => {
runAppSearch(event)
}}
/>
*/}
{filteredApps.map(app=> {
// FIXME - add label to apps, as this might be slow with A LOT of apps
var newAppname = app.name
@@ -2299,7 +2313,7 @@ const AngularWorkflow = (props) => {
try {
JSON.parse(event.target.value)
} catch (e) {
alert.error("Failed to parse json")
alert.error("Failed to parse json: ", e)
}
}
}}
@@ -2324,10 +2338,15 @@ const AngularWorkflow = (props) => {
<div>
<Select
PaperProps={{
style: {
backgroundColor: inputColor,
}
}}
style: {
backgroundColor: inputColor,
}
}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
value={selectedActionParameters[count].action_field}
fullWidth
onChange={(e) => {
@@ -2378,10 +2397,15 @@ const AngularWorkflow = (props) => {
datafield =
<Select
PaperProps={{
style: {
backgroundColor: inputColor,
}
}}
style: {
backgroundColor: inputColor,
}
}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
fullWidth
value={selectedAction.parameters[count].action_field}
onChange={(e) => {
@@ -2537,6 +2561,11 @@ const AngularWorkflow = (props) => {
backgroundColor: inputColor,
}
}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
fullWidth
onChange={(e) => {
const env = environments.find(a => a.Name === e.target.value)
@@ -2572,6 +2601,11 @@ const AngularWorkflow = (props) => {
fullWidth
onChange={setNewSelectedAction}
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
>
{selectedApp.actions.map(data => {
var newActionname = data.name
@@ -2806,18 +2840,23 @@ const AngularWorkflow = (props) => {
datafield =
<div>
<Select
value={data.action_field}
fullWidth
onChange={(e) => {
changeActionVariable(e.target.value, data.value)
}}
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
>
{parents.map(data => (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.label}>
{data.label}
</MenuItem>
))}
value={data.action_field}
fullWidth
onChange={(e) => {
changeActionVariable(e.target.value, data.value)
}}
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
>
{parents.map(data => (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.label}>
{data.label}
</MenuItem>
))}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
</Select>
<TextField
style={{backgroundColor: inputColor}}
@@ -2858,11 +2897,16 @@ const AngularWorkflow = (props) => {
<Select
fullWidth
value={data.action_field}
PaperProps={{
style: {
backgroundColor: inputColor,
}
}}
PaperProps={{
style: {
backgroundColor: inputColor,
}
}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
onChange={(e) => {
changeActionVariable(e.target.value, data.value)
}}
@@ -2939,23 +2983,32 @@ const AngularWorkflow = (props) => {
<div style={{flex: "10"}}>
<b>{data.name} </b>
</div>
<div style={{cursor: "pointer", color: staticcolor}} onClick={() => {
changeActionParameterVariant("STATIC_VALUE")
<Tooltip color="primary" title="Static data" placement="top">
<div style={{cursor: "pointer", color: staticcolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("STATIC_VALUE")
}}>
<CreateIcon />
</div>
</Tooltip>
&nbsp;|&nbsp;
<Tooltip color="primary" title="Data from previous action" placement="top">
<div style={{cursor: "pointer", color: actioncolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("ACTION_RESULT")
}}>
static
</div>
<AppsIcon />
</div>
</Tooltip>
&nbsp;|&nbsp;
<div style={{cursor: "pointer", color: actioncolor}} onClick={() => {
changeActionParameterVariant("ACTION_RESULT")
}}>
action
</div>
&nbsp;|&nbsp;
<div style={{cursor: "pointer", color: varcolor}} onClick={() => {
changeActionParameterVariant("WORKFLOW_VARIABLE")
}}>
var
</div>
<Tooltip color="primary" title="Use local variable" placement="top">
<div style={{cursor: "pointer", color: varcolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("WORKFLOW_VARIABLE")
}}>
<FavoriteBorderIcon />
</div>
</Tooltip>
</div>
{datafield}
</div>
@@ -3091,8 +3144,16 @@ const AngularWorkflow = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null);
const deleteCondition = (conditionIndex) => {
//selectedEdge.conditions.splice(conditionIndex, 1)
//setSelectedEdge(selectedEdge)
console.log(selectedEdge)
if (selectedEdge.conditions.length === 1) {
selectedEdge.conditions = []
} else {
selectedEdge.conditions.splice(conditionIndex, 1)
}
setSelectedEdge(selectedEdge)
setOpen(false)
setUpdate("delete "+conditionIndex)
}
const paperVariableStyle = {
@@ -3108,6 +3169,7 @@ const AngularWorkflow = (props) => {
}
const menuClick = (event) => {
console.log("MENU CLICK")
setOpen(!open)
setAnchorEl(event.currentTarget);
}
@@ -3350,11 +3412,16 @@ const AngularWorkflow = (props) => {
value={selectedTrigger.parameters[0].value.split(splitter)}
style={{backgroundColor: inputColor, color: "white"}}
PaperProps={{
style: {
style: {
height: "200px",
backgroundColor: inputColor,
}
}}
backgroundColor: inputColor,
}
}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
onChange={(e) => {
//setTriggerFolderWrapper(e)
setTriggerFolderWrapperMulti(e)
+4 -4
View File
@@ -52,10 +52,10 @@ const theme = createMuiTheme({
palette: {
primary: {
main: "#f85a3e"
},
secondary: {
main: '#e8eaf6',
},
},
secondary: {
main: '#e8eaf6',
},
},
typography: {
useNextVariants: true
+12 -15
View File
@@ -35,6 +35,7 @@ const actionListStyle = {
marginTop: "5px",
backgroundColor: inputColor,
display: "flex",
color: "white",
}
const boxStyle = {
@@ -1013,7 +1014,7 @@ const AppCreator = (props) => {
</Dialog>
const actionView =
<div>
<div style={{color: "white"}}>
<h2>Actions</h2>
Actions are the tasks performed by an app. Read more about actions and apps
<a href="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</a>.
@@ -1038,7 +1039,7 @@ const AppCreator = (props) => {
</div>
const testView =
<div>
<div style={{color: "white"}}>
<h2>Test</h2>
Test an action to see whether it performs in an expected way.
<a href="/docs/apps#testing" style={{textDecoration: "none", color: "#f85a3e"}}>&nbsp;Click here to learn more about testing</a>.
@@ -1087,18 +1088,18 @@ const AppCreator = (props) => {
// Random names for type & autoComplete. Didn't research :^)
const landingpageDataBrowser =
<div style={{paddingBottom: "100px"}}>
<div style={{paddingBottom: 100, color: "white",}}>
<Paper style={boxStyle}>
<h2 style={{marginBottom: "10px"}}>General information</h2>
<h2 style={{marginBottom: "10px", color: "white"}}>General information</h2>
<a href="/docs/apps#create" style={{textDecoration: "none", color: "#f85a3e"}}>Click here to learn more about app creation</a>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<div style={{color: "white", flex: "1", display: "flex", flexDirection: "row"}}>
<Tooltip title="Click to edit the app's image" placement="bottom">
<div style={{flex: "1", margin: 10, border: "1px solid #f85a3e", cursor: "pointer", backgroundColor: inputColor, maxWidth: 174, maxHeight: 174}} onClick={() => {upload.click()}}>
<input hidden type="file" ref={(ref) => upload = ref} onChange={editHeaderImage} />
{imageInfo}
</div>
</Tooltip>
<div style={{flex: "3"}}>
<div style={{flex: "3", color: "white",}}>
<div style={{marginTop: "10px"}}/>
Name
<TextField
@@ -1149,8 +1150,8 @@ const AppCreator = (props) => {
</div>
</div>
<Divider style={{marginBottom: "10px", marginTop: "30px", height: "1px", width: "100%", backgroundColor: "grey"}}/>
<h3 style={{marginBottom: "10px"}}>API information</h3>
Base URL - leave empty if user changeable
<h3 style={{marginBottom: "10px", color: "white",}}>API information</h3>
<span style={{color: "white"}}>Base URL - leave empty if user changeable</span>
<TextField
color="primary"
style={{backgroundColor: inputColor, marginTop: "5px"}}
@@ -1176,7 +1177,7 @@ const AppCreator = (props) => {
onChange={e => setBaseUrl(e.target.value)}
/>
<FormControl style={{marginTop: "15px",}} variant="outlined">
<h5 style={{marginBottom: "10px"}}>Authentication</h5>
<h5 style={{marginBottom: "10px", color: "white",}}>Authentication</h5>
<Select
fullWidth
onChange={(e) => {
@@ -1213,12 +1214,8 @@ const AppCreator = (props) => {
const loadedCheck = isLoaded && isAppLoaded && !firstrequest ?
<div>
<BrowserView>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
{newActionModal}
</BrowserView>
<MobileView>
</MobileView>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
{newActionModal}
</div>
:
<div>
+271 -53
View File
@@ -3,13 +3,16 @@ import React, { useEffect} from 'react';
import { useInterval } from 'react-powerhooks';
import Grid from '@material-ui/core/Grid';
import Select from '@material-ui/core/Select';
import Paper from '@material-ui/core/Paper';
import Divider from '@material-ui/core/Divider';
import ButtonBase from '@material-ui/core/ButtonBase';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import FormControl from '@material-ui/core/FormControl';
import MenuItem from '@material-ui/core/MenuItem';
import Tooltip from '@material-ui/core/Tooltip';
import Input from '@material-ui/core/Input';
import YAML from 'yaml'
import {Link} from 'react-router-dom';
@@ -30,6 +33,7 @@ const Apps = (props) => {
const { globalUrl, isLoggedIn, isLoaded } = props;
//const [workflows, setWorkflows] = React.useState([]);
const baseRepository = "https://github.com/frikky/shuffle-apps"
const alert = useAlert()
const [selectedApp, setSelectedApp] = React.useState({});
const [firstrequest, setFirstrequest] = React.useState(true)
@@ -37,13 +41,19 @@ const Apps = (props) => {
const [filteredApps, setFilteredApps] = React.useState([])
const [validation, setValidation] = React.useState(false)
const [isLoading, setIsLoading] = React.useState(false)
const [appSearchLoading, setAppSearchLoading] = React.useState(false)
const [selectedAction, setSelectedAction] = React.useState({})
const [openApi, setOpenApi] = React.useState("")
const [openApiData, setOpenApiData] = React.useState("")
const [appValidation, setAppValidation] = React.useState("")
const [loadAppsModalOpen, setLoadAppsModalOpen] = React.useState(false);
const [openApiModal, setOpenApiModal] = React.useState(false);
const [openApiModalType, setOpenApiModalType] = React.useState("");
const [openApiError, setOpenApiError] = React.useState("")
const [field1, setField1] = React.useState("")
const [field2, setField2] = React.useState("")
const { start, stop } = useInterval({
duration: 5000,
startImmediate: false,
@@ -69,6 +79,7 @@ const Apps = (props) => {
color: "#ffffff",
width: "100%",
display: "flex",
margin: 20,
}
const paperAppStyle = {
@@ -103,8 +114,11 @@ const Apps = (props) => {
setFilteredApps(responseJson)
if (responseJson.length > 0) {
setSelectedApp(responseJson[0])
if (responseJson[0].actions.length > 0) {
setSelectedAction(responseJson[0].actions[0])
}
}
})
})
.catch(error => {
alert.error(error.toString())
});
@@ -205,6 +219,10 @@ const Apps = (props) => {
<Paper square style={paperAppStyle} onClick={() => {
if (selectedApp.id !== data.id) {
setSelectedApp(data)
if (data.actions.length > 0) {
console.log(data.actions[0])
setSelectedAction(data.actions[0])
}
}
}}>
<Grid container style={{margin: 10, flex: "10"}}>
@@ -231,9 +249,11 @@ const Apps = (props) => {
</Grid>
</Grid>
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}} onClick={() => {downloadApp(data)}}>
{/*
<Tooltip title={"Download"} style={{marginTop: "28px", width: "100%"}} aria-label={data.name}>
<CloudDownload />
</Tooltip>
*/}
</Grid>
</Paper>
)
@@ -249,33 +269,6 @@ const Apps = (props) => {
marginBottom: 10,
}
//const handleFile = (event) =>{
// const formData = new FormData();
// formData.append('file', event.target.files[0]);
// fetch(globalUrl+"/api/v1/workflows/apps/validate", {
// method: 'POST',
// headers: {
// 'Accept': 'application/json',
// },
// body: formData,
// credentials: "include",
// })
// .then((response) => {
// if (response.status !== 200) {
// console.log("Status not 200 for apps :O!")
// return
// }
// return response.json()
// })
// .then((responseJson) => {
// console.log(responseJson)
// })
// .catch(error => {
// alert.error(error.toString())
// });
//}
const UploadView = () => {
//var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ?
// <img alt="" style={{width: "80px"}} />
@@ -325,9 +318,65 @@ const Apps = (props) => {
<h2>{newAppname}</h2>
<p>{description}</p>
<Divider style={{marginBottom: "10px", marginTop: "10px", backgroundColor: dividerColor}}/>
<p>URL: {selectedApp.link}</p>
{selectedApp.link.length > 0 ? <p>URL: {selectedApp.link}</p> : null}
<p>ID: {selectedApp.id}</p>
<p>PrivateID: {selectedApp.privateId}</p>
{selectedApp.privateId !== undefined && selectedApp.privateId.length > 0 ? <p>PrivateID: {selectedApp.privateId}</p> : null}
<div style={{marginTop: 15, marginBottom: 15}}>
<b>Actions</b>
<Select
fullWidth
value={selectedAction}
onChange={(event) => {
setSelectedAction(event.target.value)
}}
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
>
{selectedApp.actions.map(data => {
var newActionname = data.label !== undefined && data.label.length > 0 ? data.label : data.name
// ROFL FIXME - loop
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
{newActionname}
</MenuItem>
)
})}
</Select>
</div>
{selectedAction.parameters !== undefined ?
<div style={{marginTop: 15, marginBottom: 15}}>
<b>Arguments</b>
{selectedAction.parameters.map(data => {
var itemColor = "#f85a3e"
if (!data.required) {
itemColor = "#ffeb3b"
}
const circleSize = 10
return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
<div style={{width: circleSize, height: circleSize, borderRadius: circleSize / 2, backgroundColor: itemColor, marginRight: "10px"}}/>
{data.name}
</MenuItem>
)
})}
</div>
: null}
{editButton}
{deleteButton}
</div>
@@ -338,11 +387,11 @@ const Apps = (props) => {
<div>
<Paper square style={uploadViewPaperStyle}>
<div style={{width: "100%", margin: 25}}>
<h2>App creation</h2>
<Link to="/docs/apps" style={{textDecoration: "none", color: "#f85a3e"}}>What are apps?</Link>
&nbsp;- <a href="https://swagger.io/specification/" style={{textDecoration: "none", color: "#f85a3e"}}>OpenAPI specification</a>
<h2>App Creator</h2>
<a href="https://github.com/frikky/OpenAPI-security-definitions" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">Security API's</a>
&nbsp;- <a href="https://apis.guru/browse-apis/" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">OpenAPI directory</a>
<div/>
Apps are how you interact with workflows, and are used to execute workflows. They are created with the app creator, using OpenAPI specification or manually in python.
Apps interact with eachother in workflows. They are created with the app creator, using OpenAPI specification or manually in python. Use the links above to find potential apps you're looking for using OpenAPI or make one from scratch. There's 1000+ available.
<div/>
<div style={{marginTop: 20}}>
<Button
@@ -381,34 +430,54 @@ const Apps = (props) => {
const handleSearchChange = (event) => {
const searchfield = event.target.value.toLowerCase()
const newapps = apps.filter(data => data.name.toLowerCase().includes(searchfield) || data.description.toLowerCase().includes(searchfield))
setFilteredApps(newapps)
if (newapps.length === 0 && !appSearchLoading) {
setAppSearchLoading(true)
runAppSearch(searchfield)
} else {
setFilteredApps(newapps)
}
}
const appView = isLoggedIn ?
<div style={{width: 1366, margin: "auto"}}>
<div style={{maxWidth: 1366, margin: "auto",}}>
<div style={appViewStyle}>
<div style={{flex: "1", marginLeft: "10px", marginRight: "10px"}}>
<div style={{flex: "1", marginLeft: 10, marginRight: 10}}>
<h2>Upload</h2>
<div style={{marginTop: 20}}/>
<UploadView />
</div>
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "100%", width: "1px", backgroundColor: dividerColor}}/>
<div style={{flex: 1, marginLeft: "10px", marginRight: "10px"}}>
<div style={{flex: 1, marginLeft: 10, marginRight: 10}}>
<div style={{display: "flex"}}>
<div style={{flex: 10}}>
<h2>Available integrations</h2>
</div>
{isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null}
{/*
<Button
variant="contained"
variant="outlined"
component="label"
color="primary"
style={{maxHeight: 50, marginTop: 10}}
style={{margin: 5, maxHeight: 50, marginTop: 10}}
onClick={() => {
getExistingApps()
getSpecificApps(baseRepository)
}}
>
Load existing apps
Load apps
</Button>
*/}
<Button
variant="outlined"
component="label"
color="primary"
style={{margin: 5, maxHeight: 50, marginTop: 10}}
onClick={() => {
setOpenApi(baseRepository)
setLoadAppsModalOpen(true)
}}
>
Download from URL
</Button>
</div>
<TextField
@@ -432,7 +501,7 @@ const Apps = (props) => {
<div style={{marginTop: 15}}>
{apps.length > 0 ?
filteredApps.length > 0 ?
<div style={{maxHeight: "80vh", overflowY: "scroll"}}>
<div style={{maxHeight: "78vh", overflowY: "scroll"}}>
{filteredApps.map(app => {
return (
appPaper(app)
@@ -444,6 +513,12 @@ const Apps = (props) => {
<h4>
Try a broader search term. E.g. "http" or "TheHive"
</h4>
<div/>
{appSearchLoading ?
<CircularProgress color="primary" style={{margin: "auto"}}/>
: null
}
</Paper>
:
<Paper square style={uploadViewPaperStyle}>
@@ -459,28 +534,38 @@ const Apps = (props) => {
:
null
// Gets the URL itself (hopefully this works in most cases?
// Will then forward the data to an internal endpoint to validate the api
const getExistingApps = () => {
// Load data e.g. from github
const getSpecificApps = (url) => {
setValidation(true)
setIsLoading(true)
start()
alert.success("Downloading and building apps. Feel free to move around meanwhile.")
const parsedData = {
"url": url,
}
if (field1.length > 0) {
parsedData["field_1"] = field1
}
if (field2.length > 0) {
parsedData["field_2"] = field2
}
alert.success("Getting specific apps from your URL.")
var cors = "cors"
fetch(globalUrl+"/api/v1/apps/get_existing", {
method: "GET",
method: "POST",
mode: "cors",
headers: {
'Accept': 'application/json',
},
body: JSON.stringify(parsedData),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
alert.success("Failed loading.")
} else {
if (response.status === 200) {
response.text().then(function (text) {
console.log("RETURN: ", text)
alert.success("Loaded existing apps!")
@@ -488,6 +573,16 @@ const Apps = (props) => {
}
setIsLoading(false)
stop()
return response.json()
})
.then((responseJson) => {
console.log("DATA: ", responseJson)
if (responseJson.reason !== undefined) {
alert.error("Failed loading: "+responseJson.reason)
} else {
alert.error("Failed loading")
}
})
.catch(error => {
alert.error(error.toString())
@@ -540,6 +635,29 @@ const Apps = (props) => {
});
}
const runAppSearch = (searchterm) => {
const data = {"search": searchterm}
fetch(globalUrl+"/api/v1/apps/search", {
method: 'POST',
headers: {
'Accept': 'application/json',
},
body: JSON.stringify(data),
credentials: "include",
})
.then((response) => {
setAppSearchLoading(false)
return response.json()
})
.then((responseJson) => {
console.log(responseJson)
})
.catch(error => {
alert.error(error.toString())
});
}
const validateRemote = () => {
setValidation(true)
@@ -621,6 +739,105 @@ const Apps = (props) => {
window.location.href = "/apps/new?id="+appValidation
}
const handleGithubValidation = () => {
getSpecificApps(openApi)
setLoadAppsModalOpen(false)
}
const appsModalLoad = loadAppsModalOpen ?
<Dialog modal
open={loadAppsModalOpen}
onClose={() => {
setOpenApi("")
setLoadAppsModalOpen(false)
setField1("")
setField2("")
}}
PaperProps={{
style: {
backgroundColor: surfaceColor,
color: "white",
minWidth: "800px",
minHeight: "320px",
},
}}
>
<DialogTitle>
<div style={{color: "rgba(255,255,255,0.9)"}}>
Load from github repo
</div>
</DialogTitle>
<DialogContent style={{color: "rgba(255,255,255,0.65)"}}>
Repository (supported: github, gitlab, bitbucket)
<TextField
style={{backgroundColor: inputColor}}
variant="outlined"
margin="normal"
defaultValue="https://github.com/frikky/shuffle-apps"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setOpenApi(e.target.value)}
placeholder="https://github.com/frikky/shuffle-apps"
fullWidth
/>
<span style={{marginTop: 10}}>Authentication (optional - private repos etc):</span>
<div style={{display: "flex"}}>
<TextField
style={{flex: 1, backgroundColor: inputColor}}
variant="outlined"
margin="normal"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setField1(e.target.value)}
type="username"
placeholder="Username / APIkey (optional)"
fullWidth
/>
<TextField
style={{flex: 1, backgroundColor: inputColor}}
variant="outlined"
margin="normal"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setField2(e.target.value)}
type="password"
placeholder="Password (optional)"
fullWidth
/>
</div>
</DialogContent>
<DialogActions>
{circularLoader}
<Button style={{borderRadius: "0px"}} onClick={() => setLoadAppsModalOpen(false)} color="primary">
Cancel
</Button>
<Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
handleGithubValidation()
}} color="primary">
Submit
</Button>
</DialogActions>
</Dialog>
: null
const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null
const circularLoader = validation ? <CircularProgress color="primary" /> : null
const modalView = openApiModal ?
@@ -693,11 +910,11 @@ const Apps = (props) => {
<Button style={{borderRadius: "0px"}} onClick={() => setOpenApiModal(false)} color="primary">
Cancel
</Button>
<Button style={{borderRadius: "0px"}} disabled={appValidation.length === 0} onClick={() => {
<Button style={{borderRadius: "0px"}} disabled={appValidation.length === 0} onClick={() => {
redirectOpenApi()
}} color="primary">
Submit
</Button>
</Button>
</DialogActions>
</FormControl>
</Dialog>
@@ -708,6 +925,7 @@ const Apps = (props) => {
<div>
{appView}
{modalView}
{appsModalLoad}
</div>
:
<div>
+95 -23
View File
@@ -10,9 +10,9 @@ import MenuItem from '@material-ui/core/MenuItem';
import {Link} from 'react-router-dom';
const Body = {
maxWidth: '1000px',
minWidth: '768px',
margin: 'auto',
maxWidth: '1000px',
minWidth: '768px',
margin: 'auto',
display: "flex",
heigth: "100%",
color: "white",
@@ -32,7 +32,7 @@ const hrefStyle = {
}
const Docs = (props) => {
const { isLoaded, globalUrl } = props;
const { isLoaded, globalUrl } = props;
const [data, setData] = useState("");
const [firstrequest, setFirstrequest] = useState(true);
@@ -52,19 +52,84 @@ const Docs = (props) => {
if (firstrequest) {
setFirstrequest(false)
fetchDocList()
fetchDocs()
fetchDocs(props.match.params.key)
return
}
// Continue this, and find the h2 with the data in it lol
if (window.location.hash.length > 0) {
console.log("HELLO")
var parent = document.getElementById("markdown_wrapper")
if (parent !== null) {
var elements = parent.getElementsByTagName('h2')
const name = window.location.hash.slice(1, window.location.hash.lenth).toLowerCase().split("%20").join(" ").split("_").join(" ")
console.log(name)
var found = false
for (var key in elements) {
const element = elements[key]
if (element.innerHTML === undefined) {
continue
}
// Fix location..
if (element.innerHTML.toLowerCase() === name) {
element.scrollIntoView({behavior: "smooth"})
found = true
//element.scrollTo({
// top: element.offsetTop-100,
// behavior: "smooth"
//})
}
}
// H#
if (!found) {
var elements = parent.getElementsByTagName('h3')
console.log(name)
var found = false
for (var key in elements) {
const element = elements[key]
if (element.innerHTML === undefined) {
continue
}
// Fix location..
if (element.innerHTML.toLowerCase() === name) {
element.scrollIntoView({behavior: "smooth"})
found = true
//element.scrollTo({
// top: element.offsetTop-100,
// behavior: "smooth"
//})
}
}
}
}
//console.log(element)
//console.log("NAME: ", name)
//console.log(document.body.innerHTML)
// parent = document.getElementById(parent);
//var descendants = parent.getElementsByTagName(tagname);
// this.scrollDiv.current.scrollIntoView({ behavior: 'smooth' });
//$(".parent").find("h2:contains('Statistics')").parent();
}
})
const fetchDocList = () => {
fetch(globalUrl+"/api/v1/docs", {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
})
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
})
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.success) {
@@ -77,8 +142,8 @@ const Docs = (props) => {
.catch(error => {});
}
const fetchDocs = () => {
fetch(globalUrl+"/api/v1/docs/"+props.match.params.key, {
const fetchDocs = (docId) => {
fetch(globalUrl+"/api/v1/docs/"+docId, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@@ -99,10 +164,15 @@ const Docs = (props) => {
const markdownStyle = {
color: "rgba(255, 255, 255, 0.65)",
flex: "1",
maxWidth: 750,
overflow: "hidden",
}
function Link(props) {
return <a href={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</a>
function OuterLink(props) {
if (props.href.includes("http") || props.href.includes("mailto")) {
return <a href={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</a>
}
return <Link to={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</Link>
}
function Img(props) {
@@ -117,7 +187,7 @@ const Docs = (props) => {
// );
//}
const postDataBrowser =
const postDataBrowser =
<div style={Body}>
<div style={SideBar}>
<ul style={{listStyle: "none", paddingLeft: "0"}}>
@@ -128,22 +198,23 @@ const Docs = (props) => {
</li>
{list.map(item => {
const path = "/docs/"+item
const newname = item.charAt(0).toUpperCase()+item.substring(1)
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ")
return (
<li style={{marginTop: "10px"}}>
<a style={hrefStyle} href={path}>
<Link style={hrefStyle} to={path} onClick={() => {fetchDocs(item)}}>
<h2>{newname}</h2>
</a>
</Link>
</li>
)
})}
</ul>
</div>
<div style={markdownStyle}>
<div id="markdown_wrapper" style={markdownStyle}>
<ReactMarkdown
id="markdown_wrapper"
escapeHtml={false}
source={data}
renderers={{link: Link, image: Img}}
renderers={{link: OuterLink, image: Img}}
/>
</div>
</div>
@@ -172,7 +243,7 @@ const Docs = (props) => {
>
{list.map(item => {
const path = "/docs/"+item
const newname = item.charAt(0).toUpperCase()+item.substring(1)
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ")
return (
<MenuItem onClick={() => {window.location.pathname = path}}>{newname}</MenuItem>
)
@@ -180,9 +251,10 @@ const Docs = (props) => {
</Menu>
<div style={markdownStyle}>
<ReactMarkdown
id="markdown_wrapper"
escapeHtml={false}
source={data}
renderers={{link: Link, image: Img}}
renderers={{link: OuterLink, image: Img}}
/>
</div>
<Divider style={{marginTop: "10px", marginBottom: "10px", backgroundColor: dividerColor}}/>
+1 -1
View File
@@ -172,7 +172,7 @@ const LoginDialog = props => {
const basedata =
<div style={bodyDivStyle}>
<Paper style={boxStyle}>
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}>
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px", color: "white",}}>
<h2>{formtitle}</h2>
Username
<div>
+35 -7
View File
@@ -19,6 +19,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
network "github.com/docker/docker/api/types/network"
dockerclient "github.com/docker/docker/client"
//network "github.com/docker/docker/api/types/network"
//natting "github.com/docker/go-connections/nat"
@@ -26,6 +27,7 @@ import (
var baseUrl = os.Getenv("BASE_URL")
var baseimagename = "frikky/shuffle"
var dockerApiVersion = os.Getenv("DOCKER_API_VERSION")
var environment = os.Getenv("ENVIRONMENT_NAME")
var orgId = os.Getenv("ORG_ID")
@@ -67,14 +69,32 @@ func deployWorker(cli *dockerclient.Client, image string, identifier string, env
Image: image,
Env: env,
}
//Volumes: map[string]struct{}{
// "/var/run/docker.sock": {},
//},
// Set the network
networkConfig := &network.NetworkingConfig{}
if baseUrl == "http://shuffle-backend:5001" {
networkConfig = &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
"shuffle_shuffle": {
NetworkID: "shuffle_shuffle",
},
},
}
} else {
//log.Printf("Bad config: %s. Using default.", baseUrl)
}
//test := &network.EndpointSettings{
// Gateway: "helo",
//}
//NetworkID
//if connect.EndpointConfig.NetworkID != "NetworkID" {
cont, err := cli.ContainerCreate(
context.Background(),
config,
hostConfig,
networkConfig,
nil,
identifier,
)
@@ -84,8 +104,12 @@ func deployWorker(cli *dockerclient.Client, image string, identifier string, env
return err
}
cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
log.Printf("Container %s is created", cont.ID)
err = cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
if err != nil {
log.Printf("Failed to start container: %s", err)
} else {
log.Printf("Container %s is created", cont.ID)
}
return nil
}
@@ -283,11 +307,14 @@ func main() {
env := []string{
fmt.Sprintf("AUTHORIZATION=%s", execution.Authorization),
fmt.Sprintf("EXECUTIONID=%s", execution.ExecutionId),
fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion),
fmt.Sprintf("ENVIRONMENT_NAME=%s", environment),
fmt.Sprintf("BASE_URL=%s", baseUrl),
}
if dockerApiVersion != "" {
env = append(env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
}
err = deployWorker(dockercli, workerImage, containerName, env)
if err != nil {
stats, err := dockercli.ContainerInspect(context.Background(), containerName)
@@ -360,7 +387,8 @@ func main() {
continue
}
log.Println(string(body))
_ = body
//log.Println(string(body))
// FIXME - remove these
//log.Println(string(body))
+4 -1
View File
@@ -1,5 +1,8 @@
docker run \
--env ORG_ID=$ORG_ID \
--env BASE_URL=$BASE_URL \
--env ENVIRONMENT_NAME="Shuffle" \
--env BASE_URL=http://shuffle-backend:5001 \
--env DOCKER_API_VERSION=1.42 \
--network "shuffle_shuffle" \
-v /var/run/docker.sock:/var/run/docker.sock \
frikky/shuffle:orborus
Binary file not shown.
+17 -1
View File
@@ -16,6 +16,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
network "github.com/docker/docker/api/types/network"
dockerclient "github.com/docker/docker/client"
)
@@ -284,10 +285,24 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env []
Env: env,
}
networkConfig := &network.NetworkingConfig{}
if baseUrl == "http://shuffle-backend:5001" {
networkConfig = &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
"shuffle_shuffle": {
NetworkID: "shuffle_shuffle",
},
},
}
} else {
log.Printf("Bad config: %s. Using default network", baseUrl)
}
cont, err := cli.ContainerCreate(
context.Background(),
config,
hostConfig,
networkConfig,
nil,
identifier,
)
@@ -375,6 +390,7 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W
children[branch.SourceID] = append(children[branch.SourceID], branch.DestinationID)
}
log.Printf("Actions: %d", len(workflowExecution.Workflow.Actions))
for _, action := range workflowExecution.Workflow.Actions {
if action.Environment != environment {
continue
@@ -395,7 +411,7 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W
}
if len(onpremApps) == 0 {
return errors.New("No apps to handle onprem")
return errors.New(fmt.Sprintf("No apps to handle onprem (%s)", environment))
}
pullOptions := types.ImagePullOptions{}