3
0

Bundle code serving

This commit is contained in:
Denis Arh
2020-01-22 18:07:49 +01:00
parent b9cd860bf2
commit b89b1d1056
14 changed files with 359 additions and 0 deletions
+25
View File
@@ -1658,6 +1658,31 @@
]
}
},
{
"name": "bundle",
"method": "GET",
"title": "Serves client scripts bundle",
"path": "/{bundle}-{type}.{ext}",
"parameters": {
"path": [
{
"name": "bundle",
"type": "string",
"title": "Name of the bundle"
},
{
"name": "type",
"type": "string",
"title": "Bundle type"
},
{
"name": "ext",
"type": "string",
"title": "Bundle extension"
}
]
}
},
{
"name": "triggerScript",
"method": "POST",
+25
View File
@@ -47,6 +47,31 @@
]
}
},
{
"Name": "bundle",
"Method": "GET",
"Title": "Serves client scripts bundle",
"Path": "/{bundle}-{type}.{ext}",
"Parameters": {
"path": [
{
"name": "bundle",
"title": "Name of the bundle",
"type": "string"
},
{
"name": "type",
"title": "Bundle type",
"type": "string"
},
{
"name": "ext",
"title": "Bundle extension",
"type": "string"
}
]
}
},
{
"Name": "triggerScript",
"Method": "POST",
+25
View File
@@ -1727,6 +1727,31 @@
]
}
},
{
"name": "bundle",
"method": "GET",
"title": "Serves client scripts bundle",
"path": "/{bundle}-{type}.{ext}",
"parameters": {
"path": [
{
"name": "bundle",
"type": "string",
"title": "Name of the bundle"
},
{
"name": "type",
"type": "string",
"title": "Bundle type"
},
{
"name": "ext",
"type": "string",
"title": "Bundle extension"
}
]
}
},
{
"name": "triggerScript",
"method": "POST",
+25
View File
@@ -47,6 +47,31 @@
]
}
},
{
"Name": "bundle",
"Method": "GET",
"Title": "Serves client scripts bundle",
"Path": "/{bundle}-{type}.{ext}",
"Parameters": {
"path": [
{
"name": "bundle",
"title": "Name of the bundle",
"type": "string"
},
{
"name": "type",
"title": "Bundle type",
"type": "string"
},
{
"name": "ext",
"title": "Bundle extension",
"type": "string"
}
]
}
},
{
"Name": "triggerScript",
"Method": "POST",
+10
View File
@@ -37,6 +37,16 @@ func (ctrl *Automation) List(ctx context.Context, r *request.AutomationList) (in
)
}
func (ctrl *Automation) Bundle(ctx context.Context, r *request.AutomationBundle) (interface{}, error) {
return corredor.GenericBundleHandler(
ctx,
corredor.Service(),
r.Bundle,
r.Type,
r.Ext,
)
}
func (ctrl *Automation) TriggerScript(ctx context.Context, r *request.AutomationTriggerScript) (interface{}, error) {
return resputil.OK(), corredor.Service().ExecOnManual(ctx, r.Script, event.ComposeOnManual())
}
+23
View File
@@ -30,12 +30,14 @@ import (
// Internal API interface
type AutomationAPI interface {
List(context.Context, *request.AutomationList) (interface{}, error)
Bundle(context.Context, *request.AutomationBundle) (interface{}, error)
TriggerScript(context.Context, *request.AutomationTriggerScript) (interface{}, error)
}
// HTTP API interface
type Automation struct {
List func(http.ResponseWriter, *http.Request)
Bundle func(http.ResponseWriter, *http.Request)
TriggerScript func(http.ResponseWriter, *http.Request)
}
@@ -61,6 +63,26 @@ func NewAutomation(h AutomationAPI) *Automation {
resputil.JSON(w, value)
}
},
Bundle: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewAutomationBundle()
if err := params.Fill(r); err != nil {
logger.LogParamError("Automation.Bundle", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Bundle(r.Context(), params)
if err != nil {
logger.LogControllerError("Automation.Bundle", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Automation.Bundle", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
TriggerScript: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewAutomationTriggerScript()
@@ -88,6 +110,7 @@ func (h Automation) MountRoutes(r chi.Router, middlewares ...func(http.Handler)
r.Group(func(r chi.Router) {
r.Use(middlewares...)
r.Get("/automation/", h.List)
r.Get("/automation/{bundle}-{type}.{ext}", h.Bundle)
r.Post("/automation/trigger", h.TriggerScript)
})
}
+57
View File
@@ -117,6 +117,63 @@ func (r *AutomationList) Fill(req *http.Request) (err error) {
var _ RequestFiller = NewAutomationList()
// Automation bundle request parameters
type AutomationBundle struct {
Bundle string
Type string
Ext string
}
func NewAutomationBundle() *AutomationBundle {
return &AutomationBundle{}
}
func (r AutomationBundle) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["bundle"] = r.Bundle
out["type"] = r.Type
out["ext"] = r.Ext
return out
}
func (r *AutomationBundle) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.Bundle = chi.URLParam(req, "bundle")
r.Type = chi.URLParam(req, "type")
r.Ext = chi.URLParam(req, "ext")
return err
}
var _ RequestFiller = NewAutomationBundle()
// Automation triggerScript request parameters
type AutomationTriggerScript struct {
Script string
+19
View File
@@ -116,6 +116,7 @@
| Method | Endpoint | Purpose |
| ------ | -------- | ------- |
| `GET` | `/automation/` | List all available automation scripts for compose resources |
| `GET` | `/automation/{bundle}-{type}.{ext}` | Serves client scripts bundle |
| `POST` | `/automation/trigger` | Triggers execution of a specific script on a system service level |
## List all available automation scripts for compose resources
@@ -139,6 +140,24 @@ Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.cru
| excludeClientScripts | bool | GET | Do not include client scripts | N/A | NO |
| excludeServerScripts | bool | GET | Do not include server scripts | N/A | NO |
## Serves client scripts bundle
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| bundle | string | PATH | Name of the bundle | N/A | NO |
| type | string | PATH | Bundle type | N/A | NO |
| ext | string | PATH | Bundle extension | N/A | NO |
## Triggers execution of a specific script on a system service level
#### Method
+19
View File
@@ -320,6 +320,7 @@
| Method | Endpoint | Purpose |
| ------ | -------- | ------- |
| `GET` | `/automation/` | List all available automation scripts for system resources |
| `GET` | `/automation/{bundle}-{type}.{ext}` | Serves client scripts bundle |
| `POST` | `/automation/trigger` | Triggers execution of a specific script on a system service level |
## List all available automation scripts for system resources
@@ -343,6 +344,24 @@ Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.cru
| excludeClientScripts | bool | GET | Do not include client scripts | N/A | NO |
| excludeServerScripts | bool | GET | Do not include server scripts | N/A | NO |
## Serves client scripts bundle
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| bundle | string | PATH | Name of the bundle | N/A | NO |
| type | string | PATH | Bundle type | N/A | NO |
| ext | string | PATH | Bundle extension | N/A | NO |
## Triggers execution of a specific script on a system service level
#### Method
+26
View File
@@ -673,3 +673,29 @@ func (svc *service) registerClientScripts(ss ...*ClientScript) {
}
}
}
func (svc *service) GetBundle(ctx context.Context, name, bType string) *Bundle {
var (
err error
rsp *BundleResponse
)
svc.log.Debug("reloading server scripts")
ctx, cancel := context.WithTimeout(ctx, svc.opt.ListTimeout)
defer cancel()
rsp, err = svc.csClient.Bundle(ctx, &BundleRequest{Name: name}, grpc.WaitForReady(true))
if err != nil {
svc.log.Error("could not load corredor server scripts", zap.Error(err))
return nil
}
for _, b := range rsp.Bundles {
if b.Type == bType {
return b
}
}
return nil
}
+15
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/cortezaproject/corteza-server/pkg/eventbus"
"github.com/pkg/errors"
"net/http"
)
type (
@@ -99,3 +100,17 @@ func GenericListHandler(ctx context.Context, svc *service, f Filter, resourcePre
p.Set, p.Filter, err = svc.Find(ctx, f)
return p, err
}
func GenericBundleHandler(ctx context.Context, svc *service, bundleName, bundleType, ext string) (interface{}, error) {
return func(w http.ResponseWriter, req *http.Request) {
// Serve bundle directly for now
bundle := svc.GetBundle(ctx, bundleName, bundleType)
if bundle == nil {
w.WriteHeader(http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(bundle.Code))
}, nil
}
+10
View File
@@ -37,6 +37,16 @@ func (ctrl *Automation) List(ctx context.Context, r *request.AutomationList) (in
)
}
func (ctrl *Automation) Bundle(ctx context.Context, r *request.AutomationBundle) (interface{}, error) {
return corredor.GenericBundleHandler(
ctx,
corredor.Service(),
r.Bundle,
r.Type,
r.Ext,
)
}
func (ctrl *Automation) TriggerScript(ctx context.Context, r *request.AutomationTriggerScript) (interface{}, error) {
return resputil.OK(), corredor.Service().ExecOnManual(ctx, r.Script, event.SystemOnManual())
}
+23
View File
@@ -30,12 +30,14 @@ import (
// Internal API interface
type AutomationAPI interface {
List(context.Context, *request.AutomationList) (interface{}, error)
Bundle(context.Context, *request.AutomationBundle) (interface{}, error)
TriggerScript(context.Context, *request.AutomationTriggerScript) (interface{}, error)
}
// HTTP API interface
type Automation struct {
List func(http.ResponseWriter, *http.Request)
Bundle func(http.ResponseWriter, *http.Request)
TriggerScript func(http.ResponseWriter, *http.Request)
}
@@ -61,6 +63,26 @@ func NewAutomation(h AutomationAPI) *Automation {
resputil.JSON(w, value)
}
},
Bundle: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewAutomationBundle()
if err := params.Fill(r); err != nil {
logger.LogParamError("Automation.Bundle", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Bundle(r.Context(), params)
if err != nil {
logger.LogControllerError("Automation.Bundle", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Automation.Bundle", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
TriggerScript: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewAutomationTriggerScript()
@@ -88,6 +110,7 @@ func (h Automation) MountRoutes(r chi.Router, middlewares ...func(http.Handler)
r.Group(func(r chi.Router) {
r.Use(middlewares...)
r.Get("/automation/", h.List)
r.Get("/automation/{bundle}-{type}.{ext}", h.Bundle)
r.Post("/automation/trigger", h.TriggerScript)
})
}
+57
View File
@@ -117,6 +117,63 @@ func (r *AutomationList) Fill(req *http.Request) (err error) {
var _ RequestFiller = NewAutomationList()
// Automation bundle request parameters
type AutomationBundle struct {
Bundle string
Type string
Ext string
}
func NewAutomationBundle() *AutomationBundle {
return &AutomationBundle{}
}
func (r AutomationBundle) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["bundle"] = r.Bundle
out["type"] = r.Type
out["ext"] = r.Ext
return out
}
func (r *AutomationBundle) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.Bundle = chi.URLParam(req, "bundle")
r.Type = chi.URLParam(req, "type")
r.Ext = chi.URLParam(req, "ext")
return err
}
var _ RequestFiller = NewAutomationBundle()
// Automation triggerScript request parameters
type AutomationTriggerScript struct {
Script string