func UnmarshalBody(t string, b []byte) (Body, error) { switch t { case PluginListType: return unmarshalAndHandleError(b, &PluginList{}) case PluginsLoadedType: return unmarshalAndHandleError(b, &PluginsLoaded{}) case PluginUnloadedType: return unmarshalAndHandleError(b, &PluginUnloaded{}) case PluginReturnedType: return unmarshalAndHandleError(b, &PluginReturned{}) case ScheduledTaskListReturnedType: return unmarshalAndHandleError(b, &ScheduledTaskListReturned{}) case ScheduledTaskReturnedType: return unmarshalAndHandleError(b, &ScheduledTaskReturned{}) case ScheduledTaskType: return unmarshalAndHandleError(b, &ScheduledTask{}) case AddScheduledTaskType: return unmarshalAndHandleError(b, &AddScheduledTask{}) case ScheduledTaskStartedType: return unmarshalAndHandleError(b, &ScheduledTaskStarted{}) case ScheduledTaskStoppedType: return unmarshalAndHandleError(b, &ScheduledTaskStopped{}) case ScheduledTaskRemovedType: return unmarshalAndHandleError(b, &ScheduledTaskRemoved{}) case ScheduledTaskEnabledType: return unmarshalAndHandleError(b, &ScheduledTaskEnabled{}) case MetricReturnedType: return unmarshalAndHandleError(b, &MetricReturned{}) case MetricsReturnedType: return unmarshalAndHandleError(b, &MetricsReturned{}) case ScheduledTaskWatchingEndedType: return unmarshalAndHandleError(b, &ScheduledTaskWatchingEnded{}) case TribeMemberListType: return unmarshalAndHandleError(b, &TribeMemberList{}) case TribeListAgreementType: return unmarshalAndHandleError(b, &TribeListAgreement{}) case TribeAddAgreementType: return unmarshalAndHandleError(b, &TribeAddAgreement{}) case TribeDeleteAgreementType: return unmarshalAndHandleError(b, &TribeDeleteAgreement{}) case TribeMemberShowType: return unmarshalAndHandleError(b, &TribeMemberShow{}) case TribeJoinAgreementType: return unmarshalAndHandleError(b, &TribeJoinAgreement{}) case TribeLeaveAgreementType: return unmarshalAndHandleError(b, &TribeLeaveAgreement{}) case TribeGetAgreementType: return unmarshalAndHandleError(b, &TribeGetAgreement{}) case PluginConfigItemType: return unmarshalAndHandleError(b, &PluginConfigItem{*cdata.NewNode()}) case SetPluginConfigItemType: return unmarshalAndHandleError(b, &SetPluginConfigItem{*cdata.NewNode()}) case DeletePluginConfigItemType: return unmarshalAndHandleError(b, &DeletePluginConfigItem{*cdata.NewNode()}) case ErrorType: return unmarshalAndHandleError(b, &Error{}) default: return nil, ErrCannotUnmarshalBody } }
func TestGetMetricConfigItem(t *testing.T) { Convey("Get a value of items from Metrics Config with no error", t, func() { // create config config := cdata.NewNode() config.AddItem("dummy_string", ctypes.ConfigValueStr{Value: dummy_str}) config.AddItem("dummy_bool", ctypes.ConfigValueBool{Value: dummy_bool}) config.AddItem("dummy_int", ctypes.ConfigValueInt{Value: dummy_int}) config.AddItem("dummy_float", ctypes.ConfigValueFloat{Value: dummy_float}) // create metric and set config metric := plugin.MetricType{} metric.Config_ = config Convey("string type of item", func() { result, err := GetMetricConfigItem(metric, "dummy_string") So(err, ShouldBeNil) So(result, ShouldEqual, dummy_str) }) Convey("bool type of item", func() { result, err := GetMetricConfigItem(metric, "dummy_bool") So(err, ShouldBeNil) So(result, ShouldEqual, dummy_bool) }) Convey("int type of item", func() { result, err := GetMetricConfigItem(metric, "dummy_int") So(err, ShouldBeNil) So(result, ShouldEqual, dummy_int) }) Convey("float type of item", func() { result, err := GetMetricConfigItem(metric, "dummy_float") So(err, ShouldBeNil) So(result, ShouldEqual, dummy_float) }) }) Convey("Try to get a value of items not defined in Metrics Config", t, func() { config := cdata.NewNode() config.AddItem("foo", ctypes.ConfigValueStr{Value: "foo_val"}) metric := plugin.MetricType{} metric.Config_ = config result, err := GetMetricConfigItem(metric, "foo_not_exist") So(err, ShouldNotBeNil) So(result, ShouldBeNil) }) Convey("No item defined in Metrics Config", t, func() { metric := plugin.MetricType{} metric.Config_ = cdata.NewNode() result, err := GetMetricConfigItem(metric, "foo") So(err, ShouldNotBeNil) So(result, ShouldBeNil) }) }
func TestMesos_getConfig(t *testing.T) { log.SetLevel(log.ErrorLevel) // Suppress warning messages from getConfig Convey("Get plugin configuration from snap global config", t, func() { Convey("When only a master is provided, getConfig() should return only the master value", func() { node := cdata.NewNode() node.AddItem("master", ctypes.ConfigValueStr{Value: "mesos-master.example.com:5050"}) snapCfg := plugin.ConfigType{ConfigDataNode: node} parsedCfg, err := getConfig(snapCfg) So(parsedCfg["master"], ShouldEqual, "mesos-master.example.com:5050") So(parsedCfg["agent"], ShouldEqual, "") So(err, ShouldBeNil) }) Convey("When only an agent is provided, getConfig() should return only the agent value", func() { node := cdata.NewNode() node.AddItem("agent", ctypes.ConfigValueStr{Value: "mesos-agent.example.com:5051"}) snapCfg := plugin.ConfigType{ConfigDataNode: node} parsedCfg, err := getConfig(snapCfg) So(parsedCfg["master"], ShouldEqual, "") So(parsedCfg["agent"], ShouldEqual, "mesos-agent.example.com:5051") So(err, ShouldBeNil) }) Convey("When both a master and an agent are provided, getConfig() should return both values", func() { node := cdata.NewNode() node.AddItem("master", ctypes.ConfigValueStr{Value: "mesos-master.example.com:5050"}) node.AddItem("agent", ctypes.ConfigValueStr{Value: "mesos-agent.example.com:5051"}) snapCfg := plugin.ConfigType{ConfigDataNode: node} parsedCfg, err := getConfig(snapCfg) So(len(parsedCfg), ShouldEqual, 2) So(err, ShouldBeNil) }) Convey("When both master and agent are missing, getConfig() should return an error", func() { node := cdata.NewNode() node.AddItem("foo", ctypes.ConfigValueStr{Value: "bar"}) snapCfg := plugin.ConfigType{ConfigDataNode: node} parsedCfg, err := getConfig(snapCfg) So(len(parsedCfg), ShouldEqual, 0) So(err, ShouldNotBeNil) }) }) }
func testingConfig() (cfg1 plugin.ConfigType, cfg2 *cdata.ConfigDataNode) { cfg1 = plugin.NewPluginConfigType() cfg2 = cdata.NewNode() cfg1.AddItem("openstack_user", ctypes.ConfigValueStr{Value: "x"}) cfg1.AddItem("openstack_pass", ctypes.ConfigValueStr{Value: "x"}) cfg1.AddItem("openstack_tenant", ctypes.ConfigValueStr{Value: "asdf"}) cfg1.AddItem("openstack_auth_url", ctypes.ConfigValueStr{Value: "x"}) cfg2.AddItem("openstack_user", ctypes.ConfigValueStr{Value: "x"}) cfg2.AddItem("openstack_pass", ctypes.ConfigValueStr{Value: "x"}) cfg2.AddItem("openstack_tenant", ctypes.ConfigValueStr{Value: "asdf"}) cfg2.AddItem("openstack_auth_url", ctypes.ConfigValueStr{Value: "x"}) cfg1.AddItem("allocation_ratio_cores", ctypes.ConfigValueFloat{Value: 3}) cfg1.AddItem("allocation_ratio_ram", ctypes.ConfigValueFloat{Value: 4}) cfg1.AddItem("reserved_node_cores", ctypes.ConfigValueFloat{Value: 5}) cfg1.AddItem("reserved_node_ram_mb", ctypes.ConfigValueFloat{Value: 6}) cfg2.AddItem("allocation_ratio_cores", ctypes.ConfigValueFloat{Value: 3}) cfg2.AddItem("allocation_ratio_ram", ctypes.ConfigValueFloat{Value: 4}) cfg2.AddItem("reserved_node_cores", ctypes.ConfigValueFloat{Value: 5}) cfg2.AddItem("reserved_node_ram_mb", ctypes.ConfigValueFloat{Value: 6}) return cfg1, cfg2 }
func configtoConfigDataNode(cmap map[string]interface{}, ns string) (*cdata.ConfigDataNode, error) { cdn := cdata.NewNode() for ck, cv := range cmap { switch v := cv.(type) { case string: cdn.AddItem(ck, ctypes.ConfigValueStr{Value: v}) case int: cdn.AddItem(ck, ctypes.ConfigValueInt{Value: v}) case float64: //working around the fact that json decodes numbers to floats //if we can convert the number to an int without loss it will be an int if v == float64(int(v)) { cdn.AddItem(ck, ctypes.ConfigValueInt{Value: int(v)}) } else { cdn.AddItem(ck, ctypes.ConfigValueFloat{Value: v}) } case bool: cdn.AddItem(ck, ctypes.ConfigValueBool{Value: v}) default: // TODO make sure this is covered in tests!!! return nil, errors.New(fmt.Sprintf("Cannot convert config value to config data node: %s=>%+v", ns, v)) } } return cdn, nil }
func setupCfg(endpoint, user, password, tenant string) plugin.ConfigType { node := cdata.NewNode() node.AddItem("endpoint", ctypes.ConfigValueStr{Value: endpoint}) node.AddItem("user", ctypes.ConfigValueStr{Value: user}) node.AddItem("password", ctypes.ConfigValueStr{Value: password}) node.AddItem("tenant", ctypes.ConfigValueStr{Value: tenant}) return plugin.ConfigType{ConfigDataNode: node} }
func TestGetMetricConfigItems(t *testing.T) { Convey("Get values of items from Metrics Config with no error", t, func() { // create config config := cdata.NewNode() config.AddItem("dummy_string", ctypes.ConfigValueStr{Value: dummy_str}) config.AddItem("dummy_bool", ctypes.ConfigValueBool{Value: dummy_bool}) config.AddItem("dummy_int", ctypes.ConfigValueInt{Value: dummy_int}) config.AddItem("dummy_float", ctypes.ConfigValueFloat{Value: dummy_float}) // create metric and set config metric := plugin.MetricType{} metric.Config_ = config names := []string{"dummy_string", "dummy_bool", "dummy_int", "dummy_float"} result, err := GetMetricConfigItems(metric, names) So(err, ShouldBeNil) for _, name := range names { So(result[name], ShouldNotBeEmpty) } }) Convey("Try to get values of items not defined in Metrics config", t, func() { config := cdata.NewNode() config.AddItem("foo", ctypes.ConfigValueStr{Value: "foo_val"}) metric := plugin.MetricType{} metric.Config_ = config names := []string{"foo1", "foo2"} result, err := GetMetricConfigItems(metric, names) So(err, ShouldNotBeNil) So(result, ShouldBeNil) }) Convey("No item defined in Metrics Config", t, func() { metric := plugin.MetricType{} metric.Config_ = cdata.NewNode() names := []string{"foo", "bar"} result, err := GetMetricConfigItems(metric, names) So(err, ShouldNotBeNil) So(result, ShouldBeNil) }) }
func newPluginConfig() *pluginConfig { return &pluginConfig{ All: cdata.NewNode(), Collector: newPluginTypeConfigItem(), Processor: newPluginTypeConfigItem(), Publisher: newPluginTypeConfigItem(), pluginCache: make(map[string]*cdata.ConfigDataNode), } }
func getMockMetricConfig() *cdata.ConfigDataNode { // mocking metric config cfg := cdata.NewNode() cfg.AddItem("host", ctypes.ConfigValueStr{Value: "hostname"}) cfg.AddItem("port", ctypes.ConfigValueInt{Value: 1234}) cfg.AddItem("user", ctypes.ConfigValueStr{Value: "test"}) cfg.AddItem("password", ctypes.ConfigValueStr{Value: "passwd"}) return cfg }
func (p *ConfigType) UnmarshalJSON(data []byte) error { cdn := cdata.NewNode() dec := json.NewDecoder(bytes.NewReader(data)) dec.UseNumber() if err := dec.Decode(cdn); err != nil { return err } p.ConfigDataNode = cdn return nil }
func (p *ConfigType) GobDecode(data []byte) error { cdn := cdata.NewNode() decoder := gob.NewDecoder(bytes.NewReader(data)) if err := decoder.Decode(cdn); err != nil { return err } p.ConfigDataNode = cdn return nil }
func TestPublishMetrics(t *testing.T) { Convey("Given an available file publisher plugin", t, func() { // adjust HB timeouts for test plugin.PingTimeoutLimit = 1 plugin.PingTimeoutDurationDefault = time.Second * 1 // Create controller config := NewConfig() c := New(OptSetConfig(config)) lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("TestPublishMetrics", lpe) c.pluginRunner.(*runner).monitor.duration = time.Millisecond * 100 c.Start() time.Sleep(1 * time.Second) // Load plugin _, err := load(c, path.Join(SnapPath, "plugin", "snap-publisher-file")) <-lpe.done So(err, ShouldBeNil) So(len(c.pluginManager.all()), ShouldEqual, 1) lp, err2 := c.pluginManager.get("publisher:file:3") So(err2, ShouldBeNil) So(lp.Name(), ShouldResemble, "file") So(lp.ConfigPolicy, ShouldNotBeNil) Convey("Subscribe to file publisher with good config", func() { n := cdata.NewNode() config.Plugins.Publisher.Plugins[lp.Name()] = newPluginConfigItem(optAddPluginConfigItem("file", ctypes.ConfigValueStr{Value: "/tmp/snap-TestPublishMetrics.out"})) pool, errp := c.pluginRunner.AvailablePlugins().getOrCreatePool("publisher:file:3") So(errp, ShouldBeNil) pool.subscribe("1", unboundSubscriptionType) err := c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) time.Sleep(2500 * time.Millisecond) Convey("Publish to file", func() { metrics := []plugin.PluginMetricType{ *plugin.NewPluginMetricType([]string{"foo"}, time.Now(), "", nil, nil, 1), } var buf bytes.Buffer enc := gob.NewEncoder(&buf) enc.Encode(metrics) contentType := plugin.SnapGOBContentType errs := c.PublishMetrics(contentType, buf.Bytes(), "file", 3, n.Table()) So(errs, ShouldBeNil) ap := c.AvailablePlugins() So(ap, ShouldNotBeEmpty) }) }) c.Stop() time.Sleep(100 * time.Millisecond) }) }
func newPluginConfigItem(opts ...pluginConfigOpt) *pluginConfigItem { p := &pluginConfigItem{ ConfigDataNode: cdata.NewNode(), Versions: make(map[int]*cdata.ConfigDataNode), } for _, opt := range opts { opt(p) } return p }
func TestSubscriptionGroups_GetSpecifiedDynamic(t *testing.T) { log.SetLevel(log.DebugLevel) c := New(getTestSGConfig()) lpe := newLstnToPluginEvents() c.eventManager.RegisterHandler("TestSubscriptionGroups_AddRemove", lpe) c.Start() Convey("Loading a mock collector plugn", t, func() { _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-mock1")) So(err, ShouldBeNil) <-lpe.load Convey("Subscription group created for requested metric with specified instance of dynamic element", func() { requested := mockRequestedMetric{namespace: core.NewNamespace("intel", "mock").AddDynamicElement("host", "name of the host").AddStaticElement("baz")} // specified dynamic element requested.Namespace()[2].Value = "host0" subsPlugin := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "mock", version: 1, config: cdata.NewNode(), } subsPluginKey := key(subsPlugin) sg := newSubscriptionGroups(c) So(sg, ShouldNotBeNil) sg.Add("task-id", []core.RequestedMetric{requested}, cdata.NewTree(), []core.SubscribedPlugin{subsPlugin}) <-lpe.sub So(len(sg.subscriptionMap), ShouldEqual, 1) val, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(val, ShouldNotBeNil) pluginToMetricMap, serrs, err := sg.Get("task-id") So(len(serrs), ShouldEqual, 0) So(err, ShouldBeNil) So(len(pluginToMetricMap), ShouldEqual, 1) So(pluginToMetricMap, ShouldContainKey, subsPluginKey) metrics := pluginToMetricMap[subsPluginKey].Metrics() So(len(metrics), ShouldEqual, 1) pluginToMetricMap, serrs, err = sg.Get("task-fake-id") So(len(serrs), ShouldEqual, 0) So(err, ShouldNotBeNil) So(err, ShouldResemble, ErrSubscriptionGroupDoesNotExist) So(pluginToMetricMap, ShouldBeEmpty) }) }) }
func (p *pluginConfig) getPluginConfigDataNode(pluginType core.PluginType, name string, ver int) *cdata.ConfigDataNode { // check cache key := fmt.Sprintf("%d:%s:%d", pluginType, name, ver) if res, ok := p.pluginCache[key]; ok { return res } //todo process/interpolate values p.pluginCache[key] = cdata.NewNode() p.pluginCache[key].Merge(p.All) // check for plugin config switch pluginType { case core.CollectorPluginType: p.pluginCache[key].Merge(p.Collector.All) if res, ok := p.Collector.Plugins[name]; ok { p.pluginCache[key].Merge(res.ConfigDataNode) if res2, ok2 := res.Versions[ver]; ok2 { p.pluginCache[key].Merge(res2) } } case core.ProcessorPluginType: p.pluginCache[key].Merge(p.Processor.All) if res, ok := p.Processor.Plugins[name]; ok { p.pluginCache[key].Merge(res.ConfigDataNode) if res2, ok2 := res.Versions[ver]; ok2 { p.pluginCache[key].Merge(res2) } } case core.PublisherPluginType: p.pluginCache[key].Merge(p.Publisher.All) if res, ok := p.Publisher.Plugins[name]; ok { p.pluginCache[key].Merge(res.ConfigDataNode) if res2, ok2 := res.Versions[ver]; ok2 { p.pluginCache[key].Merge(res2) } } } //todo change to debug log.WithFields(log.Fields{ "_block_": "getPluginConfigDataNode", "_module": "config", "config-cache-key": key, "config-cache-value": p.pluginCache[key], }).Debug("Getting plugin config") return p.pluginCache[key] }
func TestConfigItems(t *testing.T) { names := []string{"dummy_string", "dummy_bool", "dummy_int", "dummy_float"} Convey("Get values of configuration items with no error", t, func() { Convey("Source: global config", func() { //create global config and add item (different types) cfg := plugin.NewPluginConfigType() cfg.AddItem("dummy_string", ctypes.ConfigValueStr{Value: dummy_str}) cfg.AddItem("dummy_bool", ctypes.ConfigValueBool{Value: dummy_bool}) cfg.AddItem("dummy_int", ctypes.ConfigValueInt{Value: dummy_int}) cfg.AddItem("dummy_float", ctypes.ConfigValueFloat{Value: dummy_float}) result, err := GetConfigItems(cfg, names...) So(err, ShouldBeNil) for _, name := range names { So(result[name], ShouldNotBeEmpty) } }) Convey("Source: metrics config", func() { // create metrics config config := cdata.NewNode() config.AddItem("dummy_string", ctypes.ConfigValueStr{Value: dummy_str}) config.AddItem("dummy_bool", ctypes.ConfigValueBool{Value: dummy_bool}) config.AddItem("dummy_int", ctypes.ConfigValueInt{Value: dummy_int}) config.AddItem("dummy_float", ctypes.ConfigValueFloat{Value: dummy_float}) // create metric and set config metric := plugin.MetricType{} metric.Config_ = config result, err := GetConfigItems(metric, names...) So(err, ShouldBeNil) for _, name := range names { So(result[name], ShouldNotBeEmpty) } }) }) Convey("Try to get values of items from invalid config (unsupported type)", t, func() { invalid_cfg := []string{"invalid", "config", "source"} result, err := GetConfigItems(invalid_cfg, names...) So(err, ShouldNotBeNil) So(result, ShouldBeNil) }) }
// setupCfg builds a new ConfigDataNode that specifies the Mesos master and agent host / port // to use in the integration test(s). func setupCfg() plugin.ConfigType { master := os.Getenv("SNAP_MESOS_MASTER") if master == "" { master = "127.0.0.1:5050" } agent := os.Getenv("SNAP_MESOS_AGENT") if agent == "" { agent = "127.0.0.1:5051" } node := cdata.NewNode() node.AddItem("master", ctypes.ConfigValueStr{Value: master}) node.AddItem("agent", ctypes.ConfigValueStr{Value: agent}) return plugin.ConfigType{ConfigDataNode: node} }
func (c *collectorJob) Run() { log.WithFields(log.Fields{ "_module": "scheduler-job", "block": "run", "job-type": "collector", "metric-count": len(c.metricTypes), }).Debug("starting collector job") metrics := make([]core.Metric, len(c.metricTypes)) for i, rmt := range c.metricTypes { config := c.configDataTree.Get(rmt.Namespace()) if config == nil { config = cdata.NewNode() } metrics[i] = &metric{ namespace: rmt.Namespace(), version: rmt.Version(), config: config, } } ret, errs := c.collector.CollectMetrics(metrics, c.Deadline()) log.WithFields(log.Fields{ "_module": "scheduler-job", "block": "run", "job-type": "collector", "metric-count": len(ret), }).Debug("collector run completed") c.metrics = ret if errs != nil { for _, e := range errs { log.WithFields(log.Fields{ "_module": "scheduler-job", "block": "run", "job-type": "collector", "error": e, }).Error("collector run error") } c.errors = errs } c.replchan <- struct{}{} }
func TestSubscriptionGroups_AddRemoveDynamic(t *testing.T) { log.SetLevel(log.DebugLevel) c := New(getTestSGConfig()) lpe := newLstnToPluginEvents() c.eventManager.RegisterHandler("TestSubscriptionGroups_AddRemove", lpe) c.Start() Convey("Loading a mock collector plugn", t, func() { _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-mock1")) So(err, ShouldBeNil) <-lpe.load Convey("Subscription group created for requested metric with wildcards", func() { requested := mockRequestedMetric{ namespace: core.NewNamespace("intel", "mock").AddDynamicElement("wild", "wild description"), version: -1, } subsPlugin := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "mock", version: 1, config: cdata.NewNode(), } sg := newSubscriptionGroups(c) So(sg, ShouldNotBeNil) sg.Add("task-id", []core.RequestedMetric{requested}, cdata.NewTree(), []core.SubscribedPlugin{subsPlugin}) <-lpe.sub So(len(sg.subscriptionMap), ShouldEqual, 1) val, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(val, ShouldNotBeNil) serrs := sg.Remove("task-id") <-lpe.unsub So(len(serrs), ShouldEqual, 0) So(len(sg.subscriptionMap), ShouldEqual, 0) }) }) }
func (s *Server) setPluginConfigItem(w http.ResponseWriter, r *http.Request, p httprouter.Params) { var err error var typ core.PluginType styp := p.ByName("type") if styp != "" { typ, err = getPluginType(styp) if err != nil { respond(400, rbody.FromError(err), w) return } } name := p.ByName("name") sver := p.ByName("version") var iver int if sver != "" { if iver, err = strconv.Atoi(sver); err != nil { respond(400, rbody.FromError(err), w) return } } else { iver = -2 } src := cdata.NewNode() errCode, err := core.UnmarshalBody(src, r.Body) if errCode != 0 && err != nil { respond(400, rbody.FromError(err), w) return } var res cdata.ConfigDataNode if styp == "" { res = s.mc.MergePluginConfigDataNodeAll(src) } else { res = s.mc.MergePluginConfigDataNode(typ, name, iver, src) } item := &rbody.SetPluginConfigItem{ConfigDataNode: res} respond(200, item, w) }
func (c *collectorPluginProxy) GetMetricTypes(args []byte, reply *[]byte) error { defer catchPluginPanic(c.Session.Logger()) c.Session.Logger().Println("GetMetricTypes called") // Reset heartbeat c.Session.ResetHeartbeat() dargs := &GetMetricTypesArgs{PluginConfig: PluginConfigType{ConfigDataNode: cdata.NewNode()}} c.Session.Decode(args, dargs) mts, err := c.Plugin.GetMetricTypes(dargs.PluginConfig) if err != nil { return errors.New(fmt.Sprintf("GetMetricTypes call error : %s", err.Error())) } r := GetMetricTypesReply{PluginMetricTypes: mts} *reply, err = c.Session.Encode(r) if err != nil { return err } return nil }
func TestLibirtPlugin(t *testing.T) { Convey("Meta should return metadata for the plugin", t, func() { meta := Meta() So(meta.Name, ShouldResemble, Name) So(meta.Version, ShouldResemble, Version) So(meta.Type, ShouldResemble, plugin.CollectorPluginType) }) Convey("Create Osv Collector", t, func() { osvCol := NewOsvCollector() Convey("So psCol should not be nil", func() { So(osvCol, ShouldNotBeNil) }) Convey("So psCol should be of Osv type", func() { So(osvCol, ShouldHaveSameTypeAs, &Osv{}) }) Convey("osvCol.GetConfigPolicy() should return a config policy", func() { configPolicy, _ := osvCol.GetConfigPolicy() Convey("So config policy should not be nil", func() { So(configPolicy, ShouldNotBeNil) }) Convey("So config policy should be a cpolicy.ConfigPolicy", func() { So(configPolicy, ShouldHaveSameTypeAs, &cpolicy.ConfigPolicy{}) }) }) }) Convey("Join namespace ", t, func() { namespace1 := []string{"intel", "osv", "one"} namespace2 := []string{} Convey("So namespace should equal intel/osv/one", func() { So("/intel/osv/one", ShouldResemble, joinNamespace(namespace1)) }) Convey("So namespace should equal slash", func() { So("/", ShouldResemble, joinNamespace(namespace2)) }) }) Convey("Get URI ", t, func() { Convey("So should return 10.1.0.1:8000", func() { swagIP := "10.1.0.1" swagPort := 8000 uri := osvRestURL(swagIP, swagPort) So("http://10.1.0.1:8000", ShouldResemble, uri) }) }) Convey("Get Metrics ", t, func() { osvCol := NewOsvCollector() cfgNode := cdata.NewNode() var cfg = plugin.PluginConfigType{ ConfigDataNode: cfgNode, } Convey("So should return 187 types of metrics", func() { metrics, err := osvCol.GetMetricTypes(cfg) So(187, ShouldResemble, len(metrics)) So(err, ShouldBeNil) }) Convey("So should check namespace", func() { metrics, err := osvCol.GetMetricTypes(cfg) waitNamespace := joinNamespace(metrics[0].Namespace()) wait := regexp.MustCompile(`^/osv/trace/virtio/virtio_wait_for_queue`) So(true, ShouldEqual, wait.MatchString(waitNamespace)) So(err, ShouldBeNil) }) }) Convey("Get Metrics ", t, func() { osvCol := NewOsvCollector() cfgNode := cdata.NewNode() cfgNode.AddItem("swagIP", ctypes.ConfigValueStr{Value: "192.168.192.200"}) cfgNode.AddItem("swagPort", ctypes.ConfigValueInt{Value: 8000}) httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/os/memory/free", func(req *http.Request) (*http.Response, error) { resp := httpmock.NewStringResponse(200, "20000") return resp, nil }, ) httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/trace/count", func(req *http.Request) (*http.Response, error) { resp := httpmock.NewStringResponse(200, `{"time_ms": 144123232, "list": []}`) return resp, nil }, ) defer httpmock.DeactivateAndReset() httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/trace/count", func(req *http.Request) (*http.Response, error) { resp := httpmock.NewStringResponse(200, `{"time_ms": 144123232, "list": [{"name": "waitqueue_wake_one", "count": 1000}]}`) return resp, nil }, ) Convey("So should get memory metrics", func() { metrics := []plugin.PluginMetricType{{ Namespace_: []string{"osv", "memory", "free"}, Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(len(collect), ShouldResemble, 1) }) Convey("So should get cpu metrics", func() { metrics := []plugin.PluginMetricType{{ Namespace_: []string{"osv", "cpu", "cputime"}, Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(collect[0].Data_, ShouldResemble, "144123232") So(len(collect), ShouldResemble, 1) }) Convey("So should get trace metrics", func() { metrics := []plugin.PluginMetricType{{ Namespace_: []string{"osv", "trace", "wait", "waitqueue_wake_one"}, Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(collect[0].Data_, ShouldResemble, "1000") So(len(collect), ShouldResemble, 1) }) }) }
func TestLibirtPlugin(t *testing.T) { httpmock.Mock = true Convey("Meta should return metadata for the plugin", t, func() { meta := Meta() So(meta.Name, ShouldResemble, Name) So(meta.Version, ShouldResemble, Version) So(meta.Type, ShouldResemble, plugin.CollectorPluginType) }) Convey("Create Osv Collector", t, func() { osvCol := NewOsvCollector() Convey("So psCol should not be nil", func() { So(osvCol, ShouldNotBeNil) }) Convey("So psCol should be of Osv type", func() { So(osvCol, ShouldHaveSameTypeAs, &Osv{}) }) Convey("osvCol.GetConfigPolicy() should return a config policy", func() { configPolicy, _ := osvCol.GetConfigPolicy() Convey("So config policy should not be nil", func() { So(configPolicy, ShouldNotBeNil) }) Convey("So config policy should be a cpolicy.ConfigPolicy", func() { So(configPolicy, ShouldHaveSameTypeAs, &cpolicy.ConfigPolicy{}) }) }) }) Convey("Get URI ", t, func() { Convey("So should return 10.1.0.1:8000", func() { swagIP := "10.1.0.1" swagPort := 8000 uri := osvRestURL(swagIP, swagPort) So("http://10.1.0.1:8000", ShouldResemble, uri) }) }) Convey("Get Metrics ", t, func() { osvCol := NewOsvCollector() cfgNode := cdata.NewNode() var cfg = plugin.ConfigType{ ConfigDataNode: cfgNode, } Convey("So should return 187 types of metrics", func() { metrics, err := osvCol.GetMetricTypes(cfg) So(187, ShouldResemble, len(metrics)) So(err, ShouldBeNil) }) Convey("So should check namespace", func() { metrics, err := osvCol.GetMetricTypes(cfg) waitNamespace := metrics[0].Namespace().String() wait := regexp.MustCompile(`^/intel/osv/trace/virtio/virtio_wait_for_queue`) So(true, ShouldEqual, wait.MatchString(waitNamespace)) So(err, ShouldBeNil) }) }) Convey("Get Metrics ", t, func() { osvCol := NewOsvCollector() cfgNode := cdata.NewNode() cfgNode.AddItem("swagIP", ctypes.ConfigValueStr{Value: "192.168.192.200"}) cfgNode.AddItem("swagPort", ctypes.ConfigValueInt{Value: 8000}) defer httpmock.ResetResponders() httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/os/memory/free", "20000", 200) httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/trace/count", `{"time_ms": 144123232, "list": [{"name": "waitqueue_wake_one", "count": 1000}]}`, 200) Convey("So should get memory metrics", func() { metrics := []plugin.MetricType{{ Namespace_: core.NewNamespace("intel", "osv", "memory", "free"), Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(len(collect), ShouldResemble, 1) }) Convey("So should get cpu metrics", func() { metrics := []plugin.MetricType{{ Namespace_: core.NewNamespace("intel", "osv", "cpu", "cputime"), Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(collect[0].Data_, ShouldEqual, 144123232) So(len(collect), ShouldEqual, 1) }) Convey("So should get trace metrics", func() { metrics := []plugin.MetricType{{ Namespace_: core.NewNamespace("intel", "osv", "trace", "wait", "waitqueue_wake_one"), Config_: cfgNode, }} collect, err := osvCol.CollectMetrics(metrics) So(err, ShouldBeNil) So(collect[0].Data_, ShouldNotBeNil) So(collect[0].Data_, ShouldEqual, 1000) So(len(collect), ShouldEqual, 1) }) }) }
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.PluginMetricType{ Namespace_: []string{"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.PluginMetricType{ Namespace_: []string{"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") }) }) }) Convey("Processor Client", t, func() { session.c = false p, _ := NewProcessorHttpJSONRPCClient(fmt.Sprintf("http://%v", addr), 1*time.Second, &key.PublicKey, true) cl := p.(*httpJSONRPCClient) cl.encrypter.Key = symkey So(p, ShouldNotBeNil) Convey("GetConfigPolicy", func() { cp, err := p.GetConfigPolicy() So(err, ShouldBeNil) So(cp, ShouldNotBeNil) cp_ := cpolicy.New() cpn_ := cpolicy.NewPolicyNode() r1, err := cpolicy.NewIntegerRule("SomeRequiredInt", true, 1) r2, _ := cpolicy.NewStringRule("password", true) r3, _ := cpolicy.NewFloatRule("somefloat", false, 3.14) So(err, ShouldBeNil) cpn_.Add(r1, r2, r3) cp_.Add([]string{""}, cpn_) cpjson, _ := cp.MarshalJSON() cp_json, _ := cp_.MarshalJSON() So(string(cpjson), ShouldResemble, string(cp_json)) }) Convey("Process metrics", func() { pmt := plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", nil, nil, 1) b, _ := json.Marshal([]plugin.PluginMetricType{*pmt}) contentType, content, err := p.Process(plugin.SnapJSONContentType, b, nil) So(contentType, ShouldResemble, plugin.SnapJSONContentType) So(content, ShouldNotBeNil) So(err, ShouldEqual, nil) var pmts []plugin.PluginMetricType err = json.Unmarshal(content, &pmts) So(err, ShouldBeNil) So(len(pmts), ShouldEqual, 1) So(pmts[0].Data(), ShouldEqual, 1) So(pmts[0].Namespace(), ShouldResemble, []string{"foo", "bar"}) }) }) Convey("Publisher Client", t, func() { session.c = false p, _ := NewPublisherHttpJSONRPCClient(fmt.Sprintf("http://%v", addr), 1*time.Second, &key.PublicKey, true) cl := p.(*httpJSONRPCClient) cl.encrypter.Key = symkey So(p, ShouldNotBeNil) Convey("GetConfigPolicy", func() { cp, err := p.GetConfigPolicy() So(err, ShouldBeNil) So(cp, ShouldNotBeNil) cp_ := cpolicy.New() cpn_ := cpolicy.NewPolicyNode() r1, err := cpolicy.NewIntegerRule("SomeRequiredInt", true, 1) r2, _ := cpolicy.NewStringRule("password", true) r3, _ := cpolicy.NewFloatRule("somefloat", false, 3.14) So(err, ShouldBeNil) cpn_.Add(r1, r2, r3) cp_.Add([]string{""}, cpn_) cpjson, _ := cp.MarshalJSON() cp_json, _ := cp_.MarshalJSON() So(string(cpjson), ShouldResemble, string(cp_json)) }) Convey("Publish metrics", func() { pmt := plugin.NewPluginMetricType([]string{"foo", "bar"}, time.Now(), "", nil, nil, 1) b, _ := json.Marshal([]plugin.PluginMetricType{*pmt}) err := p.Publish(plugin.SnapJSONContentType, b, nil) So(err, ShouldBeNil) }) }) }
func TestPluginRestCalls(t *testing.T) { CompressedUpload = false Convey("REST API functional V1", t, func() { Convey("Load Plugin - POST - /v1/plugins", func() { Convey("a single plugin loads", func() { // This test alone tests gzip. Saves on test time. CompressedUpload = true r := startAPI(getDefaultMockConfig()) port := r.port col := core.CollectorPluginType pub := core.PublisherPluginType Convey("A global plugin config is added for all plugins", func() { cdn := cdata.NewNode() cdn.AddItem("password", ctypes.ConfigValueStr{Value: "p@ssw0rd"}) r := setPluginConfigItem(port, "", "", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) r2 := getPluginConfigItem(port, &col, "", "") So(r2.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r3 := r2.Body.(*rbody.PluginConfigItem) So(len(r3.Table()), ShouldEqual, 1) So(r3.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) Convey("A plugin config is added for all publishers", func() { cdn := cdata.NewNode() cdn.AddItem("user", ctypes.ConfigValueStr{Value: "john"}) r := setPluginConfigItem(port, core.PublisherPluginType.String(), "", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(len(r1.Table()), ShouldEqual, 2) Convey("A plugin config is added for all versions of a publisher", func() { cdn := cdata.NewNode() cdn.AddItem("path", ctypes.ConfigValueStr{Value: "/usr/local/influxdb/bin"}) r := setPluginConfigItem(port, "2", "influxdb", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/influxdb/bin"}) So(len(r1.Table()), ShouldEqual, 3) Convey("A plugin config is added for a specific version of a publisher", func() { cdn := cdata.NewNode() cdn.AddItem("rate", ctypes.ConfigValueFloat{Value: .8}) r := setPluginConfigItem(port, core.PublisherPluginType.String(), "influxdb", "1", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["rate"], ShouldResemble, ctypes.ConfigValueFloat{Value: .8}) So(len(r1.Table()), ShouldEqual, 4) r2 := getPluginConfigItem(port, &pub, "", "") So(r2.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r3 := r2.Body.(*rbody.PluginConfigItem) So(len(r3.Table()), ShouldEqual, 2) r4 := getPluginConfigItem(port, &pub, "influxdb", "1") So(r4.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r5 := r4.Body.(*rbody.PluginConfigItem) So(len(r5.Table()), ShouldEqual, 4) Convey("A global plugin config field is deleted", func() { r := deletePluginConfigItem(port, "", "", "", []string{"password"}) So(r.Body, ShouldHaveSameTypeAs, &rbody.DeletePluginConfigItem{}) r1 := r.Body.(*rbody.DeletePluginConfigItem) So(len(r1.Table()), ShouldEqual, 0) r2 := setPluginConfigItem(port, core.PublisherPluginType.String(), "influxdb", "", cdn) So(r2.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r3 := r2.Body.(*rbody.SetPluginConfigItem) So(len(r3.Table()), ShouldEqual, 3) }) }) }) }) }) }) Convey("Plugin config is set at startup", func() { cfg := getDefaultMockConfig() err := cfgfile.Read("../../examples/configs/snap-config-sample.json", &cfg, MOCK_CONSTRAINTS) So(err, ShouldBeNil) if len(SNAP_AUTODISCOVER_PATH) == 0 { if len(SNAP_PATH) != 0 { SNAP_AUTODISCOVER_PATH = fmt.Sprintf("%s/plugin", SNAP_PATH) log.Warning(fmt.Sprintf("SNAP_AUTODISCOVER_PATH has been set to SNAP_PATH/plugin (%s). This might cause test failures", SNAP_AUTODISCOVER_PATH)) } } else { log.Warning(fmt.Sprintf("SNAP_AUTODISCOVER_PATH is set to %s. This might cause test failures", SNAP_AUTODISCOVER_PATH)) } cfg.Control.AutoDiscoverPath = SNAP_AUTODISCOVER_PATH r := startAPI(cfg) port := r.port col := core.CollectorPluginType Convey("Gets the collector config by name and version", func() { r := getPluginConfigItem(port, &col, "pcm", "1") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(len(r1.Table()), ShouldEqual, 6) }) Convey("Gets the config for a collector by name", func() { r := getPluginConfigItem(port, &col, "pcm", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) So(len(r1.Table()), ShouldEqual, 3) }) Convey("Gets the config for all collectors", func() { r := getPluginConfigItem(port, &col, "", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(len(r1.Table()), ShouldEqual, 2) }) Convey("Gets the config for all plugins", func() { r := getPluginConfigItem(port, nil, "", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(len(r1.Table()), ShouldEqual, 1) }) }) }) Convey("Enable task - put - /v1/tasks/:id/enable", func() { Convey("Enable a running task", func(c C) { r := startAPI(getDefaultMockConfig()) port := r.port uploadPlugin(MOCK_PLUGIN_PATH2, port) uploadPlugin(FILE_PLUGIN_PATH, port) r1 := createTask("1.json", "yeti", "1s", true, port) So(r1.Body, ShouldHaveSameTypeAs, new(rbody.AddScheduledTask)) plr1 := r1.Body.(*rbody.AddScheduledTask) id := plr1.ID r2 := startTask(id, port) So(r2.Body, ShouldHaveSameTypeAs, new(rbody.ScheduledTaskStarted)) plr2 := r2.Body.(*rbody.ScheduledTaskStarted) So(plr2.ID, ShouldEqual, id) r4 := enableTask(id, port) So(r4.Body, ShouldHaveSameTypeAs, new(rbody.Error)) plr4 := r4.Body.(*rbody.Error) So(plr4.ErrorMessage, ShouldEqual, "Task must be disabled") }) }) }) }
func TestCollectMetrics(t *testing.T) { Convey("given a loaded plugin", t, func() { // adjust HB timeouts for test plugin.PingTimeoutLimit = 1 plugin.PingTimeoutDurationDefault = time.Second * 1 // Create controller config := NewConfig() config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) c := New(OptSetConfig(config)) c.pluginRunner.(*runner).monitor.duration = time.Millisecond * 100 c.Start() lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) // Add a global plugin config c.Config.Plugins.Collector.Plugins["mock"] = newPluginConfigItem(optAddPluginConfigItem("test", ctypes.ConfigValueBool{Value: true})) // Load plugin load(c, JSONRPCPluginPath) <-lpe.done mts, err := c.MetricCatalog() So(err, ShouldBeNil) So(len(mts), ShouldEqual, 4) cd := cdata.NewNode() cd.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) m := []core.Metric{} m1 := MockMetricType{ namespace: []string{"intel", "mock", "foo"}, cfg: cd, } m2 := MockMetricType{ namespace: []string{"intel", "mock", "bar"}, cfg: cd, } m3 := MockMetricType{ namespace: []string{"intel", "mock", "test"}, cfg: cd, } // retrieve loaded plugin lp, err := c.pluginManager.get("collector:mock:1") So(err, ShouldBeNil) So(lp, ShouldNotBeNil) Convey("create a pool, add subscriptions and start plugins", func() { pool, errp := c.pluginRunner.AvailablePlugins().getOrCreatePool("collector:mock:1") So(errp, ShouldBeNil) pool.subscribe("1", unboundSubscriptionType) err = c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) pool.subscribe("2", unboundSubscriptionType) err = c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) m = append(m, m1, m2, m3) Convey("collect metrics", func() { for x := 0; x < 4; x++ { cr, err := c.CollectMetrics(m, time.Now().Add(time.Second*1)) So(err, ShouldBeNil) for i := range cr { So(cr[i].Data(), ShouldContainSubstring, "The mock collected data!") So(cr[i].Data(), ShouldContainSubstring, "test=true") } } ap := c.AvailablePlugins() So(ap, ShouldNotBeEmpty) So(pool.strategy.String(), ShouldEqual, plugin.DefaultRouting.String()) So(len(pool.plugins), ShouldEqual, 2) for _, p := range pool.plugins { So(p.hitCount, ShouldEqual, 2) So(p.hitCount, ShouldEqual, 2) } c.Stop() }) }) }) // Not sure what this was supposed to test, because it's actually testing nothing SkipConvey("Pool", t, func() { // adjust HB timeouts for test plugin.PingTimeoutLimit = 1 plugin.PingTimeoutDurationDefault = time.Second * 1 // Create controller c := New() c.pluginRunner.(*runner).monitor.duration = time.Millisecond * 100 c.Start() load(c, PluginPath) m := []core.Metric{} c.CollectMetrics(m, time.Now().Add(time.Second*60)) c.Stop() time.Sleep(100 * time.Millisecond) }) }
func TestCollectDynamicMetrics(t *testing.T) { Convey("given a plugin using the native client", t, func() { config := NewConfig() config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) c := New(OptSetConfig(config), CacheExpiration(time.Second*1)) c.Start() So(strategy.GlobalCacheExpiration, ShouldResemble, time.Second*1) lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) _, e := load(c, PluginPath) Convey("Loading native client plugin", func() { Convey("Should not error", func() { So(e, ShouldBeNil) }) }) if e != nil { t.FailNow() } <-lpe.done _, e = load(c, JSONRPCPluginPath) Convey("Loading JSONRPC client plugin", func() { Convey("Should not error", func() { So(e, ShouldBeNil) }) }) if e != nil { t.FailNow() } <-lpe.done cd := cdata.NewNode() metrics, err := c.metricCatalog.Fetch([]string{}) So(err, ShouldBeNil) So(len(metrics), ShouldEqual, 6) m, err := c.metricCatalog.Get([]string{"intel", "mock", "*", "baz"}, 2) So(err, ShouldBeNil) So(m, ShouldNotBeNil) jsonm, err := c.metricCatalog.Get([]string{"intel", "mock", "*", "baz"}, 1) So(err, ShouldBeNil) So(jsonm, ShouldNotBeNil) metric, errs := c.validateMetricTypeSubscription(m, cd) So(errs, ShouldBeNil) So(metric, ShouldNotBeNil) Convey("collects metrics from plugin using native client", func() { lp, err := c.pluginManager.get("collector:mock:2") So(err, ShouldBeNil) So(lp, ShouldNotBeNil) pool, errp := c.pluginRunner.AvailablePlugins().getOrCreatePool("collector:mock:2") So(errp, ShouldBeNil) So(pool, ShouldNotBeNil) ttl, err := pool.CacheTTL() So(err, ShouldResemble, ErrPoolEmpty) So(ttl, ShouldEqual, 0) pool.subscribe("1", unboundSubscriptionType) err = c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) ttl, err = pool.CacheTTL() So(err, ShouldBeNil) // The minimum TTL advertised by the plugin is 100ms therefore the TTL for the // pool should be the global cache expiration So(ttl, ShouldEqual, strategy.GlobalCacheExpiration) mts, errs := c.CollectMetrics([]core.Metric{m}, time.Now().Add(time.Second*1)) hits, err := pool.CacheHits(core.JoinNamespace(m.namespace), 2) So(err, ShouldBeNil) So(hits, ShouldEqual, 0) So(errs, ShouldBeNil) So(len(mts), ShouldEqual, 10) mts, errs = c.CollectMetrics([]core.Metric{m}, time.Now().Add(time.Second*1)) hits, err = pool.CacheHits(core.JoinNamespace(m.namespace), 2) So(err, ShouldBeNil) So(hits, ShouldEqual, 1) So(errs, ShouldBeNil) So(len(mts), ShouldEqual, 10) pool.unsubscribe("1") Convey("collects metrics from plugin using httpjson client", func() { lp, err := c.pluginManager.get("collector:mock:1") So(err, ShouldBeNil) So(lp, ShouldNotBeNil) pool, errp := c.pluginRunner.AvailablePlugins().getOrCreatePool("collector:mock:1") So(errp, ShouldBeNil) So(pool, ShouldNotBeNil) ttl, err := pool.CacheTTL() So(err, ShouldResemble, ErrPoolEmpty) So(ttl, ShouldEqual, 0) pool.subscribe("1", unboundSubscriptionType) err = c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) ttl, err = pool.CacheTTL() So(err, ShouldBeNil) So(ttl, ShouldEqual, 1100*time.Millisecond) mts, errs := c.CollectMetrics([]core.Metric{jsonm}, time.Now().Add(time.Second*1)) hits, err := pool.CacheHits(core.JoinNamespace(jsonm.namespace), jsonm.version) So(pool.subscriptionCount(), ShouldEqual, 1) So(pool.strategy, ShouldNotBeNil) So(len(mts), ShouldBeGreaterThan, 0) So(err, ShouldBeNil) So(hits, ShouldEqual, 0) So(errs, ShouldBeNil) So(len(mts), ShouldEqual, 10) mts, errs = c.CollectMetrics([]core.Metric{jsonm}, time.Now().Add(time.Second*1)) hits, err = pool.CacheHits(core.JoinNamespace(m.namespace), 1) So(err, ShouldBeNil) So(hits, ShouldEqual, 1) So(errs, ShouldBeNil) So(len(mts), ShouldEqual, 10) So(pool.AllCacheHits(), ShouldEqual, 1) So(pool.AllCacheMisses(), ShouldEqual, 1) pool.unsubscribe("1") c.Stop() time.Sleep(100 * time.Millisecond) }) }) }) }
func TestMetricConfig(t *testing.T) { Convey("required config provided by task", t, func() { c := New() c.Start() lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) load(c, JSONRPCPluginPath) <-lpe.done cd := cdata.NewNode() m1 := MockMetricType{ namespace: []string{"intel", "mock", "foo"}, } metric, errs := c.validateMetricTypeSubscription(m1, cd) Convey("So metric should not be valid without config", func() { So(metric, ShouldBeNil) So(errs, ShouldNotBeNil) }) cd.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) metric, errs = c.validateMetricTypeSubscription(m1, cd) Convey("So metric should be valid with config", func() { So(errs, ShouldBeNil) So(metric, ShouldNotBeNil) }) c.Stop() time.Sleep(100 * time.Millisecond) }) Convey("nil config provided by task", t, func() { config := NewConfig() config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) c := New(OptSetConfig(config)) c.Start() lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) load(c, JSONRPCPluginPath) <-lpe.done var cd *cdata.ConfigDataNode m1 := MockMetricType{ namespace: []string{"intel", "mock", "foo"}, } metric, errs := c.validateMetricTypeSubscription(m1, cd) Convey("So metric should be valid with config", func() { So(errs, ShouldBeNil) So(metric, ShouldNotBeNil) }) c.Stop() time.Sleep(100 * time.Millisecond) }) Convey("required config provided by global plugin config", t, func() { config := NewConfig() config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) c := New(OptSetConfig(config)) c.Start() lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) load(c, JSONRPCPluginPath) <-lpe.done cd := cdata.NewNode() m1 := MockMetricType{ namespace: []string{"intel", "mock", "foo"}, ver: 1, } metric, errs := c.validateMetricTypeSubscription(m1, cd) Convey("So metric should be valid with config", func() { So(errs, ShouldBeNil) So(metric, ShouldNotBeNil) }) c.Stop() time.Sleep(100 * time.Millisecond) }) }
func TestProcessMetrics(t *testing.T) { Convey("Given an available file processor plugin", t, func() { // adjust HB timeouts for test plugin.PingTimeoutLimit = 1 plugin.PingTimeoutDurationDefault = time.Second * 1 // Create controller c := New() lpe := newListenToPluginEvent() c.eventManager.RegisterHandler("TestProcessMetrics", lpe) c.pluginRunner.(*runner).monitor.duration = time.Millisecond * 100 c.Start() time.Sleep(1 * time.Second) c.Config.Plugins.Processor.Plugins["passthru"] = newPluginConfigItem(optAddPluginConfigItem("test", ctypes.ConfigValueBool{Value: true})) // Load plugin _, err := load(c, path.Join(SnapPath, "plugin", "snap-processor-passthru")) <-lpe.done So(err, ShouldBeNil) So(len(c.pluginManager.all()), ShouldEqual, 1) lp, err2 := c.pluginManager.get("processor:passthru:1") So(err2, ShouldBeNil) So(lp.Name(), ShouldResemble, "passthru") So(lp.ConfigPolicy, ShouldNotBeNil) Convey("Subscribe to passthru processor with good config", func() { n := cdata.NewNode() pool, errp := c.pluginRunner.AvailablePlugins().getOrCreatePool("processor:passthru:1") So(errp, ShouldBeNil) pool.subscribe("1", unboundSubscriptionType) err := c.pluginRunner.runPlugin(lp.Details) So(err, ShouldBeNil) time.Sleep(2500 * time.Millisecond) Convey("process metrics", func() { metrics := []plugin.PluginMetricType{ *plugin.NewPluginMetricType([]string{"foo"}, time.Now(), "", nil, nil, 1), } var buf bytes.Buffer enc := gob.NewEncoder(&buf) enc.Encode(metrics) contentType := plugin.SnapGOBContentType _, ct, errs := c.ProcessMetrics(contentType, buf.Bytes(), "passthru", 1, n.Table()) So(errs, ShouldBeEmpty) mts := []plugin.PluginMetricType{} dec := gob.NewDecoder(bytes.NewBuffer(ct)) err := dec.Decode(&mts) So(err, ShouldBeNil) So(mts[0].Data_, ShouldEqual, 2) So(errs, ShouldBeNil) }) }) Convey("Count()", func() { pmt := &pluginMetricTypes{} count := pmt.Count() So(count, ShouldResemble, 0) }) c.Stop() time.Sleep(100 * time.Millisecond) }) }
func NewPluginConfigType() ConfigType { return ConfigType{ ConfigDataNode: cdata.NewNode(), } }