func (pc *ControlGRPCServer) SubscribeDeps(ctx context.Context, r *rpc.SubscribeDepsRequest) (*rpc.SubscribeDepsReply, error) { plugins := common.ToSubPlugins(r.Plugins) configTree := cdata.NewTree() requested := common.MetricToRequested(r.Requested) serrors := pc.control.SubscribeDeps(r.TaskId, requested, plugins, configTree) return &rpc.SubscribeDepsReply{Errors: common.NewErrors(serrors)}, nil }
func (pc *ControlGRPCServer) ValidateDeps(ctx context.Context, r *rpc.ValidateDepsRequest) (*rpc.ValidateDepsReply, error) { metrics := common.ToRequestedMetrics(r.Metrics) plugins := common.ToSubPlugins(r.Plugins) configTree := cdata.NewTree() serrors := pc.control.ValidateDeps(metrics, plugins, configTree) return &rpc.ValidateDepsReply{Errors: common.NewErrors(serrors)}, nil }
func TestCollectorJob(t *testing.T) { log.SetLevel(log.FatalLevel) cdt := cdata.NewTree() //TODO: kromar do something with tags? tags := map[string]map[string]string{} Convey("newCollectorJob()", t, func() { Convey("it returns an init-ed collectorJob", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj, ShouldHaveSameTypeAs, &collectorJob{}) }) }) Convey("StartTime()", t, func() { Convey("it should return the job starttime", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj.StartTime(), ShouldHaveSameTypeAs, time.Now()) }) }) Convey("Deadline()", t, func() { Convey("it should return the job daedline", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj.Deadline(), ShouldResemble, cj.(*collectorJob).deadline) }) }) Convey("Type()", t, func() { Convey("it should return the job type", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj.Type(), ShouldEqual, collectJobType) }) }) Convey("Errors()", t, func() { Convey("it should return the errors from the job", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj.Errors(), ShouldResemble, []error{}) }) }) Convey("AddErrors()", t, func() { Convey("it should append errors to the job", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) So(cj.Errors(), ShouldResemble, []error{}) e1 := errors.New("1") e2 := errors.New("2") e3 := errors.New("3") cj.AddErrors(e1) So(cj.Errors(), ShouldResemble, []error{e1}) cj.AddErrors(e2, e3) So(cj.Errors(), ShouldResemble, []error{e1, e2, e3}) }) }) Convey("Run()", t, func() { Convey("it should complete without errors", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt, "taskid", tags) cj.(*collectorJob).Run() So(cj.Errors(), ShouldResemble, []error{}) }) }) }
func TestCollectorJob(t *testing.T) { log.SetLevel(log.FatalLevel) cdt := cdata.NewTree() Convey("newCollectorJob()", t, func() { Convey("it returns an init-ed collectorJob", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj, ShouldHaveSameTypeAs, &collectorJob{}) }) }) Convey("StartTime()", t, func() { Convey("it should return the job starttime", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj.StartTime(), ShouldHaveSameTypeAs, time.Now()) }) }) Convey("Deadline()", t, func() { Convey("it should return the job daedline", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj.Deadline(), ShouldResemble, cj.(*collectorJob).deadline) }) }) Convey("Type()", t, func() { Convey("it should return the job type", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj.Type(), ShouldEqual, collectJobType) }) }) Convey("ReplChan()", t, func() { Convey("it should return the reply channel", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj.ReplChan(), ShouldHaveSameTypeAs, make(chan struct{})) }) }) // Convey("Metrics()", t, func() { // Convey("it should return the job metrics", func() { // cj := newCollectorJob([]core.MetricType{}, defaultDeadline, &mockCollector{}) // So(cj.Metrics(), ShouldResemble, []core.Metric{}) // }) // }) Convey("Errors()", t, func() { Convey("it should return the errors from the job", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) So(cj.Errors(), ShouldResemble, []error{}) }) }) Convey("Run()", t, func() { Convey("it should reply on the reply chan", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) go cj.(*collectorJob).Run() <-cj.(*collectorJob).replchan So(cj.Errors(), ShouldResemble, []error{}) }) }) }
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) }) }) }
// GetConfigTree converts config data for collection node in wmap into a proper cdata.ConfigDataTree func (c *CollectWorkflowMapNode) GetConfigTree() (*cdata.ConfigDataTree, error) { cdt := cdata.NewTree() // Iterate over config and attempt to convert into data nodes in the tree for ns_, cmap := range c.Config { ns := strings.Split(ns_, "/")[1:] cdn, err := configtoConfigDataNode(cmap, ns_) if err != nil { return nil, err } cdt.Add(ns, cdn) } return cdt, nil }
func TestValidateDeps(t *testing.T) { Convey("RPC client errors", t, func() { proxy := ControlProxy{Client: mockClient{RpcErr: true}} errs := proxy.ValidateDeps([]core.RequestedMetric{}, []core.SubscribedPlugin{}, cdata.NewTree()) So(errs, ShouldNotBeNil) So(len(errs), ShouldBeGreaterThan, 0) Convey("So the error should be passed through", func() { So(errs[0].Error(), ShouldResemble, rpcErr.Error()) }) }) Convey("Control.ValidateDeps returns an error", t, func() { reply := &rpc.ValidateDepsReply{ Errors: []*common.SnapError{&common.SnapError{ErrorFields: map[string]string{}, ErrorString: "test"}}, } proxy := ControlProxy{Client: mockClient{ValidateReply: reply}} errs := proxy.ValidateDeps([]core.RequestedMetric{}, []core.SubscribedPlugin{}, cdata.NewTree()) So(errs, ShouldNotBeNil) So(len(errs), ShouldEqual, 1) Convey("So the error should resemble 'test'", func() { So(errs[0].Error(), ShouldResemble, "test") }) }) Convey("Control.ValidateDeps returns successfully", t, func() { reply := &rpc.ValidateDepsReply{} proxy := ControlProxy{Client: mockClient{ValidateReply: reply}} errs := proxy.ValidateDeps([]core.RequestedMetric{}, []core.SubscribedPlugin{}, cdata.NewTree()) Convey("So the there should be no errors", func() { So(len(errs), ShouldEqual, 0) }) }) }
func TestQueuedJob(t *testing.T) { log.SetLevel(log.FatalLevel) cdt := cdata.NewTree() Convey("Job()", t, func() { Convey("it should return the underlying job", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) qj := newQueuedJob(cj) So(qj.Job(), ShouldEqual, cj) }) }) Convey("Promise()", t, func() { Convey("it should return the underlying promise", func() { cj := newCollectorJob([]core.RequestedMetric{}, defaultDeadline, &mockCollector{}, cdt) qj := newQueuedJob(cj) So(qj.Promise().IsComplete(), ShouldBeFalse) }) }) }
// GetConfigTree converts config data for collection node in wmap into a proper cdata.ConfigDataTree func (c *CollectWorkflowMapNode) GetConfigTree() (*cdata.ConfigDataTree, error) { cdt := cdata.NewTree() // Iterate over config and attempt to convert into data nodes in the tree for ns_, cmap := range c.Config { // Attempt to convert namespace string to proper namespace if !isValidNamespaceString(ns_) { return nil, errors.New(fmt.Sprintf("Invalid namespace: %v", ns_)) } ns := strings.Split(ns_, "/")[1:] cdn, err := configtoConfigDataNode(cmap, ns_) if err != nil { return nil, err } cdt.Add(ns, cdn) } return cdt, nil }
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 TestSubscriptionGroups_ProcessSpecifiedDynamicNegative(t *testing.T) { log.SetLevel(log.DebugLevel) c := New(getTestSGConfig()) lpe := newLstnToPluginEvents() c.eventManager.RegisterHandler("TestSubscriptionGroups_Process", lpe) c.Start() Convey("Loading a mock collector plugin", 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" mock1 := 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{mock1}) <-lpe.sub So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 1) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeTrue) plgKey := key(group.plugins[0]) So(group.metrics, ShouldContainKey, plgKey) metrics := group.metrics[plgKey].Metrics() // expected 1 subscribed metrics:`/intel/mock/host0/baz` So(len(metrics), ShouldEqual, 1) So(len(group.requestedMetrics), ShouldEqual, 1) So(metrics[0].Namespace().String(), ShouldEqual, group.requestedMetrics[0].Namespace().String()) mts1 := len(metrics) Convey("loading another mock", func() { anotherMock1 := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "anothermock", version: 1, config: cdata.NewNode(), } _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-anothermock1")) So(err, ShouldBeNil) <-lpe.load serrs := sg.Process() So(len(serrs), ShouldEqual, 0) So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 1) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeTrue) So(subscribedPluginsContain(group.plugins, anotherMock1), ShouldBeFalse) plgKey := key(group.plugins[0]) So(group.metrics, ShouldContainKey, plgKey) metrics := group.metrics[plgKey].Metrics() // expected 1 subscribed metrics:`/intel/mock/host0/baz` So(len(metrics), ShouldEqual, 1) So(len(group.requestedMetrics), ShouldEqual, 1) So(metrics[0].Namespace().String(), ShouldEqual, group.requestedMetrics[0].Namespace().String()) mts2 := len(metrics) So(mts1, ShouldEqual, mts2) }) }) }) }
func TestSubscriptionGroups_ProcessDynamicPositive(t *testing.T) { log.SetLevel(log.DebugLevel) c := New(getTestSGConfig()) lpe := newLstnToPluginEvents() c.eventManager.RegisterHandler("TestSubscriptionGroups_Process", lpe) c.Start() Convey("Loading a mock collector plugin", t, func() { _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-mock1")) So(err, ShouldBeNil) <-lpe.load Convey("ValidateDeps", func() { requested := mockRequestedMetric{namespace: core.NewNamespace("intel").AddDynamicElement("wild", "wild description")} mock1 := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "mock", version: 1, config: cdata.NewNode(), } cnode := cdata.NewNode() cnode.AddItem("password", ctypes.ConfigValueStr{Value: "secret"}) ctree := cdata.NewTree() ctree.Add([]string{"intel", "mock"}, cnode) sg := newSubscriptionGroups(c) So(sg, ShouldNotBeNil) errs := sg.ValidateDeps([]core.RequestedMetric{requested}, []core.SubscribedPlugin{mock1}, ctree) So(errs, ShouldBeNil) Convey("Subscription group created for requested metric with wildcards", func() { sg.Add("task-id", []core.RequestedMetric{requested}, ctree, []core.SubscribedPlugin{mock1}) <-lpe.sub So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 1) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeTrue) plgKey := key(group.plugins[0]) So(group.metrics, ShouldContainKey, plgKey) metrics := group.metrics[plgKey].Metrics() So(len(metrics), ShouldBeGreaterThan, 1) So(len(group.requestedMetrics), ShouldEqual, 1) mts1 := len(metrics) Convey("loading another mock", func() { anotherMock1 := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "anothermock", version: 1, config: cdata.NewNode(), } _, err := loadPlg(c, path.Join(helper.PluginFilePath("snap-plugin-collector-anothermock1"))) So(err, ShouldBeNil) <-lpe.load serrs := sg.Process() So(len(serrs), ShouldEqual, 0) So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 2) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeTrue) So(subscribedPluginsContain(group.plugins, anotherMock1), ShouldBeTrue) plgKey1 := key(group.plugins[0]) plgKey2 := key(group.plugins[1]) So(group.metrics, ShouldContainKey, plgKey1) So(group.metrics, ShouldContainKey, plgKey2) metricsPlg1 := group.metrics[plgKey1].Metrics() metricsPlg2 := group.metrics[plgKey2].Metrics() So(len(metricsPlg1), ShouldBeGreaterThan, 1) So(len(metricsPlg2), ShouldBeGreaterThan, 1) So(len(group.requestedMetrics), ShouldEqual, 1) mts2 := len(metricsPlg1) + len(metricsPlg2) So(mts2, ShouldBeGreaterThan, mts1) }) }) }) }) }
func TestSubscriptionGroups_ProcessStaticPositive(t *testing.T) { log.SetLevel(log.DebugLevel) c := New(getTestSGConfig()) lpe := newLstnToPluginEvents() c.eventManager.RegisterHandler("TestSubscriptionGroups_Process", lpe) c.Start() Convey("Loading a mock collector plugin", t, func() { _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-mock1")) So(err, ShouldBeNil) <-lpe.load Convey("Subscription group created for requested metric with no wildcards", func() { requested := mockRequestedMetric{namespace: core.NewNamespace("intel", "mock", "foo")} mock1 := 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{mock1}) <-lpe.sub So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 1) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeTrue) plgKey := key(group.plugins[0]) So(group.metrics, ShouldContainKey, plgKey) metrics := group.metrics[plgKey].Metrics() So(len(metrics), ShouldEqual, 1) So(len(group.requestedMetrics), ShouldEqual, 1) So(metrics[0].Namespace().String(), ShouldEqual, group.requestedMetrics[0].Namespace().String()) Convey("loading another mock", func() { mock2 := mockSubscribedPlugin{ typeName: core.CollectorPluginType, name: "mock", version: 2, config: cdata.NewNode(), } _, err := loadPlg(c, helper.PluginFilePath("snap-plugin-collector-mock2")) So(err, ShouldBeNil) <-lpe.load serrs := sg.Process() So(len(serrs), ShouldEqual, 0) So(len(sg.subscriptionMap), ShouldEqual, 1) group, ok := sg.subscriptionMap["task-id"] So(ok, ShouldBeTrue) So(group, ShouldNotBeNil) So(len(group.plugins), ShouldEqual, 1) So(subscribedPluginsContain(group.plugins, mock1), ShouldBeFalse) So(subscribedPluginsContain(group.plugins, mock2), ShouldBeTrue) plgKey := key(group.plugins[0]) So(group.metrics, ShouldContainKey, plgKey) metrics := group.metrics[plgKey].Metrics() So(len(metrics), ShouldEqual, 1) So(len(group.requestedMetrics), ShouldEqual, 1) So(metrics[0].Namespace().String(), ShouldEqual, group.requestedMetrics[0].Namespace().String()) }) }) }) }