From 8622b0e3370e0010a86f6114ece2d9285df01a26 Mon Sep 17 00:00:00 2001 From: Sven Rebhan <36194019+srebhan@users.noreply.github.com> Date: Mon, 16 Oct 2023 23:54:54 +0200 Subject: [PATCH] feat(migrations): Add migration for outputs.riemann_legacy (#14121) --- migrations/all/outputs_riemann_legacy.go | 5 + migrations/common/output_options.go | 19 ++++ migrations/outputs_riemann_legacy/README.md | 0 .../outputs_riemann_legacy/migration.go | 106 ++++++++++++++++++ .../outputs_riemann_legacy/migration_test.go | 61 ++++++++++ .../testcases/general_options/expected.conf | 5 + .../testcases/general_options/telegraf.conf | 9 ++ .../testcases/simple/expected.conf | 3 + .../testcases/simple/telegraf.conf | 8 ++ 9 files changed, 216 insertions(+) create mode 100644 migrations/all/outputs_riemann_legacy.go create mode 100644 migrations/common/output_options.go create mode 100644 migrations/outputs_riemann_legacy/README.md create mode 100644 migrations/outputs_riemann_legacy/migration.go create mode 100644 migrations/outputs_riemann_legacy/migration_test.go create mode 100644 migrations/outputs_riemann_legacy/testcases/general_options/expected.conf create mode 100644 migrations/outputs_riemann_legacy/testcases/general_options/telegraf.conf create mode 100644 migrations/outputs_riemann_legacy/testcases/simple/expected.conf create mode 100644 migrations/outputs_riemann_legacy/testcases/simple/telegraf.conf diff --git a/migrations/all/outputs_riemann_legacy.go b/migrations/all/outputs_riemann_legacy.go new file mode 100644 index 000000000..bac00ae8e --- /dev/null +++ b/migrations/all/outputs_riemann_legacy.go @@ -0,0 +1,5 @@ +//go:build !custom || (migrations && (outputs || outputs.riemann_legacy)) + +package all + +import _ "github.com/influxdata/telegraf/migrations/outputs_riemann_legacy" // register migration diff --git a/migrations/common/output_options.go b/migrations/common/output_options.go new file mode 100644 index 000000000..fda61ff76 --- /dev/null +++ b/migrations/common/output_options.go @@ -0,0 +1,19 @@ +package common + +type OutputOptions struct { + // General options + Alias string `toml:"alias,omitempty"` + + // Filter options + NamePass []string `toml:"namepass,omitempty"` + NameDrop []string `toml:"namedrop,omitempty"` + FieldPassOld []string `toml:"pass,omitempty"` + FieldPass []string `toml:"fieldpass,omitempty"` + FieldDropOld []string `toml:"drop,omitempty"` + FieldDrop []string `toml:"fielddrop,omitempty"` + TagPassFilters map[string][]string `toml:"tagpass,omitempty"` + TagDropFilters map[string][]string `toml:"tagdrop,omitempty"` + TagExclude []string `toml:"tagexclude,omitempty"` + TagInclude []string `toml:"taginclude,omitempty"` + MetricPass string `toml:"metricpass,omitempty"` +} diff --git a/migrations/outputs_riemann_legacy/README.md b/migrations/outputs_riemann_legacy/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/migrations/outputs_riemann_legacy/migration.go b/migrations/outputs_riemann_legacy/migration.go new file mode 100644 index 000000000..4b16af4ca --- /dev/null +++ b/migrations/outputs_riemann_legacy/migration.go @@ -0,0 +1,106 @@ +package outputs_riemann_legacy + +import ( + "github.com/influxdata/toml" + "github.com/influxdata/toml/ast" + + "github.com/influxdata/telegraf/migrations" + "github.com/influxdata/telegraf/migrations/common" +) + +// Define "old" data structure +type riemannLegacy struct { + URL string `toml:"url"` + Transport string `toml:"transport"` + Separator string `toml:"separator"` + common.OutputOptions +} + +// Define "new" data structure(s) +type riemann struct { + URL string `toml:"url"` + Separator string `toml:"separator"` + + // Common options for outputs + Alias string `toml:"alias,omitempty"` + NamePass []string `toml:"namepass,omitempty"` + NameDrop []string `toml:"namedrop,omitempty"` + FieldPass []string `toml:"fieldpass,omitempty"` + FieldDrop []string `toml:"fielddrop,omitempty"` + TagPassFilters map[string][]string `toml:"tagpass,omitempty"` + TagDropFilters map[string][]string `toml:"tagdrop,omitempty"` + TagExclude []string `toml:"tagexclude,omitempty"` + TagInclude []string `toml:"taginclude,omitempty"` + MetricPass string `toml:"metricpass,omitempty"` +} + +// Migration function +func migrate(tbl *ast.Table) ([]byte, string, error) { + // Decode the old data structure + var old riemannLegacy + if err := toml.UnmarshalTable(tbl, &old); err != nil { + return nil, "", err + } + + // Create new plugin configurations + cfg := migrations.CreateTOMLStruct("outputs", "riemann") + plugin := riemann{ + URL: old.Transport + "://" + old.URL, + Separator: old.Separator, + } + plugin.fillCommon(old.OutputOptions) + cfg.Add("outputs", "riemann", plugin) + + // Marshal the new configuration + buf, err := toml.Marshal(cfg) + if err != nil { + return nil, "", err + } + buf = append(buf, []byte("\n")...) + + // Create the new content to output + return buf, "", nil +} + +func (j *riemann) fillCommon(o common.OutputOptions) { + j.Alias = o.Alias + + if len(o.NamePass) > 0 { + j.NamePass = append(j.NamePass, o.NamePass...) + } + if len(o.NameDrop) > 0 { + j.NameDrop = append(j.NameDrop, o.NameDrop...) + } + if len(o.FieldPass) > 0 || len(o.FieldDropOld) > 0 { + j.FieldPass = append(j.FieldPass, o.FieldPass...) + j.FieldPass = append(j.FieldPass, o.FieldPassOld...) + } + if len(o.FieldDrop) > 0 || len(o.FieldDropOld) > 0 { + j.FieldDrop = append(j.FieldDrop, o.FieldDrop...) + j.FieldDrop = append(j.FieldDrop, o.FieldDropOld...) + } + if len(o.TagPassFilters) > 0 { + j.TagPassFilters = make(map[string][]string, len(o.TagPassFilters)) + for k, v := range o.TagPassFilters { + j.TagPassFilters[k] = v + } + } + if len(o.TagDropFilters) > 0 { + j.TagDropFilters = make(map[string][]string, len(o.TagDropFilters)) + for k, v := range o.TagDropFilters { + j.TagDropFilters[k] = v + } + } + if len(o.TagExclude) > 0 { + j.TagExclude = append(j.TagExclude, o.TagExclude...) + } + if len(o.TagInclude) > 0 { + j.TagInclude = append(j.TagInclude, o.TagInclude...) + } + j.MetricPass = o.MetricPass +} + +// Register the migration function for the plugin type +func init() { + migrations.AddPluginMigration("outputs.riemann_legacy", migrate) +} diff --git a/migrations/outputs_riemann_legacy/migration_test.go b/migrations/outputs_riemann_legacy/migration_test.go new file mode 100644 index 000000000..cf570e483 --- /dev/null +++ b/migrations/outputs_riemann_legacy/migration_test.go @@ -0,0 +1,61 @@ +package outputs_riemann_legacy_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/influxdata/telegraf/config" + _ "github.com/influxdata/telegraf/migrations/outputs_riemann_legacy" // register migration + _ "github.com/influxdata/telegraf/plugins/outputs/riemann" // register plugin +) + +func TestCases(t *testing.T) { + // Get all directories in testdata + folders, err := os.ReadDir("testcases") + require.NoError(t, err) + + for _, f := range folders { + // Only handle folders + if !f.IsDir() { + continue + } + + t.Run(f.Name(), func(t *testing.T) { + testcasePath := filepath.Join("testcases", f.Name()) + inputFile := filepath.Join(testcasePath, "telegraf.conf") + expectedFile := filepath.Join(testcasePath, "expected.conf") + + // Read the expected output + expected := config.NewConfig() + require.NoError(t, expected.LoadConfig(expectedFile)) + require.NotEmpty(t, expected.Outputs) + + // Read the input data + input, remote, err := config.LoadConfigFile(inputFile) + require.NoError(t, err) + require.False(t, remote) + require.NotEmpty(t, input) + + // Migrate + output, n, err := config.ApplyMigrations(input) + require.NoError(t, err) + require.NotEmpty(t, output) + require.GreaterOrEqual(t, n, uint64(1)) + actual := config.NewConfig() + require.NoError(t, actual.LoadConfigData(output)) + + // Test the output + require.Len(t, actual.Outputs, len(expected.Outputs)) + actualIDs := make([]string, 0, len(expected.Outputs)) + expectedIDs := make([]string, 0, len(expected.Outputs)) + for i := range actual.Outputs { + actualIDs = append(actualIDs, actual.Outputs[i].ID()) + expectedIDs = append(expectedIDs, expected.Outputs[i].ID()) + } + require.ElementsMatch(t, expectedIDs, actualIDs) + }) + } +} diff --git a/migrations/outputs_riemann_legacy/testcases/general_options/expected.conf b/migrations/outputs_riemann_legacy/testcases/general_options/expected.conf new file mode 100644 index 000000000..1c8aa82ec --- /dev/null +++ b/migrations/outputs_riemann_legacy/testcases/general_options/expected.conf @@ -0,0 +1,5 @@ +[[outputs.riemann]] +url = "udp://localhost:5555" +separator = "." +namepass = ["foo"] +fieldpass = ["motor_*"] diff --git a/migrations/outputs_riemann_legacy/testcases/general_options/telegraf.conf b/migrations/outputs_riemann_legacy/testcases/general_options/telegraf.conf new file mode 100644 index 000000000..d35d5841e --- /dev/null +++ b/migrations/outputs_riemann_legacy/testcases/general_options/telegraf.conf @@ -0,0 +1,9 @@ +# Configuration for the Riemann server to send metrics to +[[outputs.riemann_legacy]] + url = "localhost:5555" + transport = "udp" + separator = "." + + ## Metric filtering + namepass = ["foo"] + fieldpass = ["motor_*"] diff --git a/migrations/outputs_riemann_legacy/testcases/simple/expected.conf b/migrations/outputs_riemann_legacy/testcases/simple/expected.conf new file mode 100644 index 000000000..c91b500db --- /dev/null +++ b/migrations/outputs_riemann_legacy/testcases/simple/expected.conf @@ -0,0 +1,3 @@ +[[outputs.riemann]] +url = "tcp://localhost:5555" +separator = " " diff --git a/migrations/outputs_riemann_legacy/testcases/simple/telegraf.conf b/migrations/outputs_riemann_legacy/testcases/simple/telegraf.conf new file mode 100644 index 000000000..9ba4e0954 --- /dev/null +++ b/migrations/outputs_riemann_legacy/testcases/simple/telegraf.conf @@ -0,0 +1,8 @@ +# Configuration for the Riemann server to send metrics to +[[outputs.riemann_legacy]] + ## URL of server + url = "localhost:5555" + ## transport protocol to use either tcp or udp + transport = "tcp" + ## separator to use between input name and field name in Riemann service name + separator = " " \ No newline at end of file