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)
		})
	})
}
Beispiel #2
0
func TestValidateSignature(t *testing.T) {
	keyringFile := []string{"pubring.gpg"}
	signedFile := "snap-plugin-collector-mock1"
	signatureFile := signedFile + ".asc"
	unsignedFile := helper.PluginFilePath("snap-plugin-collector-mock2")
	s := SigningManager{}

	signature, _ := ioutil.ReadFile(signatureFile)
	Convey("Valid files and good signature", t, func() {
		err := s.ValidateSignature(keyringFile, signedFile, signature)
		So(err, ShouldBeNil)
	})

	Convey("Valid files and good signature. Multiple keyrings", t, func() {
		keyringFiles := []string{"pubkeys.gpg", "pubring.gpg"}
		err := s.ValidateSignature(keyringFiles, signedFile, signature)
		So(err, ShouldBeNil)
	})

	Convey("Validate unsigned file with signature", t, func() {
		err := s.ValidateSignature(keyringFile, unsignedFile, signature)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "Error checking signature")
	})

	Convey("Invalid keyring", t, func() {
		err := s.ValidateSignature([]string{""}, signedFile, signature)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "Keyring file (.gpg) not found")
	})

	Convey("Invalid signed file", t, func() {
		err := s.ValidateSignature(keyringFile, "", signature)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "Signed file not found")
	})

	Convey("Invalid signature file", t, func() {
		err := s.ValidateSignature(keyringFile, signedFile, nil)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "Error checking signature")
	})
}
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)
		})
	})
}
// This test is meant to cover the grpc implementation of the subset of control
// features that scheduler uses. It is not intended to test the control features
// themselves, only that we are correctly passing data over grpc and correctly
// passing success/errors.
func TestGRPCServerScheduler(t *testing.T) {
	l, _ := net.Listen("tcp", ":0")
	l.Close()
	cfg := GetDefaultConfig()
	cfg.ListenPort = l.Addr().(*net.TCPAddr).Port
	c := New(cfg)
	err := c.Start()

	lpe := newFoo()
	c.eventManager.RegisterHandler("Control.PluginLoaded", lpe)

	Convey("Starting control_proxy server/client", t, func() {
		Convey("So err should be nil", func() {
			So(err, ShouldBeNil)
		})
	})
	// Load 3 plugins
	// collector -- mock
	// processor -- passthru
	// publisher -- file
	mock, err := core.NewRequestedPlugin(fixtures.JSONRPCPluginPath)
	if err != nil {
		log.Fatal(err)
	}
	_, serr := c.Load(mock)
	Convey("Loading mock collector", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	<-lpe.done
	passthru, err := core.NewRequestedPlugin(helper.PluginFilePath("snap-plugin-processor-passthru"))
	if err != nil {
		log.Fatal(err)
	}
	catalogedPassthru, serr := c.Load(passthru)
	Convey("Loading passthru processor", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	subscribedPassThruPlugin := subscribedPlugin{
		name:     catalogedPassthru.Name(),
		version:  catalogedPassthru.Version(),
		typeName: catalogedPassthru.TypeName(),
	}
	<-lpe.done
	filepub, err := core.NewRequestedPlugin(helper.PluginFilePath("snap-plugin-publisher-mock-file"))
	if err != nil {
		log.Fatal(err)
	}
	catalogedFile, serr := c.Load(filepub)
	Convey("Loading file publisher", t, func() {
		Convey("should not error", func() {
			So(serr, ShouldBeNil)
		})
	})
	subscribedFilePlugin := subscribedPlugin{
		name:     catalogedFile.Name(),
		version:  catalogedFile.Version(),
		typeName: catalogedFile.TypeName(),
	}

	<-lpe.done
	conn, err := rpcutil.GetClientConnection(c.Config.ListenAddr, c.Config.ListenPort)

	Convey("Creating an rpc connection", t, func() {
		Convey("Should not error", func() {
			So(err, ShouldBeNil)
		})
	})

	client := rpc.NewMetricManagerClient(conn)

	Convey("Creating an RPC client to control RPC server", t, func() {
		Convey("And a client should exist", func() {
			So(client, ShouldNotBeNil)
		})
	})

	// Verify that validate deps is properly passing through errors
	Convey("Validating Deps", t, func() {
		Convey("Should Fail if given invalid info", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.InvalidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
		Convey("with valid metrics", func() {
			req := &rpc.ValidateDepsRequest{
				Metrics: common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
			}
			reply, err := client.ValidateDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})
	})
	//Subscribe Deps: valid/invalid
	Convey("SubscribeDeps", t, func() {
		Convey("Should Error with invalid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.InvalidMetric.Namespace()), Version: int64(fixtures.InvalidMetric.Version())}},
				Plugins:   common.ToSubPluginsMsg([]core.SubscribedPlugin{subscribedFilePlugin, subscribedPassThruPlugin}),
				TaskId:    "my-snowflake-id",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			So(reply.Errors[0].ErrorString, ShouldResemble, "Metric not found: /this/is/invalid (version: 1000)")
		})
		Convey("Should not error with valid inputs", func() {
			req := &rpc.SubscribeDepsRequest{
				Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
				Plugins:   common.ToSubPluginsMsg([]core.SubscribedPlugin{}),
				TaskId:    "my-snowflake-valid",
			}
			reply, err := client.SubscribeDeps(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
	//our returned metrics
	var mts []core.Metric
	//collect
	Convey("CollectMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)

		Convey("should error with invalid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				TaskID: "my-fake-snowflake-id",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})

		Convey("should not error with valid inputs", func() {
			req := &rpc.CollectMetricsRequest{
				TaskID: "my-snowflake-valid",
			}
			reply, err := client.CollectMetrics(context.Background(), req)
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
			So(reply.Metrics[0].Namespace, ShouldResemble, common.ToNamespace(fixtures.ValidMetric.Namespace()))
			// Used in a later test as metrics to be passed to processor
			mts = common.ToCoreMetrics(reply.Metrics)
		})
	})

	//process
	Convey("ProcessMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)
		Convey("should error with invalid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "passthru-invalid",
				PluginVersion: 1,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
			// content to pass to publisher
		})
		Convey("should not error with valid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics(mts),
				PluginName:    "passthru",
				PluginVersion: 1,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.ProcessMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)

		})
	})
	//publishmetrics
	Convey("PublishMetrics", t, func() {
		req := &rpc.SubscribeDepsRequest{
			Requested: []*common.Metric{&common.Metric{Namespace: common.ToNamespace(fixtures.ValidMetric.Namespace()), Version: int64(fixtures.ValidMetric.Version())}},
			Plugins: common.ToSubPluginsMsg([]core.SubscribedPlugin{
				subscribedPassThruPlugin,
				subscribedFilePlugin,
			},
			),
			TaskId: "my-snowflake-id",
		}
		_, err := client.SubscribeDeps(context.Background(), req)
		So(err, ShouldBeNil)

		Convey("Should error with invalid inputs", func() {
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "mock-file-invalid",
				PluginVersion: 3,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(map[string]ctypes.ConfigValue{}),
			}
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldNotEqual, 0)
		})

		// Publish only returns no errors on success
		Convey("should not error with valid inputs", func() {
			config := make(map[string]ctypes.ConfigValue)
			config["file"] = ctypes.ConfigValueStr{Value: "/tmp/grpcservertest.snap"}
			req := &rpc.PubProcMetricsRequest{
				Metrics:       common.NewMetrics([]core.Metric{fixtures.ValidMetric}),
				PluginName:    "mock-file",
				PluginVersion: 3,
				TaskId:        "my-snowflake-id",
				Config:        common.ToConfigMap(config),
			}
			reply, err := client.PublishMetrics(context.Background(), req)
			// we don't expect rpc errors
			So(err, ShouldBeNil)
			So(len(reply.Errors), ShouldEqual, 0)
		})
	})
}
Beispiel #5
0
	log "github.com/Sirupsen/logrus"
	"github.com/pborman/uuid"

	"github.com/intelsdi-x/snap/control"
	"github.com/intelsdi-x/snap/mgmt/rest"
	"github.com/intelsdi-x/snap/plugin/helper"
	"github.com/intelsdi-x/snap/scheduler"
	"github.com/intelsdi-x/snap/scheduler/wmap"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	// Change to set the REST API logging to debug
	LOG_LEVEL = log.FatalLevel

	MOCK_PLUGIN_PATH1       = []string{helper.PluginFilePath("snap-plugin-collector-mock1")}
	MOCK_PLUGIN_PATH2       = []string{helper.PluginFilePath("snap-plugin-collector-mock2")}
	ANOTHERMOCK_PLUGIN_PATH = []string{helper.PluginFilePath("snap-plugin-collector-anothermock1")}
	FILE_PLUGIN_PATH        = []string{helper.PluginFilePath("snap-plugin-publisher-mock-file")}
	DIRECTORY_PATH          = []string{helper.PluginPath()}

	NextPort = 45000

	p1 *LoadPluginResult
	p2 *LoadPluginResult
	p3 *LoadPluginResult
)

func getWMFromSample(sample string) *wmap.WorkflowMap {
	jsonP, err := ioutil.ReadFile("../wmap_sample/" + sample)
	if err != nil {
Beispiel #6
0
package core

import (
	"crypto/sha256"
	"io/ioutil"
	"path"
	"testing"

	"github.com/intelsdi-x/snap/plugin/helper"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	PluginName    = "snap-plugin-collector-mock1"
	SnapPath      = helper.BuildPath
	PluginPath    = helper.PluginFilePath(PluginName)
	SignatureFile = path.Join(SnapPath, "../pkg/psigning", "snap-plugin-collector-mock1.asc")
)

func TestRequestedPlugin(t *testing.T) {
	// Creating a plugin request

	Convey("Creating a plugin request from a valid path", t, func() {
		rp, err := NewRequestedPlugin(PluginPath)
		Convey("Should not return an error", func() {
			So(err, ShouldBeNil)

			Convey("Should return a RequestedPlugin type", func() {
				So(rp, ShouldHaveSameTypeAs, &RequestedPlugin{})
			})
Beispiel #7
0
	"os"
	"strings"
	"testing"

	. "github.com/smartystreets/goconvey/convey"

	log "github.com/Sirupsen/logrus"
	"github.com/intelsdi-x/snap/core/cdata"
	"github.com/intelsdi-x/snap/core/ctypes"
	"github.com/intelsdi-x/snap/mgmt/rest/fixtures"
	"github.com/intelsdi-x/snap/plugin/helper"
)

var (
	LOG_LEVEL         = log.WarnLevel
	MOCK_PLUGIN_PATH1 = helper.PluginFilePath("snap-plugin-collector-mock1")
)

type restAPIInstance struct {
	port   int
	server *Server
}

func startV1API(cfg *mockConfig, testType string) *restAPIInstance {
	log.SetLevel(LOG_LEVEL)
	r, _ := New(cfg.RestAPI)
	switch testType {
	case "tribe":
		mockTribeManager := &fixtures.MockTribeManager{}
		r.BindTribeManager(mockTribeManager)
	case "plugin":
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())
			})
		})
	})
}
Beispiel #11
0
	"github.com/intelsdi-x/snap/core/ctypes"
	"github.com/intelsdi-x/snap/mgmt/rest/rbody"
	"github.com/intelsdi-x/snap/pkg/cfgfile"
	"github.com/intelsdi-x/snap/plugin/helper"
	"github.com/intelsdi-x/snap/scheduler"
	"github.com/intelsdi-x/snap/scheduler/wmap"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	// Switching this turns on logging for all the REST API calls
	LOG_LEVEL = log.WarnLevel

	SNAP_PATH              = helper.BuildPath
	SNAP_AUTODISCOVER_PATH = os.Getenv("SNAP_AUTODISCOVER_PATH")
	MOCK_PLUGIN_PATH1      = helper.PluginFilePath("snap-plugin-collector-mock1")
	MOCK_PLUGIN_PATH2      = helper.PluginFilePath("snap-plugin-collector-mock2")
	FILE_PLUGIN_PATH       = helper.PluginFilePath("snap-plugin-publisher-mock-file")

	CompressedUpload = true
	TotalUploadSize  = 0
	UploadCount      = 0
)

const (
	MOCK_CONSTRAINTS = `{
		"$schema": "http://json-schema.org/draft-04/schema#",
		"title": "snapd global config schema",
		"type": ["object", "null"],
		"properties": {
			"control": { "$ref": "#/definitions/control" },
Beispiel #12
0
package fixtures

import (
	"encoding/json"
	"time"

	"github.com/intelsdi-x/snap/core"
	"github.com/intelsdi-x/snap/core/cdata"
	"github.com/intelsdi-x/snap/plugin/helper"
)

var (
	PluginName = "snap-plugin-collector-mock2"
	SnapPath   = helper.BuildPath
	PluginPath = helper.PluginFilePath(PluginName)

	JSONRPCPluginName = "snap-plugin-collector-mock1"
	JSONRPCPluginPath = helper.PluginFilePath(JSONRPCPluginName)
)

// mocks a metric type
type MockMetricType struct {
	Namespace_ core.Namespace
	Cfg        *cdata.ConfigDataNode
	Ver        int
}

func (m MockMetricType) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Namespace core.Namespace        `json:"namespace"`
Beispiel #13
0
func TestDistributedWorkflow(t *testing.T) {
	Convey("Create a scheduler with 2 controls and load plugins", t, func() {
		l, _ := net.Listen("tcp", ":0")
		l.Close()
		cfg := control.GetDefaultConfig()
		cfg.ListenPort = l.Addr().(*net.TCPAddr).Port
		c1 := control.New(cfg)
		c1.Start()
		m, _ := net.Listen("tcp", ":0")
		m.Close()
		cfg.ListenPort = m.Addr().(*net.TCPAddr).Port
		port1 := cfg.ListenPort
		c2 := control.New(cfg)
		schcfg := GetDefaultConfig()
		sch := New(schcfg)
		c2.Start()
		sch.SetMetricManager(c1)
		err := sch.Start()
		So(err, ShouldBeNil)
		// Load appropriate plugins into each control.
		mock2Path := helper.PluginFilePath("snap-plugin-collector-mock2")
		passthruPath := helper.PluginFilePath("snap-plugin-processor-passthru")
		filePath := helper.PluginFilePath("snap-plugin-publisher-mock-file")

		// mock2 and file onto c1

		rp, err := core.NewRequestedPlugin(mock2Path)
		So(err, ShouldBeNil)
		_, err = c1.Load(rp)
		So(err, ShouldBeNil)
		rp, err = core.NewRequestedPlugin(filePath)
		So(err, ShouldBeNil)
		_, err = c1.Load(rp)
		So(err, ShouldBeNil)
		// passthru on c2
		rp, err = core.NewRequestedPlugin(passthruPath)
		So(err, ShouldBeNil)
		passthru, err := c2.Load(rp)
		So(err, ShouldBeNil)

		Convey("Test task with one local and one remote node", func() {
			//Create a task
			//Create a workflowmap
			wf := dsWFMap(port1)
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, true)
			So(len(errs.Errors()), ShouldEqual, 0)
			So(t, ShouldNotBeNil)
			// stop the scheduler and control (since in nested Convey statements, the
			// statements in the outer Convey execute for each of the inner Conveys
			// independently; see https://github.com/smartystreets/goconvey/wiki/Execution-order
			// for details on execution order in Convey)
			sch.Stop()
			c2.Stop()
		})

		Convey("Test task with invalid remote port", func() {
			wf := dsWFMap(0)
			controlproxy.MAX_CONNECTION_TIMEOUT = 1 * time.Second
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, true)
			So(len(errs.Errors()), ShouldEqual, 1)
			So(t, ShouldBeNil)
			// stop the scheduler and control (since in nested Convey statements, the
			// statements in the outer Convey execute for each of the inner Conveys
			// independently; see https://github.com/smartystreets/goconvey/wiki/Execution-order
			// for details on execution order in Convey)
			sch.Stop()
			c2.Stop()
		})

		Convey("Test task without remote plugin", func() {
			_, err := c2.Unload(passthru)
			So(err, ShouldBeNil)
			wf := dsWFMap(port1)
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, true)
			So(len(errs.Errors()), ShouldEqual, 1)
			So(t, ShouldBeNil)
			// stop the scheduler and control (since in nested Convey statements, the
			// statements in the outer Convey execute for each of the inner Conveys
			// independently; see https://github.com/smartystreets/goconvey/wiki/Execution-order
			// for details on execution order in Convey)
			sch.Stop()
			c2.Stop()
		})

		Convey("Test task failing when control is stopped while task is running", func() {
			wf := dsWFMap(port1)
			// set timeout so that connection attempt through the controlproxy will fail after 1 second
			controlproxy.MAX_CONNECTION_TIMEOUT = time.Second
			// define an interval that the simple scheduler will run on every 100ms
			interval := time.Millisecond * 100
			// create our task; should be disabled after 3 failures
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(interval), wf, true)
			// ensure task was created successfully
			So(len(errs.Errors()), ShouldEqual, 0)
			So(t, ShouldNotBeNil)
			// create a channel to listen on for a response and setup an event handler
			// that will respond on that channel once the 'TaskDisabledEvent'  arrives
			respChan := make(chan struct{})
			sch.RegisterEventHandler("test", &failHandler{respChan})
			// then stop the controller
			c2.Stop()
			// and wait for the response (with a 30 second timeout; just in case)
			var ok bool
			select {
			case <-time.After(30 * time.Second):
				// if get here, the select timed out waiting for a response; we don't
				// expect to hit this timeout since it should only take 3 seconds for
				// the workflow to fail to connect to the gRPC server three times, but
				// it might if the task did not fail as expected
				So("Timeout triggered waiting for disabled event", ShouldBeBlank)
			case <-respChan:
				// if get here, we got a response on the respChan
				ok = true
			}
			So(ok, ShouldEqual, true)
			// stop the scheduler (since in nested Convey statements, the
			// statements in the outer Convey execute for each of the inner Conveys
			// independently; see https://github.com/smartystreets/goconvey/wiki/Execution-order
			// for details on execution order in Convey)
			sch.Stop()
		})

	})

}
Beispiel #14
0
func TestDistributedSubscriptions(t *testing.T) {

	Convey("Load control/scheduler with a mock remote scheduler", t, func() {
		l, _ := net.Listen("tcp", ":0")
		l.Close()
		cfg := control.GetDefaultConfig()
		cfg.ListenPort = l.Addr().(*net.TCPAddr).Port
		c1 := control.New(cfg)
		c1.Start()
		m, _ := net.Listen("tcp", ":0")
		m.Close()
		cfg.ListenPort = m.Addr().(*net.TCPAddr).Port
		port1 := cfg.ListenPort
		c2 := control.New(cfg)
		schcfg := GetDefaultConfig()
		sch := New(schcfg)
		c2.Start()
		sch.SetMetricManager(c1)
		err := sch.Start()
		So(err, ShouldBeNil)
		// Load appropriate plugins into each control.
		mock2Path := helper.PluginFilePath("snap-plugin-collector-mock2")
		passthruPath := helper.PluginFilePath("snap-plugin-processor-passthru")
		filePath := helper.PluginFilePath("snap-plugin-publisher-mock-file")

		// mock2 and file onto c1

		rp, err := core.NewRequestedPlugin(mock2Path)
		So(err, ShouldBeNil)
		_, err = c1.Load(rp)
		So(err, ShouldBeNil)
		rp, err = core.NewRequestedPlugin(filePath)
		So(err, ShouldBeNil)
		_, err = c1.Load(rp)
		So(err, ShouldBeNil)
		// passthru on c2
		rp, err = core.NewRequestedPlugin(passthruPath)
		So(err, ShouldBeNil)
		_, err = c2.Load(rp)
		So(err, ShouldBeNil)

		Convey("Starting task should not succeed if remote dep fails to subscribe", func() {
			//Create a task
			//Create a workflowmap
			wf := dsWFMap(port1)
			// Create a task that is not started immediately so we can
			// validate deps correctly.
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, false)
			So(len(errs.Errors()), ShouldEqual, 0)
			So(t, ShouldNotBeNil)
			schTask := t.(*task)
			remoteMockManager := &subscriptionManager{Fail: true}
			schTask.RemoteManagers.Add(fmt.Sprintf("127.0.0.1:%v", port1), remoteMockManager)
			localMockManager := &subscriptionManager{Fail: false}
			schTask.RemoteManagers.Add("", localMockManager)
			// Start task. We expect it to fail while subscribing deps
			terrs := sch.StartTask(t.ID())
			So(terrs, ShouldNotBeNil)
			Convey("So dependencies should have been unsubscribed", func() {
				// Ensure that unsubscribe call count is equal to subscribe call count
				// i.e that every subscribe call was followed by an unsubscribe since
				// we errored
				So(remoteMockManager.UnsubscribeCallCount, ShouldEqual, remoteMockManager.SubscribeCallCount)
				So(localMockManager.UnsubscribeCallCount, ShouldEqual, localMockManager.UnsubscribeCallCount)
			})
		})

		Convey("Starting task should not succeed if missing local dep fails to subscribe", func() {
			//Create a task
			//Create a workflowmap
			wf := dsWFMap(port1)
			// Create a task that is not started immediately so we can
			// validate deps correctly.
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, false)
			So(len(errs.Errors()), ShouldEqual, 0)
			So(t, ShouldNotBeNil)
			schTask := t.(*task)
			localMockManager := &subscriptionManager{Fail: true}
			schTask.RemoteManagers.Add("", localMockManager)
			remoteMockManager := &subscriptionManager{Fail: false}
			schTask.RemoteManagers.Add(fmt.Sprintf("127.0.0.1:%v", port1), remoteMockManager)

			// Start task. We expect it to fail while subscribing deps
			terrs := sch.StartTask(t.ID())
			So(terrs, ShouldNotBeNil)
			Convey("So dependencies should have been unsubscribed", func() {
				// Ensure that unsubscribe call count is equal to subscribe call count
				// i.e that every subscribe call was followed by an unsubscribe since
				// we errored
				So(remoteMockManager.UnsubscribeCallCount, ShouldEqual, remoteMockManager.SubscribeCallCount)
				So(localMockManager.UnsubscribeCallCount, ShouldEqual, localMockManager.UnsubscribeCallCount)
			})
		})

		Convey("Starting task should suceed if all deps are available", func() {
			//Create a task
			//Create a workflowmap
			wf := dsWFMap(port1)
			// Create a task that is not started immediately so we can
			// validate deps correctly.
			t, errs := sch.CreateTask(schedule.NewSimpleSchedule(time.Second), wf, false)
			So(len(errs.Errors()), ShouldEqual, 0)
			So(t, ShouldNotBeNil)
			schTask := t.(*task)
			localMockManager := &subscriptionManager{Fail: false}
			schTask.RemoteManagers.Add("", localMockManager)
			remoteMockManager := &subscriptionManager{Fail: false}
			schTask.RemoteManagers.Add(fmt.Sprintf("127.0.0.1:%v", port1), remoteMockManager)
			terrs := sch.StartTask(t.ID())
			So(terrs, ShouldBeNil)
			Convey("So all depndencies should have been subscribed to", func() {
				// Ensure that unsubscribe call count is equal to subscribe call count
				// i.e that every subscribe call was followed by an unsubscribe since
				// we errored
				So(localMockManager.SubscribeCallCount, ShouldBeGreaterThan, 0)
				So(remoteMockManager.SubscribeCallCount, ShouldBeGreaterThan, 0)
			})
		})
	})
}
Beispiel #15
0
package fixtures

import (
	"encoding/json"
	"time"

	"github.com/intelsdi-x/snap/core"
	"github.com/intelsdi-x/snap/core/cdata"
	"github.com/intelsdi-x/snap/plugin/helper"
)

var (
	SnapPath = helper.BuildPath

	PluginNameMock1 = "snap-plugin-collector-mock1"
	PluginPathMock1 = helper.PluginFilePath(PluginNameMock1)

	PluginNameMock2 = "snap-plugin-collector-mock2"
	PluginPathMock2 = helper.PluginFilePath(PluginNameMock2)
)

// mocks a metric type
type MockMetricType struct {
	Namespace_ core.Namespace
	Cfg        *cdata.ConfigDataNode
	Ver        int
}

func (m MockMetricType) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Namespace core.Namespace        `json:"namespace"`