Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Add standalone support to API v2
Browse files Browse the repository at this point in the history
  • Loading branch information
mkleina committed Aug 16, 2017
1 parent 5351697 commit 7779672
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 28 deletions.
104 changes: 76 additions & 28 deletions mgmt/rest/v2/plugin.go
Expand Up @@ -30,6 +30,7 @@ import (
"mime" "mime"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
Expand Down Expand Up @@ -146,6 +147,18 @@ type PluginPostParams struct {
// in: formData // in: formData
// //
CACerts string `json:"ca_certs"` CACerts string `json:"ca_certs"`
// Stand-alone plugin URI
//
// in: formData
//
PluginURI string `json:"plugin_uri"`
}

// Map for collecting HTTP form field data
type formFieldMap map[string]formField
type formField struct {
fileName string
data []byte
} }


// Name plugin name string // Name plugin name string
Expand Down Expand Up @@ -176,61 +189,96 @@ func (s *apiV2) loadPlugin(w http.ResponseWriter, r *http.Request, _ httprouter.
var certPath, keyPath, caCertPaths string var certPath, keyPath, caCertPaths string
var signature []byte var signature []byte
var checkSum [sha256.Size]byte var checkSum [sha256.Size]byte
mr := multipart.NewReader(r.Body, params["boundary"])


for { // Go OpenAPI sends URL-encoded forms (without boundary data) if no file fields were passed.
var b []byte // In standalone plugin mode, only plugin address is passed, so because of this behavior,
p, err := mr.NextPart() // multipart reader does not work and data needs to be processed using url.ParseQuery().
if err == io.EOF { // Otherwise, incoming data is parsed using multipart reader.
break
// Reading HTTP form fields
formFields := make(formFieldMap)
if params["boundary"] == "" {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
Write(500, FromError(err), w)
return
} }
data, err := url.ParseQuery(string(b))
if err != nil { if err != nil {
Write(500, FromError(err), w) Write(500, FromError(err), w)
return return
} }
if r.Header.Get("Plugin-Compression") == "gzip" { for key, value := range data {
g, err := gzip.NewReader(p) formFields[key] = formField{fileName: "", data: []byte(value[0])}
defer g.Close() }
if err != nil { } else {
Write(500, FromError(err), w) mr := multipart.NewReader(r.Body, params["boundary"])
return
var b []byte
for {
p, err := mr.NextPart()
if err == io.EOF {
break
} }
b, err = ioutil.ReadAll(g)
if err != nil { if err != nil {
Write(500, FromError(err), w) Write(500, FromError(err), w)
return return
} }
} else { if r.Header.Get("Plugin-Compression") == "gzip" {
b, err = ioutil.ReadAll(p) g, err := gzip.NewReader(p)
if err != nil { defer g.Close()
Write(500, FromError(err), w) if err != nil {
return Write(500, FromError(err), w)
return
}
b, err = ioutil.ReadAll(g)
if err != nil {
Write(500, FromError(err), w)
return
}
} else {
b, err = ioutil.ReadAll(p)
if err != nil {
Write(500, FromError(err), w)
return
}
} }
formFields[p.FormName()] = formField{fileName: p.FileName(), data: b}
} }
}


switch p.FormName() { // Handle actions for received form fields
for fieldName, field := range formFields {
switch fieldName {
case "ca_certs": case "ca_certs":
caCertPaths = string(b) caCertPaths = string(field.data)
handleError(caCertPaths, w) handleError(caCertPaths, w)
case "plugin_key": case "plugin_key":
keyPath = string(b) keyPath = string(field.data)
handleError(keyPath, w) handleError(keyPath, w)
case "plugin_cert": case "plugin_cert":
certPath = string(b) certPath = string(field.data)
handleError(certPath, w) handleError(certPath, w)
// plugin_data is from REST API and snap-plugins is from rest_v2_test.go. //plugin_data is from REST API and snap-plugins is from rest_v2_test.go.
case "plugin_data", "snap-plugins": case "plugin_data", "snap-plugins":
rp, err = core.NewRequestedPlugin(p.FileName(), s.metricManager.GetTempDir(), b) rp, err = core.NewRequestedPlugin(field.fileName, s.metricManager.GetTempDir(), field.data)
if err != nil {
Write(500, FromError(err), w)
return
}
checkSum = sha256.Sum256(field.data)
case "plugin_uri":
pluginURI := string(field.data)
rp, err = core.NewRequestedPlugin(pluginURI, "", nil)
if err != nil { if err != nil {
Write(500, FromError(err), w) Write(500, FromError(err), w)
return return
} }
checkSum = sha256.Sum256(b)
default: default:
if filepath.Ext(p.FileName()) == ".asc" { if filepath.Ext(field.fileName) == ".asc" {
signature = b signature = field.data
} else { } else {
e := errors.New("Error: An unknown file found " + p.FileName()) e := errors.New("Error: An unknown file found " + field.fileName)
Write(400, FromError(e), w) Write(400, FromError(e), w)
return return
} }
Expand Down
7 changes: 7 additions & 0 deletions swagger.json
Expand Up @@ -168,6 +168,13 @@
"description": "CA root certification", "description": "CA root certification",
"name": "ca_certs", "name": "ca_certs",
"in": "formData" "in": "formData"
},
{
"type": "string",
"x-go-name": "PluginURI",
"description": "Stand-alone plugin URI",
"name": "plugin_uri",
"in": "formData"
} }
], ],
"responses": { "responses": {
Expand Down

0 comments on commit 7779672

Please sign in to comment.