diff --git a/migrations/all/inputs_sflow.go b/migrations/all/inputs_sflow.go new file mode 100644 index 000000000..9fff96df4 --- /dev/null +++ b/migrations/all/inputs_sflow.go @@ -0,0 +1,5 @@ +//go:build !custom || (migrations && (inputs || inputs.sflow)) + +package all + +import _ "github.com/influxdata/telegraf/migrations/inputs_sflow" // register migration diff --git a/migrations/inputs_sflow/migration.go b/migrations/inputs_sflow/migration.go new file mode 100644 index 000000000..87c87fad7 --- /dev/null +++ b/migrations/inputs_sflow/migration.go @@ -0,0 +1,68 @@ +package inputs_sflow + +import ( + "fmt" + + "github.com/influxdata/toml" + "github.com/influxdata/toml/ast" + + "github.com/influxdata/telegraf/migrations" + "github.com/influxdata/telegraf/migrations/common" +) + +const msg = ` + Replacement 'inputs.netflow' will output a different metric format. + Please adapt your queries! +` + +// Define "old" data structure +type sflow struct { + ServiceAddress string `toml:"service_address"` + ReadBufferSize string `toml:"read_buffer_size"` + common.InputOptions +} + +// Migration function +func migrate(tbl *ast.Table) ([]byte, string, error) { + // Decode the old data structure + var old sflow + if err := toml.UnmarshalTable(tbl, &old); err != nil { + return nil, "", err + } + + // Fill common options + plugin := make(map[string]interface{}) + old.InputOptions.Migrate() + general, err := toml.Marshal(old.InputOptions) + if err != nil { + return nil, "", fmt.Errorf("marshalling general options failed: %w", err) + } + if err := toml.Unmarshal(general, &plugin); err != nil { + return nil, "", fmt.Errorf("re-unmarshalling general options failed: %w", err) + } + + // Use a map for the new plugin and fill in the data + plugin["service_address"] = old.ServiceAddress + if old.ReadBufferSize != "" { + plugin["read_buffer_size"] = old.ReadBufferSize + } + + // Create the corresponding metric configurations + cfg := migrations.CreateTOMLStruct("inputs", "netflow") + cfg.Add("inputs", "netflow", 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, msg, nil +} + +// Register the migration function for the plugin type +func init() { + migrations.AddPluginMigration("inputs.sflow", migrate) +} diff --git a/migrations/inputs_sflow/migration_test.go b/migrations/inputs_sflow/migration_test.go new file mode 100644 index 000000000..cf6cd286a --- /dev/null +++ b/migrations/inputs_sflow/migration_test.go @@ -0,0 +1,62 @@ +package inputs_sflow_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/influxdata/telegraf/config" + _ "github.com/influxdata/telegraf/migrations/inputs_sflow" // register migration + _ "github.com/influxdata/telegraf/plugins/inputs/netflow" // register plugin + _ "github.com/influxdata/telegraf/plugins/inputs/sflow" // 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.Inputs) + + // 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.Inputs, len(expected.Inputs)) + actualIDs := make([]string, 0, len(expected.Inputs)) + expectedIDs := make([]string, 0, len(expected.Inputs)) + for i := range actual.Inputs { + actualIDs = append(actualIDs, actual.Inputs[i].ID()) + expectedIDs = append(expectedIDs, expected.Inputs[i].ID()) + } + require.ElementsMatchf(t, expectedIDs, actualIDs, "generated config: %s", string(output)) + }) + } +} diff --git a/migrations/inputs_sflow/testcases/filters/expected.conf b/migrations/inputs_sflow/testcases/filters/expected.conf new file mode 100644 index 000000000..2a508cf1f --- /dev/null +++ b/migrations/inputs_sflow/testcases/filters/expected.conf @@ -0,0 +1,7 @@ +[[inputs.netflow]] +service_address = "udp://:6343" +read_buffer_size = "32KiB" +fieldinclude = ["a"] +name_override = "foo" +[inputs.netflow.tags] +foo = "bar" diff --git a/migrations/inputs_sflow/testcases/filters/telegraf.conf b/migrations/inputs_sflow/testcases/filters/telegraf.conf new file mode 100644 index 000000000..a90801dad --- /dev/null +++ b/migrations/inputs_sflow/testcases/filters/telegraf.conf @@ -0,0 +1,8 @@ +[[inputs.sflow]] + service_address = "udp://:6343" + read_buffer_size = "32KiB" + + name_override = "foo" + fieldpass = ["a"] + [inputs.sflow.tags] + foo = "bar" diff --git a/migrations/inputs_sflow/testcases/minimal/expected.conf b/migrations/inputs_sflow/testcases/minimal/expected.conf new file mode 100644 index 000000000..adc01300a --- /dev/null +++ b/migrations/inputs_sflow/testcases/minimal/expected.conf @@ -0,0 +1,2 @@ +[[inputs.netflow]] +service_address = "udp://:6343" diff --git a/migrations/inputs_sflow/testcases/minimal/telegraf.conf b/migrations/inputs_sflow/testcases/minimal/telegraf.conf new file mode 100644 index 000000000..8935fa3f2 --- /dev/null +++ b/migrations/inputs_sflow/testcases/minimal/telegraf.conf @@ -0,0 +1,11 @@ +# SFlow V5 Protocol Listener +[[inputs.sflow]] + ## Address to listen for sFlow packets. + ## example: service_address = "udp://:6343" + ## service_address = "udp4://:6343" + ## service_address = "udp6://:6343" + service_address = "udp://:6343" + + ## Set the size of the operating system's receive buffer. + ## example: read_buffer_size = "64KiB" + # read_buffer_size = "" diff --git a/migrations/inputs_sflow/testcases/read_buffer_size/expected.conf b/migrations/inputs_sflow/testcases/read_buffer_size/expected.conf new file mode 100644 index 000000000..04612793b --- /dev/null +++ b/migrations/inputs_sflow/testcases/read_buffer_size/expected.conf @@ -0,0 +1,3 @@ +[[inputs.netflow]] +service_address = "udp://:6343" +read_buffer_size = "32KiB" diff --git a/migrations/inputs_sflow/testcases/read_buffer_size/telegraf.conf b/migrations/inputs_sflow/testcases/read_buffer_size/telegraf.conf new file mode 100644 index 000000000..cb5d58ab8 --- /dev/null +++ b/migrations/inputs_sflow/testcases/read_buffer_size/telegraf.conf @@ -0,0 +1,11 @@ +# SFlow V5 Protocol Listener +[[inputs.sflow]] + ## Address to listen for sFlow packets. + ## example: service_address = "udp://:6343" + ## service_address = "udp4://:6343" + ## service_address = "udp6://:6343" + service_address = "udp://:6343" + + ## Set the size of the operating system's receive buffer. + ## example: read_buffer_size = "64KiB" + read_buffer_size = "32KiB" diff --git a/plugins/inputs/deprecations.go b/plugins/inputs/deprecations.go index 7556659a2..d546ff4d3 100644 --- a/plugins/inputs/deprecations.go +++ b/plugins/inputs/deprecations.go @@ -49,6 +49,10 @@ var Deprecations = map[string]telegraf.DeprecationInfo{ Since: "1.15.0", Notice: "use 'inputs.tail' with 'grok' data format instead", }, + "sflow": { + Since: "1.31.0", + Notice: "use 'inputs.netflow' instead", + }, "snmp_legacy": { Since: "1.0.0", RemovalIn: "1.30.0",