From 280b3b6329d4c64ec67f3bca7185e47fdab4de31 Mon Sep 17 00:00:00 2001 From: Izabella Raulin Date: Wed, 2 Nov 2016 17:32:43 +0100 Subject: [PATCH] Removed JSON RPC --- control/available_plugin.go | 12 - .../plugin/client/httpjsonrpc_deprecated.go | 314 ------------------ .../client/httpjsonrpc_deprecated_test.go | 283 ---------------- control/plugin/plugin.go | 6 +- control/plugin/plugin_deprecated.go | 68 +--- control/plugin/session_deprecated.go | 2 - control/plugin/session_test.go | 6 +- docs/PLUGIN_AUTHORING.md | 4 +- 8 files changed, 9 insertions(+), 686 deletions(-) delete mode 100644 control/plugin/client/httpjsonrpc_deprecated.go delete mode 100644 control/plugin/client/httpjsonrpc_deprecated_test.go diff --git a/control/available_plugin.go b/control/available_plugin.go index d448072da..576b48b23 100644 --- a/control/available_plugin.go +++ b/control/available_plugin.go @@ -95,22 +95,10 @@ func newAvailablePlugin(resp plugin.Response, emitter gomit.Emitter, ep executab } ap.key = fmt.Sprintf("%s"+core.Separator+"%s"+core.Separator+"%d", ap.pluginType.String(), ap.name, ap.version) - listenURL := fmt.Sprintf("http://%v/rpc", resp.ListenAddress) // Create RPC Client switch resp.Type { case plugin.CollectorPluginType: switch resp.Meta.RPCType { - case plugin.JSONRPC: - log.WithFields(log.Fields{ - "_module": "control-aplugin", - "_block": "newAvailablePlugin", - "plugin_name": ap.name, - }).Warning("This plugin is using a deprecated JSON RPC protocol. Find more information here: https://github.com/intelsdi-x/snap/issues/1296 ") - c, e := client.NewCollectorHttpJSONRPCClient(listenURL, DefaultClientTimeout, resp.PublicKey, !resp.Meta.Unsecure) - if e != nil { - return nil, errors.New("error while creating client connection: " + e.Error()) - } - ap.client = c case plugin.NativeRPC: log.WithFields(log.Fields{ "_module": "control-aplugin", diff --git a/control/plugin/client/httpjsonrpc_deprecated.go b/control/plugin/client/httpjsonrpc_deprecated.go deleted file mode 100644 index f3c535b13..000000000 --- a/control/plugin/client/httpjsonrpc_deprecated.go +++ /dev/null @@ -1,314 +0,0 @@ -/* ** DEPRECATED ** -For more information, see our deprecation notice -on Github: https://github.com/intelsdi-x/snap/issues/1296 -*/ - -/* -http://www.apache.org/licenses/LICENSE-2.0.txt - - -Copyright 2015 Intel Corporation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package client - -import ( - "bytes" - "crypto/rsa" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net/http" - "sync/atomic" - "time" - - log "github.com/Sirupsen/logrus" - - "github.com/intelsdi-x/snap/control/plugin" - "github.com/intelsdi-x/snap/control/plugin/cpolicy" - "github.com/intelsdi-x/snap/control/plugin/encoding" - "github.com/intelsdi-x/snap/control/plugin/encrypter" - "github.com/intelsdi-x/snap/core" - "github.com/intelsdi-x/snap/core/ctypes" -) - -var logger = log.WithField("_module", "client-httpjsonrpc") - -type httpJSONRPCClient struct { - url string - id uint64 - timeout time.Duration - pluginType plugin.PluginType - encrypter *encrypter.Encrypter - encoder encoding.Encoder -} - -// NewCollectorHttpJSONRPCClient returns CollectorHttpJSONRPCClient -func NewCollectorHttpJSONRPCClient(u string, timeout time.Duration, pub *rsa.PublicKey, secure bool) (PluginCollectorClient, error) { - hjr := &httpJSONRPCClient{ - url: u, - timeout: timeout, - pluginType: plugin.CollectorPluginType, - encoder: encoding.NewJsonEncoder(), - } - if secure { - key, err := encrypter.GenerateKey() - if err != nil { - return nil, err - } - e := encrypter.New(pub, nil) - e.Key = key - hjr.encoder.SetEncrypter(e) - hjr.encrypter = e - } - return hjr, nil -} - -func NewProcessorHttpJSONRPCClient(u string, timeout time.Duration, pub *rsa.PublicKey, secure bool) (PluginProcessorClient, error) { - hjr := &httpJSONRPCClient{ - url: u, - timeout: timeout, - pluginType: plugin.ProcessorPluginType, - encoder: encoding.NewJsonEncoder(), - } - if secure { - key, err := encrypter.GenerateKey() - if err != nil { - return nil, err - } - e := encrypter.New(pub, nil) - e.Key = key - hjr.encoder.SetEncrypter(e) - hjr.encrypter = e - } - return hjr, nil -} - -func NewPublisherHttpJSONRPCClient(u string, timeout time.Duration, pub *rsa.PublicKey, secure bool) (PluginPublisherClient, error) { - hjr := &httpJSONRPCClient{ - url: u, - timeout: timeout, - pluginType: plugin.PublisherPluginType, - encoder: encoding.NewJsonEncoder(), - } - if secure { - key, err := encrypter.GenerateKey() - if err != nil { - return nil, err - } - e := encrypter.New(pub, nil) - e.Key = key - hjr.encoder.SetEncrypter(e) - hjr.encrypter = e - } - return hjr, nil -} - -// Ping -func (h *httpJSONRPCClient) Ping() error { - _, err := h.call("SessionState.Ping", []interface{}{}) - return err -} - -func (h *httpJSONRPCClient) SetKey() error { - key, err := h.encrypter.EncryptKey() - if err != nil { - return err - } - a := plugin.SetKeyArgs{Key: key} - _, err = h.call("SessionState.SetKey", []interface{}{a}) - return err -} - -// kill -func (h *httpJSONRPCClient) Kill(reason string) error { - args := plugin.KillArgs{Reason: reason} - out, err := h.encoder.Encode(args) - if err != nil { - return err - } - - _, err = h.call("SessionState.Kill", []interface{}{out}) - return err -} - -// CollectMetrics returns collected metrics -func (h *httpJSONRPCClient) CollectMetrics(mts []core.Metric) ([]core.Metric, error) { - var results []core.Metric - if len(mts) == 0 { - return nil, errors.New("no metrics to collect") - } - - metricsToCollect := make([]plugin.MetricType, len(mts)) - for idx, mt := range mts { - metricsToCollect[idx] = plugin.MetricType{ - Namespace_: mt.Namespace(), - LastAdvertisedTime_: mt.LastAdvertisedTime(), - Version_: mt.Version(), - Tags_: mt.Tags(), - Config_: mt.Config(), - } - } - - args := &plugin.CollectMetricsArgs{MetricTypes: metricsToCollect} - - out, err := h.encoder.Encode(args) - if err != nil { - return nil, err - } - - res, err := h.call("Collector.CollectMetrics", []interface{}{out}) - if err != nil { - return nil, err - } - if len(res.Result) == 0 { - err := errors.New("Invalid response: result is 0") - logger.WithFields(log.Fields{ - "_block": "CollectMetrics", - "jsonrpc response": fmt.Sprintf("%+v", res), - }).Error(err) - return nil, err - } - r := &plugin.CollectMetricsReply{} - err = h.encoder.Decode(res.Result, r) - if err != nil { - return nil, err - } - - results = make([]core.Metric, len(r.PluginMetrics)) - idx := 0 - for _, m := range r.PluginMetrics { - results[idx] = m - idx++ - } - - return results, nil -} - -// GetMetricTypes returns metric types that can be collected -func (h *httpJSONRPCClient) GetMetricTypes(config plugin.ConfigType) ([]core.Metric, error) { - args := plugin.GetMetricTypesArgs{PluginConfig: config} - - out, err := h.encoder.Encode(args) - if err != nil { - return nil, err - } - - res, err := h.call("Collector.GetMetricTypes", []interface{}{out}) - if err != nil { - return nil, err - } - var mtr plugin.GetMetricTypesReply - err = h.encoder.Decode(res.Result, &mtr) - if err != nil { - return nil, err - } - metrics := make([]core.Metric, len(mtr.MetricTypes)) - for i, mt := range mtr.MetricTypes { - mt.LastAdvertisedTime_ = time.Now() - metrics[i] = mt - } - return metrics, nil -} - -// GetConfigPolicy returns a config policy -func (h *httpJSONRPCClient) GetConfigPolicy() (*cpolicy.ConfigPolicy, error) { - res, err := h.call("SessionState.GetConfigPolicy", []interface{}{}) - if err != nil { - logger.WithFields(log.Fields{ - "_block": "GetConfigPolicy", - "result": fmt.Sprintf("%+v", res), - "error": err, - }).Error("error getting config policy") - return nil, err - } - if len(res.Result) == 0 { - return nil, errors.New(res.Error) - } - var cpr plugin.GetConfigPolicyReply - err = h.encoder.Decode(res.Result, &cpr) - if err != nil { - return nil, err - } - return cpr.Policy, nil -} - -func (h *httpJSONRPCClient) Publish([]core.Metric, map[string]ctypes.ConfigValue) error { - return errors.New("Not Implemented") -} - -func (h *httpJSONRPCClient) Process([]core.Metric, map[string]ctypes.ConfigValue) ([]core.Metric, error) { - return nil, errors.New("Not Implemented") -} - -func (h *httpJSONRPCClient) GetType() string { - return upcaseInitial(h.pluginType.String()) -} - -type jsonRpcResp struct { - Id int `json:"id"` - Result []byte `json:"result"` - Error string `json:"error"` -} - -func (h *httpJSONRPCClient) call(method string, args []interface{}) (*jsonRpcResp, error) { - data, err := json.Marshal(map[string]interface{}{ - "method": method, - "id": h.id, - "params": args, - }) - if err != nil { - logger.WithFields(log.Fields{ - "_block": "call", - "url": h.url, - "args": fmt.Sprintf("%+v", args), - "method": method, - "id": h.id, - "error": err, - }).Error("error encoding request to json") - return nil, err - } - client := http.Client{Timeout: h.timeout} - resp, err := client.Post(h.url, "application/json", bytes.NewReader(data)) - if err != nil { - logger.WithFields(log.Fields{ - "_block": "call", - "url": h.url, - "request": string(data), - "error": err, - }).Error("error posting request to plugin") - return nil, err - } - defer resp.Body.Close() - result := &jsonRpcResp{} - if err = json.NewDecoder(resp.Body).Decode(result); err != nil { - bs, _ := ioutil.ReadAll(resp.Body) - logger.WithFields(log.Fields{ - "_block": "call", - "url": h.url, - "request": string(data), - "status code": resp.StatusCode, - "response": string(bs), - "error": err, - }).Error("error decoding result") - return nil, err - } - atomic.AddUint64(&h.id, 1) - if result.Error != "" { - return result, errors.New(result.Error) - } - return result, nil -} diff --git a/control/plugin/client/httpjsonrpc_deprecated_test.go b/control/plugin/client/httpjsonrpc_deprecated_test.go deleted file mode 100644 index 7cf06a838..000000000 --- a/control/plugin/client/httpjsonrpc_deprecated_test.go +++ /dev/null @@ -1,283 +0,0 @@ -/* ** DEPRECATED ** -For more information, see our deprecation notice -on Github: https://github.com/intelsdi-x/snap/issues/1296 -*/ - -/* -http://www.apache.org/licenses/LICENSE-2.0.txt - - -Copyright 2015 Intel Corporation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package client - -import ( - crand "crypto/rand" - "crypto/rsa" - "fmt" - "io" - "math/rand" - "net" - "net/http" - "net/rpc" - "testing" - "time" - - log "github.com/Sirupsen/logrus" - - "github.com/intelsdi-x/snap/control/plugin" - "github.com/intelsdi-x/snap/control/plugin/cpolicy" - "github.com/intelsdi-x/snap/control/plugin/encoding" - "github.com/intelsdi-x/snap/control/plugin/encrypter" - "github.com/intelsdi-x/snap/core" - "github.com/intelsdi-x/snap/core/cdata" - "github.com/intelsdi-x/snap/core/ctypes" - . "github.com/smartystreets/goconvey/convey" -) - -var ( - key, _ = rsa.GenerateKey(crand.Reader, 1024) - symkey, _ = encrypter.GenerateKey() -) - -type mockProxy struct { - e encoding.Encoder -} - -func (m *mockProxy) Process(args []byte, reply *[]byte) error { - var dargs plugin.ProcessorArgs - m.e.Decode(args, &dargs) - pr := plugin.ProcessorReply{Content: dargs.Content, ContentType: dargs.ContentType} - *reply, _ = m.e.Encode(pr) - return nil -} - -func (m *mockProxy) Publish(args []byte, reply *[]byte) error { - return nil -} - -type mockCollectorProxy struct { - e encoding.Encoder -} - -func (m *mockCollectorProxy) CollectMetrics(args []byte, reply *[]byte) error { - rand.Seed(time.Now().Unix()) - var dargs plugin.CollectMetricsArgs - err := m.e.Decode(args, &dargs) - if err != nil { - return err - } - var mts []plugin.MetricType - for _, i := range dargs.MetricTypes { - p := plugin.NewMetricType(i.Namespace(), time.Now(), nil, "", rand.Intn(100)) - p.Config_ = i.Config() - mts = append(mts, *p) - } - cmr := &plugin.CollectMetricsReply{PluginMetrics: mts} - *reply, err = m.e.Encode(cmr) - if err != nil { - return err - } - return nil -} - -func (m *mockCollectorProxy) GetMetricTypes(args []byte, reply *[]byte) error { - dargs := &plugin.GetMetricTypesArgs{} - m.e.Decode(args, &dargs) - - pmts := []plugin.MetricType{} - pmts = append(pmts, plugin.MetricType{ - Namespace_: core.NewNamespace("foo", "bar"), - Config_: dargs.PluginConfig.ConfigDataNode, - }) - *reply, _ = m.e.Encode(plugin.GetMetricTypesReply{MetricTypes: pmts}) - return nil -} - -type mockSessionStatePluginProxy struct { - e encoding.Encoder - c bool -} - -func (m *mockSessionStatePluginProxy) GetConfigPolicy(args []byte, reply *[]byte) error { - cp := cpolicy.New() - n1 := cpolicy.NewPolicyNode() - if m.c { - r1, _ := cpolicy.NewStringRule("name", false, "bob") - n1.Add(r1) - r2, _ := cpolicy.NewIntegerRule("someInt", true, 100) - n1.Add(r2) - r3, _ := cpolicy.NewStringRule("password", true) - n1.Add(r3) - r4, _ := cpolicy.NewFloatRule("somefloat", false, 3.14) - n1.Add(r4) - cp.Add([]string{"foo", "bar"}, n1) - } else { - r1, _ := cpolicy.NewIntegerRule("SomeRequiredInt", true, 1) - r2, _ := cpolicy.NewStringRule("password", true) - r3, _ := cpolicy.NewFloatRule("somefloat", false, 3.14) - n1.Add(r1, r2, r3) - cp.Add([]string{""}, n1) - } - cpr := plugin.GetConfigPolicyReply{Policy: cp} - var err error - *reply, err = m.e.Encode(cpr) - return err -} - -func (m *mockSessionStatePluginProxy) Ping(arg []byte, b *[]byte) error { - return nil -} - -func (m *mockSessionStatePluginProxy) Kill(arg []byte, b *[]byte) error { - return nil -} - -var httpStarted = false - -func startHTTPJSONRPC() (string, *mockSessionStatePluginProxy) { - encr := encrypter.New(&key.PublicKey, nil) - encr.Key = symkey - ee := encoding.NewJsonEncoder() - ee.SetEncrypter(encr) - mockProxy := &mockProxy{e: ee} - mockCollectorProxy := &mockCollectorProxy{e: ee} - rpc.RegisterName("Collector", mockCollectorProxy) - rpc.RegisterName("Processor", mockProxy) - rpc.RegisterName("Publisher", mockProxy) - session := &mockSessionStatePluginProxy{e: ee} - rpc.RegisterName("SessionState", session) - rpc.HandleHTTP() - - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - panic(err) - } - go func() { - http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - defer req.Body.Close() - w.Header().Set("Content-Type", "application/json") - res := plugin.NewRPCRequest(req.Body).Call() - io.Copy(w, res) - }) - http.Serve(l, nil) - }() - - return l.Addr().String(), session -} - -func TestHTTPJSONRPC(t *testing.T) { - log.SetLevel(log.DebugLevel) - addr, session := startHTTPJSONRPC() - time.Sleep(time.Millisecond * 100) - - Convey("Collector Client", t, func() { - session.c = true - c, err := NewCollectorHttpJSONRPCClient(fmt.Sprintf("http://%v", addr), 1*time.Second, &key.PublicKey, true) - So(err, ShouldBeNil) - So(c, ShouldNotBeNil) - cl := c.(*httpJSONRPCClient) - cl.encrypter.Key = symkey - - Convey("Ping", func() { - err := c.Ping() - So(err, ShouldBeNil) - }) - - Convey("Kill", func() { - err := c.Kill("somereason") - So(err, ShouldBeNil) - }) - - Convey("GetMetricTypes", func() { - cfg := plugin.NewPluginConfigType() - cfg.AddItem("test", ctypes.ConfigValueBool{Value: true}) - mts, err := c.GetMetricTypes(cfg) - So(err, ShouldBeNil) - So(mts, ShouldNotBeNil) - So(mts, ShouldHaveSameTypeAs, []core.Metric{}) - So(len(mts), ShouldBeGreaterThan, 0) - So(len(mts[0].Config().Table()), ShouldBeGreaterThan, 0) - }) - - Convey("CollectMetrics provided a valid config", func() { - cdn := cdata.NewNode() - cdn.AddItem("someInt", ctypes.ConfigValueInt{Value: 1}) - cdn.AddItem("password", ctypes.ConfigValueStr{Value: "secure"}) - - time.Sleep(500 * time.Millisecond) - mts, err := c.CollectMetrics([]core.Metric{ - &plugin.MetricType{ - Namespace_: core.NewNamespace("foo", "bar"), - Config_: cdn, - }, - }) - So(err, ShouldBeNil) - So(mts, ShouldNotBeNil) - So(mts, ShouldHaveSameTypeAs, []core.Metric{}) - So(len(mts), ShouldBeGreaterThan, 0) - So(mts[0].Config().Table(), ShouldNotBeEmpty) - So(mts[0].Config().Table()["someInt"].Type(), ShouldResemble, "integer") - - Convey("Get and process the ConfigPolicy", func() { - cp, err := c.GetConfigPolicy() - So(err, ShouldBeNil) - So(cp, ShouldNotBeNil) - So(cp.Get([]string{"foo", "bar"}), ShouldNotBeNil) - node := cp.Get([]string{"foo", "bar"}) - So(node, ShouldNotBeNil) - cpn, cserrs := node.Process(mts[0].Config().Table()) - So(cpn, ShouldNotBeNil) - So((*cpn)["somefloat"].Type(), ShouldResemble, "float") - So((*cpn)["somefloat"].(ctypes.ConfigValueFloat).Value, ShouldResemble, 3.14) - So(cserrs.Errors(), ShouldBeEmpty) - }) - }) - - Convey("CollectMetrics provided an invalid config", func() { - cdn := cdata.NewNode() - cdn.AddItem("someInt", ctypes.ConfigValueInt{Value: 1}) - - time.Sleep(500 * time.Millisecond) - mts, err := c.CollectMetrics([]core.Metric{ - &plugin.MetricType{ - Namespace_: core.NewNamespace("foo", "bar"), - Config_: cdn, - }, - }) - So(err, ShouldBeNil) - So(mts, ShouldNotBeNil) - So(mts, ShouldHaveSameTypeAs, []core.Metric{}) - So(len(mts), ShouldBeGreaterThan, 0) - So(mts[0].Config().Table(), ShouldNotBeEmpty) - So(mts[0].Config().Table()["someInt"].Type(), ShouldResemble, "integer") - - Convey("Get and process the ConfigPolicy", func() { - cp, err := c.GetConfigPolicy() - So(err, ShouldBeNil) - So(cp, ShouldNotBeNil) - node := cp.Get([]string{"foo", "bar"}) - So(node, ShouldNotBeNil) - So(err, ShouldBeNil) - _, cserrs := node.Process(mts[0].Config().Table()) - //So(cpn, ShouldBeNil) - So(cserrs.Errors(), ShouldNotBeEmpty) - So(len(cserrs.Errors()), ShouldEqual, 1) - So(cserrs.Errors()[0].Error(), ShouldContainSubstring, "password") - }) - }) - }) -} diff --git a/control/plugin/plugin.go b/control/plugin/plugin.go index fb64db57f..9ac1f1118 100644 --- a/control/plugin/plugin.go +++ b/control/plugin/plugin.go @@ -72,9 +72,9 @@ const ( type RPCType int const ( - NativeRPC RPCType = iota - JSONRPC - GRPC + // IMPORTANT: keep consistency across snap-plugin-lib, GRPC must be equal 2 + NativeRPC RPCType = 0 + GRPC RPCType = 2 ) var ( diff --git a/control/plugin/plugin_deprecated.go b/control/plugin/plugin_deprecated.go index 468d020e3..d1a361f22 100644 --- a/control/plugin/plugin_deprecated.go +++ b/control/plugin/plugin_deprecated.go @@ -25,14 +25,9 @@ limitations under the License. package plugin import ( - "bytes" - "encoding/json" "fmt" - "io" "net" - "net/http" "net/rpc" - "net/rpc/jsonrpc" "regexp" "runtime" "time" @@ -130,7 +125,7 @@ func NewPluginMeta(name string, version int, pluginType PluginType, acceptConten // PluginMeta - base information about plugin // Plugin - CollectorPlugin, ProcessorPlugin or PublisherPlugin // requestString - plugins arguments (marshaled json of control/plugin Arg struct) -// returns an error and exitCode (exitCode from SessionState initilization or plugin termination code) +// returns an error and exitCode (exitCode from SessionState initialization or plugin termination code) func Start(m *PluginMeta, c Plugin, requestString string) (error, int) { s, sErr, retCode := NewSessionState(requestString, c, m) if sErr != nil { @@ -214,28 +209,6 @@ func Start(m *PluginMeta, c Plugin, requestString string) (error, int) { s.Logger().Debugf("Session token %s\n", s.Token()) switch r.Meta.RPCType { - case JSONRPC: - rpc.HandleHTTP() - http.HandleFunc("/rpc", func(w http.ResponseWriter, req *http.Request) { - defer req.Body.Close() - w.Header().Set("Content-Type", "application/json") - if req.ContentLength == 0 { - encoder := json.NewEncoder(w) - encoder.Encode(&struct { - Id interface{} `json:"id"` - Result interface{} `json:"result"` - Error interface{} `json:"error"` - }{ - Id: nil, - Result: nil, - Error: "rpc: method request ill-formed", - }) - return - } - res := NewRPCRequest(req.Body).Call() - io.Copy(w, res) - }) - go http.Serve(l, nil) case NativeRPC: go func() { for { @@ -263,45 +236,6 @@ func Start(m *PluginMeta, c Plugin, requestString string) (error, int) { return nil, exitCode } -// rpcRequest represents a RPC request. -// rpcRequest implements the io.ReadWriteCloser interface. -type rpcRequest struct { - r io.Reader // holds the JSON formated RPC request - rw io.ReadWriter // holds the JSON formated RPC response - done chan bool // signals then end of the RPC request -} - -// NewRPCRequest returns a new rpcRequest. -func NewRPCRequest(r io.Reader) *rpcRequest { - var buf bytes.Buffer - done := make(chan bool) - return &rpcRequest{r, &buf, done} -} - -// Read implements the io.ReadWriteCloser Read method. -func (r *rpcRequest) Read(p []byte) (n int, err error) { - return r.r.Read(p) -} - -// Write implements the io.ReadWriteCloser Write method. -func (r *rpcRequest) Write(p []byte) (n int, err error) { - n, err = r.rw.Write(p) - defer func(done chan bool) { done <- true }(r.done) - return -} - -// Close implements the io.ReadWriteCloser Close method. -func (r *rpcRequest) Close() error { - return nil -} - -// Call invokes the RPC request, waits for it to complete, and returns the results. -func (r *rpcRequest) Call() io.Reader { - go jsonrpc.ServeConn(r) - <-r.done - return r.rw -} - func catchPluginPanic(l *log.Logger) { if err := recover(); err != nil { trace := make([]byte, 4096) diff --git a/control/plugin/session_deprecated.go b/control/plugin/session_deprecated.go index b9853909e..9506bb058 100644 --- a/control/plugin/session_deprecated.go +++ b/control/plugin/session_deprecated.go @@ -258,8 +258,6 @@ func NewSessionState(pluginArgsMsg string, plugin Plugin, meta *PluginMeta) (*Se var enc encoding.Encoder switch meta.RPCType { - case JSONRPC: - enc = encoding.NewJsonEncoder() case NativeRPC: enc = encoding.NewGobEncoder() case GRPC: diff --git a/control/plugin/session_test.go b/control/plugin/session_test.go index 55867be26..00d3dd190 100644 --- a/control/plugin/session_test.go +++ b/control/plugin/session_test.go @@ -152,7 +152,7 @@ func TestSessionState(t *testing.T) { Convey("InitSessionState", func() { var mockPluginArgs string = "{\"RunAsDaemon\": true, \"PingTimeoutDuration\": 2000000000}" m := PluginMeta{ - RPCType: JSONRPC, + RPCType: NativeRPC, Type: CollectorPluginType, } sessionState, err, rc := NewSessionState(mockPluginArgs, &MockPlugin{Meta: m}, &m) @@ -165,7 +165,7 @@ func TestSessionState(t *testing.T) { Convey("InitSessionState with invalid args", func() { var mockPluginArgs string m := PluginMeta{ - RPCType: JSONRPC, + RPCType: NativeRPC, Type: CollectorPluginType, } _, err, _ := NewSessionState(mockPluginArgs, &MockPlugin{Meta: m}, &m) @@ -174,7 +174,7 @@ func TestSessionState(t *testing.T) { Convey("InitSessionState with a custom log path", func() { var mockPluginArgs string = "{\"RunAsDaemon\": false, \"PluginLogPath\": \"/var/tmp/snap_plugin.log\"}" m := PluginMeta{ - RPCType: JSONRPC, + RPCType: NativeRPC, Type: CollectorPluginType, } sess, err, rc := NewSessionState(mockPluginArgs, &MockPlugin{Meta: m}, &m) diff --git a/docs/PLUGIN_AUTHORING.md b/docs/PLUGIN_AUTHORING.md index 6b820d9de..c75565082 100644 --- a/docs/PLUGIN_AUTHORING.md +++ b/docs/PLUGIN_AUTHORING.md @@ -35,9 +35,9 @@ Bon Appétit! :stew: ## Plugin Authoring Snap itself runs as a master daemon with the core functionality that may load and unload plugin processes via either CLI or HTTP APIs. -A Snap plugin is a program, or a set of functions or services, written in Go or any language; that may seamlessly integrate with snap as executables. +A Snap plugin is a program, or a set of functions or services, written in Go or any language; that may seamlessly integrate with snap as executables. -Communication between Snap and plugins uses RPC either through HTTP or TCP protocols. HTTP JSON-RPC is good for any language to use due to its nature of JSON representation of data while the native client is only suitable for plugins written in Golang. The data that plugins report to snap is in the form of JSON or GOB CODEC. +Communication between Snap and plugins uses RPC either through HTTP or TCP protocols. HTTP gRPC is good for any language to use that gRPC supports (see [gRPC docs](http://grpc.io/docs)) while the native client is only suitable for plugins written in Golang. When a plugin is written using one of the available snap-plugin-libs ([snap-plugin-lib-go](https://github.com/intelsdi-x/snap-plugin-lib-go), [snap-plugin-lib-py](https://github.com/intelsdi-x/snap-plugin-lib-py), or [snap-plugin-lib-cpp](https://github.com/intelsdi-x/snap-plugin-lib-cpp)) Google Protobuf, a binary serialization format, is used to encode/decode the data (see [plugin.proto](https://github.com/intelsdi-x/snap/blob/master/control/plugin/rpc/plugin.proto)). Before starting writing Snap plugins, check out the [Plugin Catalog](https://github.com/intelsdi-x/snap/blob/master/docs/PLUGIN_CATALOG.md) to see if any suit your needs. If not, you need to reference the plugin packages that defines the type of structures and interfaces inside snap and then write plugin endpoints to implement the defined interfaces.