diff --git a/control/control_test.go b/control/control_test.go index 9ea0d47e6..a2731bf8d 100644 --- a/control/control_test.go +++ b/control/control_test.go @@ -788,6 +788,32 @@ func TestMetricConfig(t *testing.T) { time.Sleep(100 * time.Millisecond) }) + Convey("config provided by defaults", t, func() { + c := New(GetDefaultConfig()) + c.Config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "pwd"}) + c.Start() + lpe := newListenToPluginEvent() + c.eventManager.RegisterHandler("Control.PluginLoaded", lpe) + _, err := load(c, fixtures.JSONRPCPluginPath) + So(err, ShouldBeNil) + <-lpe.done + cd := cdata.NewNode() + m1 := fixtures.MockMetricType{ + Namespace_: core.NewNamespace("intel", "mock", "foo"), + } + + Convey("So metric should be valid with config", func() { + errs := c.validateMetricTypeSubscription(m1, cd) + So(errs, ShouldBeNil) + }) + Convey("So mock should have name: bob config from defaults", func() { + So(c.Config.Plugins.pluginCache["0:mock:1"].Table()["name"], ShouldResemble, ctypes.ConfigValueStr{Value: "bob"}) + }) + + c.Stop() + time.Sleep(100 * time.Millisecond) + }) + Convey("nil config provided by task", t, func() { config := GetDefaultConfig() config.Plugins.All.AddItem("password", ctypes.ConfigValueStr{Value: "testval"}) @@ -1234,6 +1260,8 @@ func TestCollectMetrics(t *testing.T) { for i := range cr { So(cr[i].Data(), ShouldContainSubstring, "The mock collected data!") So(cr[i].Data(), ShouldContainSubstring, "test=true") + So(cr[i].Data(), ShouldContainSubstring, "name={bob}") + So(cr[i].Data(), ShouldContainSubstring, "password={testval}") } } ap := c.AvailablePlugins() diff --git a/control/plugin/client/httpjsonrpc_test.go b/control/plugin/client/httpjsonrpc_test.go index dbe73d5f0..756514bc5 100644 --- a/control/plugin/client/httpjsonrpc_test.go +++ b/control/plugin/client/httpjsonrpc_test.go @@ -240,7 +240,7 @@ func TestHTTPJSONRPC(t *testing.T) { 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((*cpn)["somefloat"].(ctypes.ConfigValueFloat).Value, ShouldResemble, 3.14) So(cserrs.Errors(), ShouldBeEmpty) }) }) diff --git a/control/plugin/cpolicy/bool.go b/control/plugin/cpolicy/bool.go index 2fce17e7b..6f194ee54 100644 --- a/control/plugin/cpolicy/bool.go +++ b/control/plugin/cpolicy/bool.go @@ -129,7 +129,7 @@ func (b *BoolRule) Validate(cv ctypes.ConfigValue) error { // Default returns a default value is it exists. func (b *BoolRule) Default() ctypes.ConfigValue { if b.default_ != nil { - return &ctypes.ConfigValueBool{Value: *b.default_} + return ctypes.ConfigValueBool{Value: *b.default_} } return nil } diff --git a/control/plugin/cpolicy/bool_test.go b/control/plugin/cpolicy/bool_test.go index 7fe154796..3a24fbbdd 100644 --- a/control/plugin/cpolicy/bool_test.go +++ b/control/plugin/cpolicy/bool_test.go @@ -54,7 +54,7 @@ func TestConfigPolicyRuleBool(t *testing.T) { r, e := NewBoolRule("thekey", true, true) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "bool") - So(r.Default().(*ctypes.ConfigValueBool).Value, ShouldEqual, true) + So(r.Default().(ctypes.ConfigValueBool).Value, ShouldEqual, true) So(e, ShouldBeNil) }) @@ -69,7 +69,7 @@ func TestConfigPolicyRuleBool(t *testing.T) { Convey("passes with string config value", func() { r, e := NewBoolRule("thekey", true, true) So(r.Default().Type(), ShouldEqual, "bool") - So(r.Default().(*ctypes.ConfigValueBool).Value, ShouldEqual, true) + So(r.Default().(ctypes.ConfigValueBool).Value, ShouldEqual, true) So(e, ShouldBeNil) v := ctypes.ConfigValueBool{Value: true} @@ -81,7 +81,7 @@ func TestConfigPolicyRuleBool(t *testing.T) { Convey("errors with non-string config value", func() { r, e := NewBoolRule("thekey", true, true) So(r.Default().Type(), ShouldEqual, "bool") - So(r.Default().(*ctypes.ConfigValueBool).Value, ShouldEqual, true) + So(r.Default().(ctypes.ConfigValueBool).Value, ShouldEqual, true) So(e, ShouldBeNil) v := ctypes.ConfigValueInt{Value: 1} diff --git a/control/plugin/cpolicy/float.go b/control/plugin/cpolicy/float.go index d2b5c6633..e79092291 100644 --- a/control/plugin/cpolicy/float.go +++ b/control/plugin/cpolicy/float.go @@ -176,7 +176,7 @@ func (f *FloatRule) Validate(cv ctypes.ConfigValue) error { // Default returns the rule's default value func (f *FloatRule) Default() ctypes.ConfigValue { if f.default_ != nil { - return &ctypes.ConfigValueFloat{Value: *f.default_} + return ctypes.ConfigValueFloat{Value: *f.default_} } return nil } @@ -198,14 +198,14 @@ func (f *FloatRule) SetMaximum(m float64) { func (i *FloatRule) Minimum() ctypes.ConfigValue { if i.minimum != nil { - return &ctypes.ConfigValueFloat{Value: *i.minimum} + return ctypes.ConfigValueFloat{Value: *i.minimum} } return nil } func (i *FloatRule) Maximum() ctypes.ConfigValue { if i.maximum != nil { - return &ctypes.ConfigValueFloat{Value: *i.maximum} + return ctypes.ConfigValueFloat{Value: *i.maximum} } return nil } diff --git a/control/plugin/cpolicy/float_test.go b/control/plugin/cpolicy/float_test.go index 3fcae0aa8..c71999cf7 100644 --- a/control/plugin/cpolicy/float_test.go +++ b/control/plugin/cpolicy/float_test.go @@ -54,7 +54,7 @@ func TestConfigPolicyRuleFloat(t *testing.T) { r, e := NewFloatRule("thekey", true, 7) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "float") - So(r.Default().(*ctypes.ConfigValueFloat).Value, ShouldEqual, 7) + So(r.Default().(ctypes.ConfigValueFloat).Value, ShouldEqual, 7) So(e, ShouldBeNil) }) @@ -84,7 +84,7 @@ func TestConfigPolicyRuleFloat(t *testing.T) { r, e := NewFloatRule("thekey", true, 7) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "float") - So(r.Default().(*ctypes.ConfigValueFloat).Value, ShouldEqual, 7) + So(r.Default().(ctypes.ConfigValueFloat).Value, ShouldEqual, 7) So(e, ShouldBeNil) v := ctypes.ConfigValueFloat{Value: 1} @@ -105,7 +105,7 @@ func TestConfigPolicyRuleFloat(t *testing.T) { r, e := NewFloatRule("thekey", true, 2) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "float") - So(r.Default().(*ctypes.ConfigValueFloat).Value, ShouldEqual, 2) + So(r.Default().(ctypes.ConfigValueFloat).Value, ShouldEqual, 2) So(e, ShouldBeNil) v := ctypes.ConfigValueStr{Value: "wat"} diff --git a/control/plugin/cpolicy/integer.go b/control/plugin/cpolicy/integer.go index 672c85196..d66a2f30e 100644 --- a/control/plugin/cpolicy/integer.go +++ b/control/plugin/cpolicy/integer.go @@ -179,7 +179,7 @@ func (i *IntRule) Validate(cv ctypes.ConfigValue) error { // Default return this rules default value func (i *IntRule) Default() ctypes.ConfigValue { if i.default_ != nil { - return &ctypes.ConfigValueInt{Value: *i.default_} + return ctypes.ConfigValueInt{Value: *i.default_} } return nil } @@ -201,14 +201,14 @@ func (i *IntRule) SetMaximum(m int) { func (i *IntRule) Minimum() ctypes.ConfigValue { if i.minimum != nil { - return &ctypes.ConfigValueInt{Value: *i.minimum} + return ctypes.ConfigValueInt{Value: *i.minimum} } return nil } func (i *IntRule) Maximum() ctypes.ConfigValue { if i.maximum != nil { - return &ctypes.ConfigValueInt{Value: *i.maximum} + return ctypes.ConfigValueInt{Value: *i.maximum} } return nil } diff --git a/control/plugin/cpolicy/integer_test.go b/control/plugin/cpolicy/integer_test.go index b1dbbcb09..37927e230 100644 --- a/control/plugin/cpolicy/integer_test.go +++ b/control/plugin/cpolicy/integer_test.go @@ -54,7 +54,7 @@ func TestConfigPolicyRuleInteger(t *testing.T) { r, e := NewIntegerRule("thekey", true, 7) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "integer") - So(r.Default().(*ctypes.ConfigValueInt).Value, ShouldEqual, 7) + So(r.Default().(ctypes.ConfigValueInt).Value, ShouldEqual, 7) So(e, ShouldBeNil) }) @@ -84,7 +84,7 @@ func TestConfigPolicyRuleInteger(t *testing.T) { r, e := NewIntegerRule("thekey", true, 7) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "integer") - So(r.Default().(*ctypes.ConfigValueInt).Value, ShouldEqual, 7) + So(r.Default().(ctypes.ConfigValueInt).Value, ShouldEqual, 7) So(e, ShouldBeNil) v := ctypes.ConfigValueInt{Value: 1} @@ -105,7 +105,7 @@ func TestConfigPolicyRuleInteger(t *testing.T) { r, e := NewIntegerRule("thekey", true, 2) So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "integer") - So(r.Default().(*ctypes.ConfigValueInt).Value, ShouldEqual, 2) + So(r.Default().(ctypes.ConfigValueInt).Value, ShouldEqual, 2) So(e, ShouldBeNil) v := ctypes.ConfigValueStr{Value: "wat"} diff --git a/control/plugin/cpolicy/node.go b/control/plugin/cpolicy/node.go index a9016790c..31388cc1f 100644 --- a/control/plugin/cpolicy/node.go +++ b/control/plugin/cpolicy/node.go @@ -170,7 +170,7 @@ func (c *ConfigPolicyNode) Process(m map[string]ctypes.ConfigValue) (*map[string } else { // If it was required add error if rule.Required() { - e := errors.New(fmt.Sprintf("required key missing (%s)", key)) + e := fmt.Errorf("required key missing (%s)", key) pErrors.AddError(e) } else { // If default returns we should add it @@ -189,6 +189,34 @@ func (c *ConfigPolicyNode) Process(m map[string]ctypes.ConfigValue) (*map[string return &m, pErrors } +// AddDefaults validates and returns a processed policy node or nil and error if validation has failed +func (c *ConfigPolicyNode) AddDefaults(m map[string]ctypes.ConfigValue) (*map[string]ctypes.ConfigValue, *ProcessingErrors) { + c.mutex.Lock() + defer c.mutex.Unlock() + pErrors := NewProcessingErrors() + // Loop through each rule and process + for key, rule := range c.rules { + // items exists for rule + if _, ok := m[key]; ok { + pErrors.AddError(fmt.Errorf("The key \"%v\" already has a default policy for this plugin", key)) + } else { + // If it was required add error + if !rule.Required() { + // If default returns we should add it + cv := rule.Default() + if cv != nil { + m[key] = cv + } + } + } + } + + if pErrors.HasErrors() { + return nil, pErrors + } + return &m, pErrors +} + // Merges a ConfigPolicyNode on top of this one (overwriting items where it occurs). func (c ConfigPolicyNode) Merge(n ctree.Node) ctree.Node { // Because Add only allows the ConfigPolicyNode type we diff --git a/control/plugin/cpolicy/node_test.go b/control/plugin/cpolicy/node_test.go index 26017f392..5023df9b1 100644 --- a/control/plugin/cpolicy/node_test.go +++ b/control/plugin/cpolicy/node_test.go @@ -122,9 +122,9 @@ func TestConfigPolicyNode(t *testing.T) { m2, pe := n.Process(m) So(len(pe.Errors()), ShouldEqual, 0) - So((*m2)["username"].(*ctypes.ConfigValueStr).Value, ShouldEqual, "root") - So((*m2)["port"].(*ctypes.ConfigValueInt).Value, ShouldEqual, 8080) - So((*m2)["nova"].(*ctypes.ConfigValueBool).Value, ShouldEqual, true) + So((*m2)["username"].(ctypes.ConfigValueStr).Value, ShouldEqual, "root") + So((*m2)["port"].(ctypes.ConfigValueInt).Value, ShouldEqual, 8080) + So((*m2)["nova"].(ctypes.ConfigValueBool).Value, ShouldEqual, true) }) Convey("defaults don't fix missing values on required", t, func() { diff --git a/control/plugin/cpolicy/string.go b/control/plugin/cpolicy/string.go index c94754b1b..e614f1c4d 100644 --- a/control/plugin/cpolicy/string.go +++ b/control/plugin/cpolicy/string.go @@ -130,7 +130,7 @@ func (s *StringRule) Validate(cv ctypes.ConfigValue) error { // Returns a default value is it exists. func (s *StringRule) Default() ctypes.ConfigValue { if s.default_ != nil { - return &ctypes.ConfigValueStr{Value: *s.default_} + return ctypes.ConfigValueStr{Value: *s.default_} } return nil } diff --git a/control/plugin/cpolicy/string_test.go b/control/plugin/cpolicy/string_test.go index dcd9b9968..1bf16dbaa 100644 --- a/control/plugin/cpolicy/string_test.go +++ b/control/plugin/cpolicy/string_test.go @@ -54,7 +54,7 @@ func TestConfigPolicyRuleString(t *testing.T) { r, e := NewStringRule("thekey", true, "wat") So(r.Default(), ShouldNotBeNil) So(r.Default().Type(), ShouldEqual, "string") - So(r.Default().(*ctypes.ConfigValueStr).Value, ShouldEqual, "wat") + So(r.Default().(ctypes.ConfigValueStr).Value, ShouldEqual, "wat") So(e, ShouldBeNil) }) @@ -69,7 +69,7 @@ func TestConfigPolicyRuleString(t *testing.T) { Convey("passes with string config value", func() { r, e := NewStringRule("thekey", true, "wat") So(r.Default().Type(), ShouldEqual, "string") - So(r.Default().(*ctypes.ConfigValueStr).Value, ShouldEqual, "wat") + So(r.Default().(ctypes.ConfigValueStr).Value, ShouldEqual, "wat") So(e, ShouldBeNil) v := ctypes.ConfigValueStr{Value: "foo"} @@ -81,7 +81,7 @@ func TestConfigPolicyRuleString(t *testing.T) { Convey("errors with non-string config value", func() { r, e := NewStringRule("thekey", true, "wat") So(r.Default().Type(), ShouldEqual, "string") - So(r.Default().(*ctypes.ConfigValueStr).Value, ShouldEqual, "wat") + So(r.Default().(ctypes.ConfigValueStr).Value, ShouldEqual, "wat") So(e, ShouldBeNil) v := ctypes.ConfigValueInt{Value: 1} diff --git a/control/plugin/cpolicy/tree.go b/control/plugin/cpolicy/tree.go index a27794a4f..4a51e34da 100644 --- a/control/plugin/cpolicy/tree.go +++ b/control/plugin/cpolicy/tree.go @@ -144,6 +144,22 @@ func (c *ConfigPolicy) Get(ns []string) *ConfigPolicyNode { } } +func (c *ConfigPolicy) GetAll() map[string]*ConfigPolicyNode { + // Automatically freeze on first Get + if !c.config.Frozen() { + c.config.Freeze() + } + + ret := map[string]*ConfigPolicyNode{} + for key, node := range c.config.GetAll() { + switch t := node.(type) { + case *ConfigPolicyNode: + ret[key] = t + } + } + return ret +} + // Freezes the ConfigPolicy from future writes (adds) and triggers compression // of tree into read-performant version. func (c *ConfigPolicy) Freeze() { diff --git a/control/plugin/cpolicy/tree_test.go b/control/plugin/cpolicy/tree_test.go index 748a2b9cd..49d6a8aef 100644 --- a/control/plugin/cpolicy/tree_test.go +++ b/control/plugin/cpolicy/tree_test.go @@ -49,7 +49,7 @@ func TestConfigPolicy(t *testing.T) { Convey("retrieves store policy", func() { gc := cp.Get(ns) So(gc.rules["username"].Required(), ShouldEqual, false) - So(gc.rules["username"].Default().(*ctypes.ConfigValueStr).Value, ShouldEqual, "root") + So(gc.rules["username"].Default().(ctypes.ConfigValueStr).Value, ShouldEqual, "root") So(gc.rules["password"].Required(), ShouldEqual, true) }) Convey("encode & decode", func() { @@ -69,7 +69,7 @@ func TestConfigPolicy(t *testing.T) { So(gc.rules["password"].Required(), ShouldEqual, true) So(gc.rules["username"].Default(), ShouldNotBeNil) So(gc.rules["password"].Default(), ShouldBeNil) - So(gc.rules["username"].Default().(*ctypes.ConfigValueStr).Value, ShouldEqual, "root") + So(gc.rules["username"].Default().(ctypes.ConfigValueStr).Value, ShouldEqual, "root") }) }) diff --git a/control/plugin_manager.go b/control/plugin_manager.go index 9ea01c461..4f1e200cc 100644 --- a/control/plugin_manager.go +++ b/control/plugin_manager.go @@ -42,6 +42,7 @@ import ( "github.com/intelsdi-x/snap/control/plugin/client" "github.com/intelsdi-x/snap/control/plugin/cpolicy" "github.com/intelsdi-x/snap/core" + "github.com/intelsdi-x/snap/core/cdata" "github.com/intelsdi-x/snap/core/serror" ) @@ -356,10 +357,49 @@ func (p *pluginManager) LoadPlugin(details *pluginDetails, emitter gomit.Emitter lPlugin.ConfigPolicy = cp if resp.Type == plugin.CollectorPluginType { + cfgNode := p.pluginConfig.getPluginConfigDataNode(core.PluginType(resp.Type), resp.Meta.Name, resp.Meta.Version) + + if lPlugin.ConfigPolicy != nil { + // Get plugin config defaults + defaults := cdata.NewNode() + cpolicies := lPlugin.ConfigPolicy.GetAll() + for _, cpolicy := range cpolicies { + _, errs := cpolicy.AddDefaults(defaults.Table()) + if len(errs.Errors()) > 0 { + for _, err := range errs.Errors() { + pmLogger.WithFields(log.Fields{ + "_block": "load-plugin", + "plugin-type": "collector", + "plugin-name": ap.Name(), + "plugin-version": ap.Version(), + "plugin-id": ap.ID(), + }).Error(err.Error()) + } + return nil, serror.New(errors.New("error getting default config")) + } + } + + // Update config policy with defaults + cfgNode.ReverseMerge(defaults) + cp, err = c.GetConfigPolicy() + if err != nil { + pmLogger.WithFields(log.Fields{ + "_block": "load-plugin", + "plugin-type": "collector", + "error": err.Error(), + "plugin-name": ap.Name(), + "plugin-version": ap.Version(), + "plugin-id": ap.ID(), + }).Error("error in getting config policy") + return nil, serror.New(err) + } + lPlugin.ConfigPolicy = cp + } + colClient := ap.client.(client.PluginCollectorClient) cfg := plugin.ConfigType{ - ConfigDataNode: p.pluginConfig.getPluginConfigDataNode(core.PluginType(resp.Type), resp.Meta.Name, resp.Meta.Version), + ConfigDataNode: cfgNode, } metricTypes, err := colClient.GetMetricTypes(cfg) diff --git a/docs/PLUGIN_AUTHORING.md b/docs/PLUGIN_AUTHORING.md index e6392c0a0..8c4562623 100644 --- a/docs/PLUGIN_AUTHORING.md +++ b/docs/PLUGIN_AUTHORING.md @@ -95,20 +95,22 @@ github.com/intelsdi-x/snap/control/plugin/cpolicy github.com/intelsdi-x/snap/core/ctypes ``` ### Writing a collector plugin -A Snap collector plugin collects telemetry data by communicating with the Snap daemon. To confine to collector plugin interfaces and metric types defined in Snap, a collector plugin must implement the following methods: +A Snap collector plugin collects telemetry data by communicating with the Snap daemon. To confine to collector plugin interfaces and metric types defined in Snap, a collector plugin must implement the following methods: ``` GetConfigPolicy() (*cpolicy.ConfigPolicy, error) CollectMetrics([]MetricType) ([]MetricType, error) GetMetricTypes(ConfigType) ([]MetricType, error) ``` +The plugin uses the default values given in the ConfigPolicy so a config file doesn't need to be passed in for these rules. An example use case would be for the URL the Apache Collector collects from. Disclaimer: Two namespaces can't have rules with the same key name. E.g. you can't have the key "username" for /intel/foo/bar and a different "username" for /intel/foo/mock. They would need unique keys. + ### Writing a processor plugin -A Snap processor plugin allows filtering, aggregation, transformation, etc of collected telemetry data. To complaint with processor plugin interfaces defined in Snap, a processor plugin must implement the following methods: +A Snap processor plugin allows filtering, aggregation, transformation, etc of collected telemetry data. To complaint with processor plugin interfaces defined in Snap, a processor plugin must implement the following methods: ``` GetConfigPolicy() (*cpolicy.ConfigPolicy, error) Process(contentType string, content []byte, config map[string]ctypes.ConfigValue) (string, []byte, error) ``` ### Writing a publisher plugin -A Snap publisher plugin allows publishing processed telemetry data into a variety of systems, databases, and monitors through Snap metrics. To compliant with metric types and plugin interfaces defined in Snap, a publisher plugin must implement the following methods: +A Snap publisher plugin allows publishing processed telemetry data into a variety of systems, databases, and monitors through Snap metrics. To compliant with metric types and plugin interfaces defined in Snap, a publisher plugin must implement the following methods: ``` GetConfigPolicy() (*cpolicy.ConfigPolicy, error) Publish(contentType string, content []byte, config map[string]ctypes.ConfigValue) error diff --git a/pkg/ctree/tree.go b/pkg/ctree/tree.go index 8c85c0ea9..6b2f6f511 100644 --- a/pkg/ctree/tree.go +++ b/pkg/ctree/tree.go @@ -24,6 +24,7 @@ import ( "encoding/gob" "encoding/json" "fmt" + "strings" log "github.com/Sirupsen/logrus" ) @@ -119,6 +120,35 @@ func (c *ConfigTree) Add(ns []string, inNode Node) { } +func (c *ConfigTree) GetAll() map[string]Node { + ret := map[string]Node{} + if !c.Frozen() { + panic("must freeze before getting") + } + if c.root == nil { + c.log(fmt.Sprintln("ctree: no root - returning nil")) + return nil + } + return c.getAll(c.root, "", ret) +} + +func (c *ConfigTree) getAll(node *node, base string, results map[string]Node) map[string]Node { + if len(node.keys) > 0 { + if base != "" { + base = base + "." + strings.Join(node.keys, ".") + } else { + base = strings.Join(node.keys, ".") + } + if node.Node != nil { + results[base] = node.Node + } + } + for _, child := range node.nodes { + c.getAll(child, base, results) + } + return results +} + // Get returns a tree node given the namespace func (c *ConfigTree) Get(ns []string) Node { c.log(fmt.Sprintf("Get on ns (%s)\n", ns)) diff --git a/plugin/collector/snap-collector-mock1/mock/mock.go b/plugin/collector/snap-collector-mock1/mock/mock.go index 8bcb77c6b..cb0ef4e23 100644 --- a/plugin/collector/snap-collector-mock1/mock/mock.go +++ b/plugin/collector/snap-collector-mock1/mock/mock.go @@ -67,9 +67,9 @@ func (f *Mock) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricType, err } } else { if cv, ok := p.Config().Table()["test"]; ok { - p.Data_ = fmt.Sprintf("The mock collected data! config data: user=%s password=%s test=%v", p.Config().Table()["user"], p.Config().Table()["password"], cv.(ctypes.ConfigValueBool).Value) + p.Data_ = fmt.Sprintf("The mock collected data! config data: name=%s password=%s test=%v", p.Config().Table()["name"], p.Config().Table()["password"], cv.(ctypes.ConfigValueBool).Value) } else { - p.Data_ = fmt.Sprintf("The mock collected data! config data: user=%s password=%s", p.Config().Table()["user"], p.Config().Table()["password"]) + p.Data_ = fmt.Sprintf("The mock collected data! config data: name=%s password=%s", p.Config().Table()["name"], p.Config().Table()["password"]) } p.Timestamp_ = time.Now() metrics = append(metrics, p)