func TestGetConfigPolicy(t *testing.T) { Convey("Get Config Policy", t, func() { logger := log.New(os.Stdout, "test: ", log.Ldate|log.Ltime|log.Lshortfile) mockPlugin := &mockPlugin{} mockSessionState := &MockSessionState{ Encoder: encoding.NewGobEncoder(), listenPort: "0", token: "abcdef", logger: logger, PingTimeoutDuration: time.Millisecond * 100, killChan: make(chan int), } c := &collectorPluginProxy{ Plugin: mockPlugin, Session: mockSessionState, } var reply []byte c.Session.GetConfigPolicy([]byte{}, &reply) var cpr GetConfigPolicyReply err := c.Session.Decode(reply, &cpr) So(err, ShouldBeNil) So(cpr.Policy, ShouldNotBeNil) }) Convey("Get error in Config Policy ", t, func() { logger := log.New(os.Stdout, "test: ", log.Ldate|log.Ltime|log.Lshortfile) errSession := &errSessionState{ &MockSessionState{ Encoder: encoding.NewGobEncoder(), listenPort: "0", token: "abcdef", logger: logger, PingTimeoutDuration: time.Millisecond * 100, killChan: make(chan int), }} mockErrorPlugin := &mockErrorPlugin{} errC := &collectorPluginProxy{ Plugin: mockErrorPlugin, Session: errSession, } var reply []byte err := errC.Session.GetConfigPolicy([]byte{}, &reply) So(err, ShouldNotBeNil) So(err.Error(), ShouldResemble, "GetConfigPolicy call error : Error in get config policy") }) }
func newNativeClient(address string, timeout time.Duration, t plugin.PluginType, pub *rsa.PublicKey, secure bool) (*PluginNativeClient, error) { // Attempt to dial address error on timeout or problem conn, err := net.DialTimeout("tcp", address, timeout) // Return nil RPCClient and err if encoutered if err != nil { return nil, err } r := rpc.NewClient(conn) p := &PluginNativeClient{ connection: r, pluginType: t, timeout: timeout, } p.encoder = encoding.NewGobEncoder() if secure { key, err := encrypter.GenerateKey() if err != nil { return nil, err } encrypter := encrypter.New(pub, nil) encrypter.Key = key p.encrypter = encrypter p.encoder.SetEncrypter(encrypter) } return p, nil }
func startCollectorServer() (int, Session, error) { lis, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return 0, nil, err } mockPlugin := &mockPlugin{} mockSessionState := &MockSessionState{ Encoder: encoding.NewGobEncoder(), listenPort: "0", token: "abcdef", logger: log.New(os.Stdout, "test: ", log.Ldate|log.Ltime|log.Lshortfile), PingTimeoutDuration: time.Millisecond * 100, killChan: make(chan int), } opts := []grpc.ServerOption{} grpcServer := grpc.NewServer(opts...) collectProxy := &gRPCCollectorProxy{ Plugin: mockPlugin, Session: mockSessionState, gRPCPluginProxy: gRPCPluginProxy{ plugin: mockPlugin, session: mockSessionState, }, } rpc.RegisterCollectorServer(grpcServer, collectProxy) go func() { err := grpcServer.Serve(lis) if err != nil { log.Print(err) } }() return lis.Addr().(*net.TCPAddr).Port, mockSessionState, nil }
func TestCollectorProxy(t *testing.T) { Convey("Test collector plugin proxy for get metric types ", t, func() { logger := log.New() mockPlugin := &mockPlugin{} mockSessionState := &MockSessionState{ Encoder: encoding.NewGobEncoder(), listenPort: "0", token: "abcdef", logger: logger, PingTimeoutDuration: time.Millisecond * 100, killChan: make(chan int), } c := &collectorPluginProxy{ Plugin: mockPlugin, Session: mockSessionState, } Convey("Get Metric Types", func() { var reply []byte c.GetMetricTypes([]byte{}, &reply) var mtr GetMetricTypesReply err := c.Session.Decode(reply, &mtr) So(err, ShouldBeNil) So(mtr.MetricTypes[0].Namespace().String(), ShouldResemble, "/foo/*/bar") }) Convey("Get error in Get Metric Type", func() { mockErrorPlugin := &mockErrorPlugin{} errC := &collectorPluginProxy{ Plugin: mockErrorPlugin, Session: mockSessionState, } var reply []byte err := errC.GetMetricTypes([]byte{}, &reply) So(err.Error(), ShouldResemble, "GetMetricTypes call error : Error in get Metric Type") }) Convey("Collect Metric ", func() { args := CollectMetricsArgs{ MetricTypes: mockMetricType, } out, err := c.Session.Encode(args) So(err, ShouldBeNil) var reply []byte c.CollectMetrics(out, &reply) var mtr CollectMetricsReply err = c.Session.Decode(reply, &mtr) So(mtr.PluginMetrics[0].Namespace().String(), ShouldResemble, "/foo/test/bar") So(mtr.PluginMetrics[0].Namespace()[1].Name, ShouldEqual, "test") Convey("Get error in Collect Metric ", func() { args := CollectMetricsArgs{ MetricTypes: mockMetricType, } mockErrorPlugin := &mockErrorPlugin{} errC := &collectorPluginProxy{ Plugin: mockErrorPlugin, Session: mockSessionState, } out, err := errC.Session.Encode(args) So(err, ShouldBeNil) var reply []byte err = errC.CollectMetrics(out, &reply) So(err, ShouldNotBeNil) }) }) }) }
// NewSessionState takes the plugin args and returns a SessionState // returns State or error and returnCode: // 0 - ok // 2 - error when unmarshaling pluginArgs // 3 - cannot open error files func NewSessionState(pluginArgsMsg string, plugin Plugin, meta *PluginMeta) (*SessionState, error, int) { pluginArg := &Arg{} err := json.Unmarshal([]byte(pluginArgsMsg), pluginArg) if err != nil { return nil, err, 2 } // If no port was provided we let the OS select a port for us. // This is safe as address is returned in the Response and keep // alive prevents unattended plugins. if pluginArg.listenPort == "" { pluginArg.listenPort = "0" } // If no PingTimeoutDuration was provided we need to set it if pluginArg.PingTimeoutDuration == 0 { pluginArg.PingTimeoutDuration = PingTimeoutDurationDefault } // Generate random token for this session rb := make([]byte, 32) rand.Read(rb) rs := base64.URLEncoding.EncodeToString(rb) logger := &log.Logger{ Out: os.Stderr, Formatter: &simpleFormatter{}, Hooks: make(log.LevelHooks), Level: pluginArg.LogLevel, } var enc encoding.Encoder switch meta.RPCType { case JSONRPC: enc = encoding.NewJsonEncoder() case NativeRPC: enc = encoding.NewGobEncoder() case GRPC: enc = encoding.NewGobEncoder() //TODO(CDR): re-think once content-types is settled } ss := &SessionState{ Arg: pluginArg, Encoder: enc, plugin: plugin, token: rs, killChan: make(chan int), logger: logger, } if !meta.Unsecure { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err, 2 } encrypt := encrypter.New(nil, key) enc.SetEncrypter(encrypt) ss.Encrypter = encrypt ss.privateKey = key } return ss, nil, 0 }
// NewSessionState takes the plugin args and returns a SessionState // returns State or error and returnCode: // 0 - ok // 2 - error when unmarshaling pluginArgs // 3 - cannot open error files func NewSessionState(pluginArgsMsg string, plugin Plugin, meta *PluginMeta) (*SessionState, error, int) { pluginArg := &Arg{} err := json.Unmarshal([]byte(pluginArgsMsg), pluginArg) if err != nil { return nil, err, 2 } // If no port was provided we let the OS select a port for us. // This is safe as address is returned in the Response and keep // alive prevents unattended plugins. if pluginArg.listenPort == "" { pluginArg.listenPort = "0" } // If no PingTimeoutDuration was provided we need to set it if pluginArg.PingTimeoutDuration == 0 { pluginArg.PingTimeoutDuration = PingTimeoutDurationDefault } // Generate random token for this session rb := make([]byte, 32) rand.Read(rb) rs := base64.URLEncoding.EncodeToString(rb) // Initialize a logger based on PluginLogPath truncOrAppend := os.O_TRUNC // truncate log file explicitly given by user // Empty or /tmp means use default tmp log (needs to be removed post-aAtruncOrAppendpha) if pluginArg.PluginLogPath == "" || pluginArg.PluginLogPath == "/tmp" { if runtime.GOOS == "windows" { pluginArg.PluginLogPath = `c:\TEMP\snap_plugin.log` } else { pluginArg.PluginLogPath = "/tmp/snap_plugin.log" } truncOrAppend = os.O_APPEND } lf, err := os.OpenFile(pluginArg.PluginLogPath, os.O_WRONLY|os.O_CREATE|truncOrAppend, 0666) if err != nil { return nil, errors.New(fmt.Sprintf("error opening log file: %v", err)), 3 } logger := log.New(lf, ">>>", log.Ldate|log.Ltime) var enc encoding.Encoder switch meta.RPCType { case JSONRPC: enc = encoding.NewJsonEncoder() case NativeRPC: enc = encoding.NewGobEncoder() } ss := &SessionState{ Arg: pluginArg, Encoder: enc, plugin: plugin, token: rs, killChan: make(chan int), logger: logger, } if !meta.Unsecure { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err, 2 } encrypt := encrypter.New(nil, key) enc.SetEncrypter(encrypt) ss.Encrypter = encrypt ss.privateKey = key } return ss, nil, 0 }