diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/README.md b/plugin/collector/snap-plugin-collector-mock2-grpc/README.md new file mode 100644 index 000000000..d46003c98 --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/README.md @@ -0,0 +1,23 @@ + +#PLEASE NOTE: These are not example plugins + +The contents of `plugin/` are used as part of our testing framework. If you are looking for examples of how to write a plugin for Snap, review the [Plugin Authoring documentation](/docs/PLUGIN_AUTHORING.md). + +Curious what plugins are under development? See the `plugin-wishlist` label in [our issue backlog](https://github.com/intelsdi-x/snap/labels/plugin-wishlist). diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/main.go b/plugin/collector/snap-plugin-collector-mock2-grpc/main.go new file mode 100644 index 000000000..7c3df5dc5 --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/main.go @@ -0,0 +1,49 @@ +/* +http://www.apache.org/licenses/LICENSE-2.0.txt + + +Copyright 2015 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "time" + + // Import the snap plugin library + "github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin" + // Import our collector plugin implementation + "github.com/intelsdi-x/snap/plugin/collector/snap-plugin-collector-mock2-grpc/mock" +) + +const ( + pluginName = "mock-grpc" + pluginVersion = 1 +) + +func main() { + // Provided: + // the definition of the plugin metadata + // the implementation satisfying plugin.CollectorPlugin + + // Start a collector + plugin.StartCollector( + new(mock.Mock), + pluginName, + pluginVersion, + plugin.CacheTTL(100*time.Millisecond), + plugin.RoutingStrategy(plugin.StickyRouter), + ) +} diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/main_small_test.go b/plugin/collector/snap-plugin-collector-mock2-grpc/main_small_test.go new file mode 100644 index 000000000..3869f2e9c --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/main_small_test.go @@ -0,0 +1,34 @@ +// +build small + +/* +http://www.apache.org/licenses/LICENSE-2.0.txt + + +Copyright 2015 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestMain(t *testing.T) { + Convey("ensure plugin loads and responds", t, func() { + So(func() { main() }, ShouldNotPanic) + }) +} diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/main_test.go b/plugin/collector/snap-plugin-collector-mock2-grpc/main_test.go new file mode 100644 index 000000000..f5168d398 --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/main_test.go @@ -0,0 +1,60 @@ +// +build legacy + +/* +http://www.apache.org/licenses/LICENSE-2.0.txt + + +Copyright 2015 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "os" + "path" + "testing" + + "github.com/intelsdi-x/snap/control" + "github.com/intelsdi-x/snap/core" + "github.com/intelsdi-x/snap/plugin/helper" + . "github.com/smartystreets/goconvey/convey" +) + +var ( + PluginName = "snap-plugin-collector-mock2-grpc" + PluginType = "collector" + SnapPath = os.ExpandEnv(os.Getenv("SNAP_PATH")) + PluginPath = path.Join(SnapPath, "plugin", PluginName) +) + +func TestMockPluginLoad(t *testing.T) { + // These tests only work if SNAP_PATH is known. + // It is the responsibility of the testing framework to + // build the plugins first into the build dir. + Convey("make sure plugin has been built", t, func() { + err := helper.CheckPluginBuilt(SnapPath, PluginName) + So(err, ShouldBeNil) + + Convey("ensure plugin loads and responds", func() { + c := control.New(control.GetDefaultConfig()) + c.Start() + rp, _ := core.NewRequestedPlugin(PluginPath) + _, err := c.Load(rp) + + So(err, ShouldBeNil) + }) + + }) +} diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/mock/README.md b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/README.md new file mode 100644 index 000000000..d46003c98 --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/README.md @@ -0,0 +1,23 @@ + +#PLEASE NOTE: These are not example plugins + +The contents of `plugin/` are used as part of our testing framework. If you are looking for examples of how to write a plugin for Snap, review the [Plugin Authoring documentation](/docs/PLUGIN_AUTHORING.md). + +Curious what plugins are under development? See the `plugin-wishlist` label in [our issue backlog](https://github.com/intelsdi-x/snap/labels/plugin-wishlist). diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock.go b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock.go new file mode 100644 index 000000000..eb5dcd9f8 --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock.go @@ -0,0 +1,192 @@ +/* +http://www.apache.org/licenses/LICENSE-2.0.txt + + +Copyright 2015 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mock + +import ( + "fmt" + "log" + "math/rand" + "time" + + "github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin" +) + +// Mock collector implementation used for testing +type Mock struct { +} + +// list of available hosts +var availableHosts = getAllHostnames() + +// CollectMetrics collects metrics for testing +func (f *Mock) CollectMetrics(mts []plugin.Metric) ([]plugin.Metric, error) { + for _, p := range mts { + log.Printf("collecting %+v\n", p) + } + + rand.Seed(time.Now().UTC().UnixNano()) + metrics := []plugin.Metric{} + for i := range mts { + if _, err := mts[i].Config.GetBool("long_print"); err == nil { + letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + longLine := []byte{} + for i := 0; i < 8193; i++ { + longLine = append(longLine, letterBytes[rand.Intn(len(letterBytes))]) + } + fmt.Println(string(longLine)) + } + if _, err := mts[i].Config.GetBool("panic"); err == nil { + panic("Oops!") + } + + if isDynamic, _ := mts[i].Namespace.IsDynamic(); isDynamic { + requestedHosts := []string{} + + if mts[i].Namespace[2].Value == "*" { + // when dynamic element is not specified (equals an asterisk) + // then consider all available hosts as requested hosts + requestedHosts = append(requestedHosts, availableHosts...) + } else { + // when the dynamic element is specified + // then consider this specified host as requested hosts + host := mts[i].Namespace[2].Value + + // check if specified host is available in system + if contains(availableHosts, host) { + requestedHosts = append(requestedHosts, host) + } else { + return nil, fmt.Errorf("requested hostname `%s` is not available (list of available hosts: %s)", host, availableHosts) + } + + } + // collect data for each of requested hosts + for _, host := range requestedHosts { + //generate random data + data := randInt(65, 90) + 1000 + // prepare namespace as a copy of incoming dynamic namespace, + // but with the set value of dynamic element + ns := plugin.NewNamespace() + for j, ne := range mts[i].Namespace { + if ne.IsDynamic() { + ns = ns.AddDynamicElement(ne.Name, ne.Description) + ns[j].Value = host + } else { + ns = ns.AddStaticElement(ne.Value) + } + } + // metric with set data, ns, timestamp and the version of the plugin + mt := plugin.Metric{ + Data: data, + Namespace: ns, + Timestamp: time.Now(), + Unit: mts[i].Unit, + Version: mts[i].Version, + } + metrics = append(metrics, mt) + } + + } else { + data := randInt(65, 90) + 1000 + mts[i].Data = data + mts[i].Timestamp = time.Now() + metrics = append(metrics, mts[i]) + } + } + return metrics, nil +} + +// GetMetricTypes returns metric types for testing +func (f *Mock) GetMetricTypes(cfg plugin.Config) ([]plugin.Metric, error) { + mts := []plugin.Metric{} + if _, err := cfg.GetBool("test-fail"); err == nil { + return mts, fmt.Errorf("testing") + } + if _, err := cfg.GetBool("test"); err == nil { + mts = append(mts, plugin.Metric{ + Namespace: plugin.NewNamespace("intel", "mock", "test"), + Description: "mock description", + Unit: "mock unit", + }) + } + if _, err := cfg.GetBool("test-less"); err != nil { + mts = append(mts, plugin.Metric{ + Namespace: plugin.NewNamespace("intel", "mock", "foo"), + Description: "mock description", + Unit: "mock unit", + }) + } + mts = append(mts, plugin.Metric{ + Namespace: plugin.NewNamespace("intel", "mock", "bar"), + Description: "mock description", + Unit: "mock unit", + }) + mts = append(mts, plugin.Metric{ + Namespace: plugin.NewNamespace("intel", "mock"). + AddDynamicElement("host", "name of the host"). + AddStaticElement("baz"), + Description: "mock description", + Unit: "mock unit", + }) + return mts, nil +} + +// GetConfigPolicy returns a ConfigPolicy for testing +func (f *Mock) GetConfigPolicy() (plugin.ConfigPolicy, error) { + p := plugin.NewConfigPolicy() + + rule1, err := plugin.NewStringRule("name", false, plugin.SetDefaultString("bob")) + if err != nil { + return *p, err + } + + rule2, err := plugin.NewStringRule("password", true) + if err != nil { + return *p, err + } + + p.AddStringRule([]string{"intel", "mock", "foo"}, rule1) + p.AddStringRule([]string{"intel", "mock", "foo"}, rule2) + + return *p, nil +} + +// contains reports whether a given item is found in a slice +func contains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} + +// getAllHostnames returns all available hostnames ('host0', 'host1', ..., 'host9') +func getAllHostnames() []string { + res := []string{} + for j := 0; j < 10; j++ { + res = append(res, fmt.Sprintf("host%d", j)) + } + return res +} + +// random number generator +func randInt(min int, max int) int { + return min + rand.Intn(max-min) +} diff --git a/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock_medium_test.go b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock_medium_test.go new file mode 100644 index 000000000..4d6e5a42e --- /dev/null +++ b/plugin/collector/snap-plugin-collector-mock2-grpc/mock/mock_medium_test.go @@ -0,0 +1,258 @@ +// +build medium + +/* +http://www.apache.org/licenses/LICENSE-2.0.txt + + +Copyright 2016 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mock + +import ( + "math/rand" + "testing" + "time" + + "github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin" + "github.com/intelsdi-x/snap-plugin-utilities/str" + . "github.com/smartystreets/goconvey/convey" +) + +func TestCollectMetric(t *testing.T) { + ns0 := plugin.NewNamespace("intel", "mock", "test") + ns1 := plugin.NewNamespace("intel", "mock", "foo") + ns2 := plugin.NewNamespace("intel", "mock", "bar") + ns3 := plugin.NewNamespace("intel", "mock").AddDynamicElement("host", "name of the host").AddStaticElement("baz") + + Convey("Testing CollectMetric", t, func() { + + newPlg := new(Mock) + So(newPlg, ShouldNotBeNil) + + Convey("with 'test' config variable'", func() { + + cfg := plugin.Config{"test": true} + + Convey("testing specific metrics", func() { + mTypes := []plugin.Metric{ + plugin.Metric{Namespace: ns0, Config: cfg}, + plugin.Metric{Namespace: ns1, Config: cfg}, + plugin.Metric{Namespace: ns2, Config: cfg}, + } + mts, _ := newPlg.CollectMetrics(mTypes) + + Convey("returned metrics should have data type integer", func() { + for _, mt := range mts { + _, ok := mt.Data.(int) + So(ok, ShouldBeTrue) + } + }) + }) + + Convey("testing dynamic metric", func() { + + mt := plugin.Metric{Namespace: ns3, Config: cfg} + isDynamic, _ := mt.Namespace.IsDynamic() + So(isDynamic, ShouldBeTrue) + + Convey("for none specified instance", func() { + mts, _ := newPlg.CollectMetrics([]plugin.Metric{mt}) + + // there is 10 available hosts (host0, host1, ..., host9) + So(len(mts), ShouldEqual, 10) + + Convey("returned metrics should have data type integer", func() { + for _, mt := range mts { + _, ok := mt.Data.(int) + So(ok, ShouldBeTrue) + } + }) + + Convey("returned metrics should remain dynamic", func() { + for _, mt := range mts { + isDynamic, _ := mt.Namespace.IsDynamic() + So(isDynamic, ShouldBeTrue) + } + }) + + }) + + Convey("for specified instance which is available - host0", func() { + mt.Namespace[2].Value = "host0" + mts, _ := newPlg.CollectMetrics([]plugin.Metric{mt}) + + // only one metric for this specific hostname should be returned + So(len(mts), ShouldEqual, 1) + So(mts[0].Namespace.String(), ShouldEqual, "/intel/mock/host0/baz") + + Convey("returned metric should have data type integer", func() { + _, ok := mts[0].Data.(int) + So(ok, ShouldBeTrue) + }) + + Convey("returned metric should remain dynamic", func() { + isDynamic, _ := mt.Namespace.IsDynamic() + So(isDynamic, ShouldBeTrue) + }) + + }) + + Convey("for specified instance which is not available - host10", func() { + mt.Namespace[2].Value = "host10" + mts, err := newPlg.CollectMetrics([]plugin.Metric{mt}) + + So(mts, ShouldBeNil) + So(err, ShouldNotBeNil) + So(err.Error(), ShouldStartWith, "requested hostname `host10` is not available") + + }) + }) + + }) + + Convey("without config variables", func() { + + cfg := plugin.Config{} + + Convey("testing specific metrics", func() { + mTypes := []plugin.Metric{ + plugin.Metric{Namespace: ns0, Config: cfg}, + plugin.Metric{Namespace: ns1, Config: cfg}, + plugin.Metric{Namespace: ns2, Config: cfg}, + } + mts, _ := newPlg.CollectMetrics(mTypes) + + Convey("returned metrics should have data type integer", func() { + for _, mt := range mts { + _, ok := mt.Data.(int) + So(ok, ShouldBeTrue) + } + }) + }) + + Convey("testing dynamic metics", func() { + mTypes := []plugin.Metric{ + plugin.Metric{Namespace: ns3, Config: cfg}, + } + mts, _ := newPlg.CollectMetrics(mTypes) + + Convey("returned metrics should have data type integer", func() { + for _, mt := range mts { + _, ok := mt.Data.(int) + So(ok, ShouldBeTrue) + } + }) + + Convey("returned metrics should remain dynamic", func() { + for _, mt := range mts { + isDynamic, _ := mt.Namespace.IsDynamic() + So(isDynamic, ShouldBeTrue) + } + }) + + }) + + }) + + }) +} + +func TestGetMetricTypes(t *testing.T) { + Convey("Tesing GetMetricTypes", t, func() { + + newPlg := new(Mock) + So(newPlg, ShouldNotBeNil) + + Convey("with missing on-load plugin config entry", func() { + cfg := plugin.Config{"test-fail": true} + _, err := newPlg.GetMetricTypes(cfg) + + So(err, ShouldNotBeNil) + }) + + Convey("with 'test' config variable", func() { + cfg := plugin.Config{"test": true} + + mts, err := newPlg.GetMetricTypes(cfg) + + So(err, ShouldBeNil) + So(len(mts), ShouldEqual, 4) + + Convey("checking namespaces", func() { + metricNames := []string{} + for _, m := range mts { + metricNames = append(metricNames, m.Namespace.String()) + } + + ns := plugin.NewNamespace("intel", "mock", "test") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + + ns = plugin.NewNamespace("intel", "mock", "foo") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + + ns = plugin.NewNamespace("intel", "mock", "bar") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + + ns = plugin.NewNamespace("intel", "mock").AddDynamicElement("host", "name of the host").AddStaticElement("baz") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + }) + }) + + Convey("without config variables", func() { + mts, err := newPlg.GetMetricTypes(plugin.Config{}) + + So(err, ShouldBeNil) + So(len(mts), ShouldEqual, 3) + + Convey("checking namespaces", func() { + metricNames := []string{} + for _, m := range mts { + metricNames = append(metricNames, m.Namespace.String()) + } + + ns := plugin.NewNamespace("intel", "mock", "foo") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + + ns = plugin.NewNamespace("intel", "mock", "bar") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + + ns = plugin.NewNamespace("intel", "mock").AddDynamicElement("host", "name of the host").AddStaticElement("baz") + So(str.Contains(metricNames, ns.String()), ShouldBeTrue) + }) + }) + + }) +} + +func TestRandInt(t *testing.T) { + Convey("Testing randInt", t, func() { + rand.Seed(time.Now().UTC().UnixNano()) + data := randInt(65, 90) + So(data, ShouldBeBetween, 64, 91) + }) +} + +func TestGetConfigPolicy(t *testing.T) { + Convey("Testing GetConfigPolicy", t, func() { + newPlg := new(Mock) + So(newPlg, ShouldNotBeNil) + + configPolicy, err := newPlg.GetConfigPolicy() + + So(err, ShouldBeNil) + So(configPolicy, ShouldNotBeNil) + }) +}