Made automatic downloads of public OpenAPI apps build by themselves
This commit is contained in:
@@ -3,13 +3,16 @@ package main
|
||||
// Docker
|
||||
import (
|
||||
"archive/tar"
|
||||
|
||||
"github.com/shuffle/shuffle-shared"
|
||||
|
||||
//"bufio"
|
||||
"path/filepath"
|
||||
//"strconv"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -756,7 +759,7 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
tagFound = version.Name
|
||||
}
|
||||
|
||||
buildSwaggerApp(resp, []byte(openApiApp.Body), user)
|
||||
buildSwaggerApp(resp, []byte(openApiApp.Body), user, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -802,6 +805,92 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
//resp.WriteHeader(200)
|
||||
}
|
||||
|
||||
// Downloads and activates an app from shuffler.io if possible
|
||||
func handleRemoteDownloadApp(resp http.ResponseWriter, ctx context.Context, user shuffle.User, appId string) {
|
||||
url := fmt.Sprintf("https://shuffler.io/api/v1/apps/%s/config", appId)
|
||||
log.Printf("Downloading API from %s", url)
|
||||
req, err := http.NewRequest(
|
||||
"GET",
|
||||
url,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed auto-downloading app %s: %s", appId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
httpClient := &http.Client{}
|
||||
newresp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed running auto-download request for %s: %s", appId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
respBody, err := ioutil.ReadAll(newresp.Body)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed setting respbody for workflow download: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
if len(respBody) > 0 {
|
||||
type tmpapp struct {
|
||||
Success bool `json:"success"`
|
||||
OpenAPI string `json:"openapi"`
|
||||
}
|
||||
|
||||
app := tmpapp{}
|
||||
err := json.Unmarshal(respBody, &app)
|
||||
if err != nil || app.Success == false || len(app.OpenAPI) == 0 {
|
||||
log.Printf("[ERROR] Failed app unmarshal during auto-download. Success%#v. Applength: %d: %s", app.Success, len(app.OpenAPI), err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
key, err := base64.StdEncoding.DecodeString(app.OpenAPI)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed auto-setting OpenAPI app: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("workflowapps-sorted-100")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-1000")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
|
||||
newapp := shuffle.ParsedOpenApi{}
|
||||
err = json.Unmarshal(key, &newapp)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed openapi unmarshal during auto-download: %s", app.Success, len(app.OpenAPI), err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(key, &newapp)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed openapi unmarshal during auto-download: %s", app.Success, len(app.OpenAPI), err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
return
|
||||
}
|
||||
|
||||
buildSwaggerApp(resp, []byte(newapp.Body), user, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func activateWorkflowAppDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := shuffle.HandleCors(resp, request)
|
||||
if cors {
|
||||
@@ -845,9 +934,9 @@ func activateWorkflowAppDocker(resp http.ResponseWriter, request *http.Request)
|
||||
apps, err := shuffle.FindWorkflowAppByName(ctx, appName)
|
||||
//log.Printf("[INFO] Found %d apps for %s", len(apps), appName)
|
||||
if err != nil || len(apps) == 0 {
|
||||
log.Printf("[WARNING] Error getting app %s (app config): %s", appName, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
log.Printf("[WARNING] Error getting app %s (app config). Starting remote download.: %s", appName, err)
|
||||
|
||||
handleRemoteDownloadApp(resp, ctx, user, fileId)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -868,10 +957,12 @@ func activateWorkflowAppDocker(resp http.ResponseWriter, request *http.Request)
|
||||
|
||||
app = &selectedApp
|
||||
} else {
|
||||
log.Printf("[WARNING] Error getting app with ID %s (app config): %s", fileId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
log.Printf("[WARNING] Error getting app with ID %s (app config): %s. Starting remote download(2)", fileId, err)
|
||||
handleRemoteDownloadApp(resp, ctx, user, fileId)
|
||||
return
|
||||
//resp.WriteHeader(401)
|
||||
//resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||
//return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -3153,18 +3153,19 @@ func handleSwaggerValidation(body []byte) (shuffle.ParsedOpenApi, error) {
|
||||
return parsed, err
|
||||
}
|
||||
|
||||
func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
||||
func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User, skipEdit bool) {
|
||||
type Test struct {
|
||||
Editing bool `datastore:"editing"`
|
||||
Id string `datastore:"id"`
|
||||
Image string `datastore:"image"`
|
||||
Editing bool `json:"editing" datastore:"editing"`
|
||||
Id string `json:"id" datastore:"id"`
|
||||
Image string `json:"image" datastore:"image"`
|
||||
Body string `json:"body" datastore:"body"`
|
||||
}
|
||||
|
||||
var test Test
|
||||
err := json.Unmarshal(body, &test)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed unmarshalling test: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
log.Printf("[ERROR] Failed unmarshalling in swagger build: %s", err)
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
@@ -3174,13 +3175,13 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
||||
hasher.Write(body)
|
||||
newmd5 := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
if test.Editing && len(user.Id) > 0 {
|
||||
if test.Editing && len(user.Id) > 0 && skipEdit != true {
|
||||
// Quick verification test
|
||||
ctx := context.Background()
|
||||
app, err := shuffle.GetApp(ctx, test.Id, user, false)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error getting app when editing: %s", app.Name)
|
||||
resp.WriteHeader(401)
|
||||
log.Printf("[ERROR] Error getting app when editing: %s", app.Name)
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
@@ -3188,7 +3189,7 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
||||
// FIXME: Check whether it's in use.
|
||||
if user.Id != app.Owner && user.Role != "admin" {
|
||||
log.Printf("[WARNING] Wrong user (%s) for app %s when verifying swagger", user.Username, app.Name)
|
||||
resp.WriteHeader(401)
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
@@ -3212,7 +3213,7 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
||||
}
|
||||
|
||||
if swagger.Info == nil {
|
||||
log.Printf("[ERORR] Info is nil?: %#v", swagger)
|
||||
log.Printf("[ERORR] Info is nil in swagger?")
|
||||
resp.WriteHeader(500)
|
||||
resp.Write([]byte(`{"success": false, "reason": "Info not parsed"}`))
|
||||
return
|
||||
@@ -3322,7 +3323,7 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
||||
//log.Println(stitched)
|
||||
|
||||
// 3. Zip and stream it directly in the directory
|
||||
_, err = shuffle.StreamZipdata(ctx, identifier, stitched, "requests\nurllib3", "")
|
||||
_, err = shuffle.StreamZipdata(ctx, identifier, stitched, shuffle.GetAppRequirements(), "")
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Zipfile error: %s", err)
|
||||
resp.WriteHeader(500)
|
||||
@@ -3473,7 +3474,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
buildSwaggerApp(resp, body, user)
|
||||
buildSwaggerApp(resp, body, user, false)
|
||||
}
|
||||
|
||||
// Creates osfs from folderpath with a basepath as directory base
|
||||
@@ -3544,7 +3545,6 @@ func handleAppHotload(ctx context.Context, location string, forceUpdate bool) er
|
||||
return err
|
||||
}
|
||||
|
||||
//log.Printf("Reading app folder: %#v", dir)
|
||||
_, _, err = IterateAppGithubFolders(ctx, fs, dir, "", "", forceUpdate)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Githubfolders error: %s", err)
|
||||
|
||||
Reference in New Issue
Block a user