func TestTribeConfigYaml(t *testing.T) { config := &mockConfig{ Tribe: GetDefaultConfig(), } path := "../../examples/configs/snap-config-sample.yaml" err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS) var cfg *Config if err == nil { cfg = config.Tribe } Convey("Provided a valid config in YAML", t, func() { Convey("An error should not be returned when unmarshalling the config", func() { So(err, ShouldBeNil) }) Convey("Enable should be true", func() { So(cfg.Enable, ShouldEqual, true) }) Convey("BindAddr should equal 127.0.0.1", func() { So(cfg.BindAddr, ShouldEqual, "127.0.0.1") }) Convey("BindPort should be 16000", func() { So(cfg.BindPort, ShouldEqual, 16000) }) Convey("Name should equal localhost", func() { So(cfg.Name, ShouldEqual, "localhost") }) Convey("Seed should be 1.1.1.1:16000", func() { So(cfg.Seed, ShouldEqual, "1.1.1.1:16000") }) }) }
// Read the snapd configuration from a configuration file func readConfig(cfg *Config, fpath string) { var path string if !defaultConfigFile() && fpath == "" { return } if defaultConfigFile() && fpath == "" { path = defaultConfigPath } if fpath != "" { f, err := os.Stat(fpath) if err != nil { log.Fatal(err) } if f.IsDir() { log.Fatal("configuration path provided must be a file") } path = fpath } serrs := cfgfile.Read(path, &cfg, CONFIG_CONSTRAINTS) if serrs != nil { for _, serr := range serrs { log.WithFields(serr.Fields()).Error(serr.Error()) } log.Fatal("Errors found while parsing global configuration file") } }
func TestRestAPIConfigYaml(t *testing.T) { config := &mockRestAPIConfig{ RestAPI: GetDefaultConfig(), } path := "../../examples/configs/snap-config-sample.yaml" err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS) var cfg *Config if err == nil { cfg = config.RestAPI } Convey("Provided a valid config in YAML", t, func() { Convey("An error should not be returned when unmarshalling the config", func() { So(err, ShouldBeNil) }) Convey("Enable should be true", func() { So(cfg.Enable, ShouldEqual, true) }) Convey("HTTPS should be true", func() { So(cfg.HTTPS, ShouldEqual, true) }) Convey("Port should be 8282", func() { So(cfg.Port, ShouldEqual, 8282) }) Convey("Address should equal 127.0.0.1:12345", func() { So(cfg.Address, ShouldEqual, "127.0.0.1:12345") }) Convey("RestAuth should be true", func() { So(cfg.RestAuth, ShouldEqual, true) }) Convey("RestAuthPassword should equal changeme", func() { So(cfg.RestAuthPassword, ShouldEqual, "changeme") }) Convey("RestCertificate should equal /path/to/cert/file", func() { So(cfg.RestCertificate, ShouldEqual, "/path/to/cert/file") }) Convey("RestKey should equal /path/to/private/key", func() { So(cfg.RestKey, ShouldEqual, "/path/to/private/key") }) }) }
func TestSchedulerConfigYaml(t *testing.T) { config := &mockConfig{ Scheduler: GetDefaultConfig(), } path := "../examples/configs/snap-config-sample.yaml" err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS) var cfg *Config if err == nil { cfg = config.Scheduler } Convey("Provided a valid config in YAML", t, func() { Convey("An error should not be returned when unmarshalling the config", func() { So(err, ShouldBeNil) }) Convey("WorkManagerQueueSize should equal 10", func() { So(cfg.WorkManagerQueueSize, ShouldEqual, 10) }) Convey("WorkManagerPoolSize should equal 2", func() { So(cfg.WorkManagerPoolSize, ShouldEqual, 2) }) }) }
func TestPluginRestCalls(t *testing.T) { CompressedUpload = false Convey("REST API functional V1", t, func() { Convey("Load Plugin - POST - /v1/plugins", func() { Convey("a single plugin loads", func() { // This test alone tests gzip. Saves on test time. CompressedUpload = true r := startAPI(getDefaultMockConfig()) port := r.port col := core.CollectorPluginType pub := core.PublisherPluginType Convey("A global plugin config is added for all plugins", func() { cdn := cdata.NewNode() cdn.AddItem("password", ctypes.ConfigValueStr{Value: "p@ssw0rd"}) r := setPluginConfigItem(port, "", "", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) r2 := getPluginConfigItem(port, &col, "", "") So(r2.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r3 := r2.Body.(*rbody.PluginConfigItem) So(len(r3.Table()), ShouldEqual, 1) So(r3.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) Convey("A plugin config is added for all publishers", func() { cdn := cdata.NewNode() cdn.AddItem("user", ctypes.ConfigValueStr{Value: "john"}) r := setPluginConfigItem(port, core.PublisherPluginType.String(), "", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(len(r1.Table()), ShouldEqual, 2) Convey("A plugin config is added for all versions of a publisher", func() { cdn := cdata.NewNode() cdn.AddItem("path", ctypes.ConfigValueStr{Value: "/usr/local/influxdb/bin"}) r := setPluginConfigItem(port, "2", "influxdb", "", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/influxdb/bin"}) So(len(r1.Table()), ShouldEqual, 3) Convey("A plugin config is added for a specific version of a publisher", func() { cdn := cdata.NewNode() cdn.AddItem("rate", ctypes.ConfigValueFloat{Value: .8}) r := setPluginConfigItem(port, core.PublisherPluginType.String(), "influxdb", "1", cdn) So(r.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r1 := r.Body.(*rbody.SetPluginConfigItem) So(r1.Table()["rate"], ShouldResemble, ctypes.ConfigValueFloat{Value: .8}) So(len(r1.Table()), ShouldEqual, 4) r2 := getPluginConfigItem(port, &pub, "", "") So(r2.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r3 := r2.Body.(*rbody.PluginConfigItem) So(len(r3.Table()), ShouldEqual, 2) r4 := getPluginConfigItem(port, &pub, "influxdb", "1") So(r4.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r5 := r4.Body.(*rbody.PluginConfigItem) So(len(r5.Table()), ShouldEqual, 4) Convey("A global plugin config field is deleted", func() { r := deletePluginConfigItem(port, "", "", "", []string{"password"}) So(r.Body, ShouldHaveSameTypeAs, &rbody.DeletePluginConfigItem{}) r1 := r.Body.(*rbody.DeletePluginConfigItem) So(len(r1.Table()), ShouldEqual, 0) r2 := setPluginConfigItem(port, core.PublisherPluginType.String(), "influxdb", "", cdn) So(r2.Body, ShouldHaveSameTypeAs, &rbody.SetPluginConfigItem{}) r3 := r2.Body.(*rbody.SetPluginConfigItem) So(len(r3.Table()), ShouldEqual, 3) }) }) }) }) }) }) Convey("Plugin config is set at startup", func() { cfg := getDefaultMockConfig() err := cfgfile.Read("../../examples/configs/snap-config-sample.json", &cfg, MOCK_CONSTRAINTS) So(err, ShouldBeNil) if len(SNAP_AUTODISCOVER_PATH) == 0 { if len(SNAP_PATH) != 0 { SNAP_AUTODISCOVER_PATH = fmt.Sprintf("%s/plugin", SNAP_PATH) log.Warning(fmt.Sprintf("SNAP_AUTODISCOVER_PATH has been set to SNAP_PATH/plugin (%s). This might cause test failures", SNAP_AUTODISCOVER_PATH)) } } else { log.Warning(fmt.Sprintf("SNAP_AUTODISCOVER_PATH is set to %s. This might cause test failures", SNAP_AUTODISCOVER_PATH)) } cfg.Control.AutoDiscoverPath = SNAP_AUTODISCOVER_PATH r := startAPI(cfg) port := r.port col := core.CollectorPluginType Convey("Gets the collector config by name and version", func() { r := getPluginConfigItem(port, &col, "pcm", "1") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(len(r1.Table()), ShouldEqual, 6) }) Convey("Gets the config for a collector by name", func() { r := getPluginConfigItem(port, &col, "pcm", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) So(len(r1.Table()), ShouldEqual, 3) }) Convey("Gets the config for all collectors", func() { r := getPluginConfigItem(port, &col, "", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(len(r1.Table()), ShouldEqual, 2) }) Convey("Gets the config for all plugins", func() { r := getPluginConfigItem(port, nil, "", "") So(r.Body, ShouldHaveSameTypeAs, &rbody.PluginConfigItem{}) r1 := r.Body.(*rbody.PluginConfigItem) So(r1.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(len(r1.Table()), ShouldEqual, 1) }) }) }) Convey("Enable task - put - /v1/tasks/:id/enable", func() { Convey("Enable a running task", func(c C) { r := startAPI(getDefaultMockConfig()) port := r.port uploadPlugin(MOCK_PLUGIN_PATH2, port) uploadPlugin(FILE_PLUGIN_PATH, port) r1 := createTask("1.json", "yeti", "1s", true, port) So(r1.Body, ShouldHaveSameTypeAs, new(rbody.AddScheduledTask)) plr1 := r1.Body.(*rbody.AddScheduledTask) id := plr1.ID r2 := startTask(id, port) So(r2.Body, ShouldHaveSameTypeAs, new(rbody.ScheduledTaskStarted)) plr2 := r2.Body.(*rbody.ScheduledTaskStarted) So(plr2.ID, ShouldEqual, id) r4 := enableTask(id, port) So(r4.Body, ShouldHaveSameTypeAs, new(rbody.Error)) plr4 := r4.Body.(*rbody.Error) So(plr4.ErrorMessage, ShouldEqual, "Task must be disabled") }) }) }) }
func TestPluginConfig(t *testing.T) { Convey("Given a plugin config", t, func() { cfg := GetDefaultConfig() So(cfg, ShouldNotBeNil) Convey("with an entry for ALL plugins", func() { cfg.Plugins.All.AddItem("gvar", ctypes.ConfigValueBool{Value: true}) So(len(cfg.Plugins.All.Table()), ShouldEqual, 1) Convey("with an entry for ALL collector plugins", func() { cfg.Plugins.Collector.All.AddItem("user", ctypes.ConfigValueStr{Value: "jane"}) cfg.Plugins.Collector.All.AddItem("password", ctypes.ConfigValueStr{Value: "P@ssw0rd"}) So(len(cfg.Plugins.Collector.All.Table()), ShouldEqual, 2) Convey("an entry for a specific plugin of any version", func() { cfg.Plugins.Collector.Plugins["test"] = newPluginConfigItem(optAddPluginConfigItem("user", ctypes.ConfigValueStr{Value: "john"})) So(len(cfg.Plugins.Collector.Plugins["test"].Table()), ShouldEqual, 1) Convey("and an entry for a specific plugin of a specific version", func() { cfg.Plugins.Collector.Plugins["test"].Versions[1] = cdata.NewNode() cfg.Plugins.Collector.Plugins["test"].Versions[1].AddItem("vvar", ctypes.ConfigValueBool{Value: true}) So(len(cfg.Plugins.Collector.Plugins["test"].Versions[1].Table()), ShouldEqual, 1) Convey("we can get the merged conf for the given plugin", func() { cd := cfg.Plugins.getPluginConfigDataNode(core.CollectorPluginType, "test", 1) So(len(cd.Table()), ShouldEqual, 4) So(cd.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) }) }) }) }) }) }) Convey("Provided a config in JSON we are able to unmarshal it into a valid config", t, func() { config := &mockConfig{ Control: GetDefaultConfig(), } path := "../examples/configs/snap-config-sample.json" err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS) So(err, ShouldBeNil) cfg := config.Control So(cfg.Plugins, ShouldNotBeNil) So(cfg.Plugins.All, ShouldNotBeNil) So(cfg.Plugins.All.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(cfg.Plugins.Collector, ShouldNotBeNil) So(cfg.Plugins.All, ShouldNotBeNil) So(cfg.Plugins.Collector.Plugins["pcm"], ShouldNotBeNil) So(cfg.Plugins.Collector.Plugins["pcm"].Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) So(cfg.Plugins.Collector.Plugins["pcm"].Versions[1].Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(cfg.Plugins.Processor, ShouldNotBeNil) So(cfg.Plugins.Processor.Plugins["movingaverage"].Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) Convey("We can access the config for plugins", func() { Convey("Getting the values of a specific version of a plugin", func() { c := cfg.Plugins.getPluginConfigDataNode(core.CollectorPluginType, "pcm", 1) So(c, ShouldNotBeNil) So(c.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) So(c.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) So(c.Table()["somefloat"], ShouldResemble, ctypes.ConfigValueFloat{Value: 3.14}) So(c.Table()["someint"], ShouldResemble, ctypes.ConfigValueInt{Value: 1234}) So(c.Table()["somebool"], ShouldResemble, ctypes.ConfigValueBool{Value: true}) }) Convey("Getting the common config for collectors", func() { c := cfg.Plugins.getPluginConfigDataNode(core.CollectorPluginType, "", -2) So(c, ShouldNotBeNil) So(len(c.Table()), ShouldEqual, 2) So(c.Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) So(c.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) }) Convey("Overwriting the value of a variable defined for all plugins", func() { c := cfg.Plugins.getPluginConfigDataNode(core.ProcessorPluginType, "movingaverage", 1) So(c, ShouldNotBeNil) So(c.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "new password"}) }) Convey("Retrieving the value of a variable defined for all versions of a plugin", func() { c := cfg.Plugins.getPluginConfigDataNode(core.CollectorPluginType, "pcm", 0) So(c, ShouldNotBeNil) So(c.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) }) Convey("Overwriting the value of a variable defined for all versions of the plugin", func() { c := cfg.Plugins.getPluginConfigDataNode(core.ProcessorPluginType, "movingaverage", 1) So(c, ShouldNotBeNil) So(c.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "new password"}) }) }) }) }
func TestControlConfigYaml(t *testing.T) { config := &mockConfig{ Control: GetDefaultConfig(), } path := "../examples/configs/snap-config-sample.yaml" err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS) var cfg *Config if err == nil { cfg = config.Control } Convey("Provided a valid config in YAML", t, func() { Convey("An error should not be returned when unmarshalling the config", func() { So(err, ShouldBeNil) }) Convey("AutoDiscoverPath should be set to /some/directory/with/plugins", func() { So(cfg.AutoDiscoverPath, ShouldEqual, "/some/directory/with/plugins") }) Convey("CacheExpiration should be set to 750ms", func() { So(cfg.CacheExpiration.Duration, ShouldResemble, 750*time.Millisecond) }) Convey("MaxRunningPlugins should be set to 1", func() { So(cfg.MaxRunningPlugins, ShouldEqual, 1) }) Convey("KeyringPaths should be set to /some/path/with/keyring/files", func() { So(cfg.KeyringPaths, ShouldEqual, "/some/path/with/keyring/files") }) Convey("PluginTrust should be set to 0", func() { So(cfg.PluginTrust, ShouldEqual, 0) }) Convey("Plugins section of control configuration should not be nil", func() { So(cfg.Plugins, ShouldNotBeNil) }) Convey("Plugins.All section should not be nil", func() { So(cfg.Plugins.All, ShouldNotBeNil) }) Convey("A password should be configured for all plugins", func() { So(cfg.Plugins.All.Table()["password"], ShouldResemble, ctypes.ConfigValueStr{Value: "p@ssw0rd"}) }) Convey("Plugins.Collector section should not be nil", func() { So(cfg.Plugins.Collector, ShouldNotBeNil) }) Convey("Plugins.Collector should have config for pcm collector plugin", func() { So(cfg.Plugins.Collector.Plugins["pcm"], ShouldNotBeNil) }) Convey("Config for pcm should set path to pcm binary to /usr/local/pcm/bin", func() { So(cfg.Plugins.Collector.Plugins["pcm"].Table()["path"], ShouldResemble, ctypes.ConfigValueStr{Value: "/usr/local/pcm/bin"}) }) Convey("Config for pcm plugin at version 1 should set user to john", func() { So(cfg.Plugins.Collector.Plugins["pcm"].Versions[1].Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "john"}) }) Convey("Plugins.Processor section should not be nil", func() { So(cfg.Plugins.Processor, ShouldNotBeNil) }) Convey("Movingaverage processor plugin should have user set to jane", func() { So(cfg.Plugins.Processor.Plugins["movingaverage"].Table()["user"], ShouldResemble, ctypes.ConfigValueStr{Value: "jane"}) }) Convey("Plugins.Publisher should not be nil", func() { So(cfg.Plugins.Publisher, ShouldNotBeNil) }) }) }