From 92e2f6723e884930f3412974ec50ec5094a2b96d Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Thu, 7 Mar 2019 12:01:16 +0100 Subject: [PATCH] [Metricbeat] Make integration tests more generic for modules The goal is that each module on its own has less and less code and is more config based. The basic fetch testing we have for each module is moved into a general integration testing and it uses the configuration to figure out which services to start, ports to talk to etc. This is still WIP and needs quite a bit of cleanup. --- metricbeat/mb/testing/data_test.go | 2 +- .../testing/integration/integration_test.go | 145 ++++++++++++++++++ metricbeat/mb/testing/modules.go | 16 +- .../php_fpm/pool/_meta/testdata/config.yml | 8 + .../php_fpm/process/_meta/testdata/config.yml | 8 + 5 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 metricbeat/mb/testing/integration/integration_test.go diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index 803bfec6d3c3..ab496c2a4ba9 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -106,7 +106,7 @@ func runTest(t *testing.T, file string, module, metricSetName, url string) { s := server(t, file, url) defer s.Close() - metricSet := newMetricSet(t, getConfig(module, metricSetName, s.URL)) + metricSet := NewMetricSet(t, getConfig(module, metricSetName, s.URL)) var events []mb.Event var errs []error diff --git a/metricbeat/mb/testing/integration/integration_test.go b/metricbeat/mb/testing/integration/integration_test.go new file mode 100644 index 000000000000..fdd6deb462bd --- /dev/null +++ b/metricbeat/mb/testing/integration/integration_test.go @@ -0,0 +1,145 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +// +build integration + +package integration + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/tests/compose" + + "gopkg.in/yaml.v2" + + "github.com/elastic/beats/metricbeat/mb" + mbtest "github.com/elastic/beats/metricbeat/mb/testing" + // TODO: generate include file for these tests automatically moving forward + _ "github.com/elastic/beats/metricbeat/module/php_fpm/pool" + _ "github.com/elastic/beats/metricbeat/module/php_fpm/process" +) + +type Config struct { + Type string + URL string + Environment struct { + Host struct { + Env string + Default string + } + Port struct { + Env string + Default string + } + Service string + } +} + +func TestAll(t *testing.T) { + + configFiles, _ := filepath.Glob(getModulesPath() + "/*/*/_meta/testdata/config.yml") + + for _, f := range configFiles { + // get module and metricset name from path + s := strings.Split(f, string(os.PathSeparator)) + moduleName := s[4] + metricSetName := s[5] + + configFile, err := ioutil.ReadFile(f) + if err != nil { + log.Printf("yamlFile.Get err #%v ", err) + } + var config Config + err = yaml.Unmarshal(configFile, &config) + if err != nil { + log.Fatalf("Unmarshal: %v", err) + } + + if config.Environment.Service == "" { + continue + } + + fmt.Println(moduleName) + fmt.Println(metricSetName) + Fetch(t, config, moduleName, metricSetName) + } +} + +func Fetch(t *testing.T, config Config, module, metricSet string) { + compose.EnsureUp(t, config.Environment.Service) + + c := getConfig(module, metricSet, config.Environment.Host.Default+":"+config.Environment.Port.Default) + + var events []mb.Event + var errs []error + + ms := mbtest.NewMetricSet(t, c) + + switch v := ms.(type) { + case mb.ReportingMetricSetV2: + f := mbtest.NewReportingMetricSetV2(t, c) + events, errs = mbtest.ReportingFetchV2(f) + t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), + events[0].BeatEvent(module, metricSet).Fields.StringToPrint()) + case mb.ReportingMetricSetV2Error: + f := mbtest.NewReportingMetricSetV2Error(t, c) + events, errs = mbtest.ReportingFetchV2Error(f) + t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), + events[0].BeatEvent(module, metricSet).Fields.StringToPrint()) + default: + t.Fatalf("unknown type: %T", v) + } + + assert.Empty(t, errs) + if !assert.NotEmpty(t, events) { + t.FailNow() + } +} + +func runTest(t *testing.T, file string, module, metricSetName, url string) { + +} + +// GetConfig returns config for elasticsearch module +func getConfig(module, metricSet, url string) map[string]interface{} { + fmt.Println(url) + return map[string]interface{}{ + "module": module, + "metricsets": []string{metricSet}, + "hosts": []string{url}, + } +} + +func getModulesPath() string { + return "../../../module" +} + +func getModulePath(module string) string { + return getModulesPath() + "/" + module +} + +func getMetricsetPath(module, metricSet string) string { + return getModulePath(module) + "/" + metricSet +} diff --git a/metricbeat/mb/testing/modules.go b/metricbeat/mb/testing/modules.go index 234feee35687..33036b701746 100644 --- a/metricbeat/mb/testing/modules.go +++ b/metricbeat/mb/testing/modules.go @@ -84,7 +84,7 @@ func NewTestModule(t testing.TB, config interface{}) *TestModule { // newMetricSet instantiates a new MetricSet using the given configuration. // The ModuleFactory and MetricSetFactory are obtained from the global // Registry. -func newMetricSet(t testing.TB, config interface{}) mb.MetricSet { +func NewMetricSet(t testing.TB, config interface{}) mb.MetricSet { c, err := common.NewConfigFrom(config) if err != nil { t.Fatal(err) @@ -112,7 +112,7 @@ func newMetricSet(t testing.TB, config interface{}) mb.MetricSet { // configuration. The ModuleFactory and MetricSetFactory are obtained from the // global Registry. func NewEventFetcher(t testing.TB, config interface{}) mb.EventFetcher { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) fetcher, ok := metricSet.(mb.EventFetcher) if !ok { @@ -126,7 +126,7 @@ func NewEventFetcher(t testing.TB, config interface{}) mb.EventFetcher { // configuration. The ModuleFactory and MetricSetFactory are obtained from the // global Registry. func NewEventsFetcher(t testing.TB, config interface{}) mb.EventsFetcher { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) fetcher, ok := metricSet.(mb.EventsFetcher) if !ok { @@ -137,7 +137,7 @@ func NewEventsFetcher(t testing.TB, config interface{}) mb.EventsFetcher { } func NewReportingMetricSet(t testing.TB, config interface{}) mb.ReportingMetricSet { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) reportingMetricSet, ok := metricSet.(mb.ReportingMetricSet) if !ok { @@ -158,7 +158,7 @@ func ReportingFetch(metricSet mb.ReportingMetricSet) ([]common.MapStr, []error) // NewReportingMetricSetV2 returns a new ReportingMetricSetV2 instance. Then // you can use ReportingFetchV2 to perform a Fetch operation with the MetricSet. func NewReportingMetricSetV2(t testing.TB, config interface{}) mb.ReportingMetricSetV2 { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) reportingMetricSetV2, ok := metricSet.(mb.ReportingMetricSetV2) if !ok { @@ -171,7 +171,7 @@ func NewReportingMetricSetV2(t testing.TB, config interface{}) mb.ReportingMetri // NewReportingMetricSetV2Error returns a new ReportingMetricSetV2 instance. Then // you can use ReportingFetchV2 to perform a Fetch operation with the MetricSet. func NewReportingMetricSetV2Error(t testing.TB, config interface{}) mb.ReportingMetricSetV2Error { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) reportingMetricSetV2Error, ok := metricSet.(mb.ReportingMetricSetV2Error) if !ok { @@ -232,7 +232,7 @@ func ReportingFetchV2Error(metricSet mb.ReportingMetricSetV2Error) ([]mb.Event, // configuration. The ModuleFactory and MetricSetFactory are obtained from the // global Registry. func NewPushMetricSet(t testing.TB, config interface{}) mb.PushMetricSet { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) pushMetricSet, ok := metricSet.(mb.PushMetricSet) if !ok { @@ -297,7 +297,7 @@ func RunPushMetricSet(duration time.Duration, metricSet mb.PushMetricSet) ([]com // configuration. The ModuleFactory and MetricSetFactory are obtained from the // global Registry. func NewPushMetricSetV2(t testing.TB, config interface{}) mb.PushMetricSetV2 { - metricSet := newMetricSet(t, config) + metricSet := NewMetricSet(t, config) pushMetricSet, ok := metricSet.(mb.PushMetricSetV2) if !ok { diff --git a/metricbeat/module/php_fpm/pool/_meta/testdata/config.yml b/metricbeat/module/php_fpm/pool/_meta/testdata/config.yml index 7ff4a86bf677..45737672c8da 100644 --- a/metricbeat/module/php_fpm/pool/_meta/testdata/config.yml +++ b/metricbeat/module/php_fpm/pool/_meta/testdata/config.yml @@ -1,2 +1,10 @@ type: http url: "/status?json=" +environment: + host: + env: PHPFPM_HOST + default: 127.0.0.1 + port: + env: PHPFPM_PORT + default: 81 + service: phpfpm diff --git a/metricbeat/module/php_fpm/process/_meta/testdata/config.yml b/metricbeat/module/php_fpm/process/_meta/testdata/config.yml index 1c6cb1189d16..c20361992e9f 100644 --- a/metricbeat/module/php_fpm/process/_meta/testdata/config.yml +++ b/metricbeat/module/php_fpm/process/_meta/testdata/config.yml @@ -1,2 +1,10 @@ type: http url: "/status?full=&json=" +environment: + host: + env: PHPFPM_HOST + default: 127.0.0.1 + port: + env: PHPFPM_PORT + default: 81 + service: phpfpm