From 762a1989ff4566727ad195436642664809a86acc Mon Sep 17 00:00:00 2001 From: Sven Rebhan <36194019+srebhan@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:40:32 +0200 Subject: [PATCH] feat(migrations): Add migration for 'inputs.io' (#13536) --- migrations/all/inputs_io.go | 5 ++ migrations/inputs_io/migration.go | 32 ++++++++++ migrations/inputs_io/migration_test.go | 61 +++++++++++++++++++ .../inputs_io/testcases/empty/expected.conf | 29 +++++++++ .../inputs_io/testcases/empty/telegraf.conf | 29 +++++++++ .../inputs_io/testcases/full/expected.conf | 10 +++ .../inputs_io/testcases/full/telegraf.conf | 34 +++++++++++ 7 files changed, 200 insertions(+) create mode 100644 migrations/all/inputs_io.go create mode 100644 migrations/inputs_io/migration.go create mode 100644 migrations/inputs_io/migration_test.go create mode 100644 migrations/inputs_io/testcases/empty/expected.conf create mode 100644 migrations/inputs_io/testcases/empty/telegraf.conf create mode 100644 migrations/inputs_io/testcases/full/expected.conf create mode 100644 migrations/inputs_io/testcases/full/telegraf.conf diff --git a/migrations/all/inputs_io.go b/migrations/all/inputs_io.go new file mode 100644 index 000000000..885e1d735 --- /dev/null +++ b/migrations/all/inputs_io.go @@ -0,0 +1,5 @@ +//go:build !custom || (migrations && (inputs || inputs.io || inputs.diskio)) + +package all + +import _ "github.com/influxdata/telegraf/migrations/inputs_io" // register migration diff --git a/migrations/inputs_io/migration.go b/migrations/inputs_io/migration.go new file mode 100644 index 000000000..bb5e5c581 --- /dev/null +++ b/migrations/inputs_io/migration.go @@ -0,0 +1,32 @@ +package inputs_io + +import ( + "github.com/influxdata/toml" + "github.com/influxdata/toml/ast" + + "github.com/influxdata/telegraf/migrations" +) + +// Migration function +func migrate(tbl *ast.Table) ([]byte, string, error) { + // Load the plugin config and directly encode it again as we do not want to + // modify anything beyond the name. + + // Decode the old data structure + var plugin interface{} + if err := toml.UnmarshalTable(tbl, &plugin); err != nil { + return nil, "", err + } + + // Create the corresponding metric configurations + cfg := migrations.CreateTOMLStruct("inputs", "diskio") + cfg.Add("inputs", "diskio", plugin) + + output, err := toml.Marshal(cfg) + return output, "", err +} + +// Register the migration function for the plugin type +func init() { + migrations.AddPluginMigration("inputs.io", migrate) +} diff --git a/migrations/inputs_io/migration_test.go b/migrations/inputs_io/migration_test.go new file mode 100644 index 000000000..384ed0a2b --- /dev/null +++ b/migrations/inputs_io/migration_test.go @@ -0,0 +1,61 @@ +package inputs_io_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/influxdata/telegraf/config" + _ "github.com/influxdata/telegraf/migrations/inputs_io" // register migration + _ "github.com/influxdata/telegraf/plugins/inputs/diskio" // 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.ElementsMatch(t, expectedIDs, actualIDs, string(output)) + }) + } +} diff --git a/migrations/inputs_io/testcases/empty/expected.conf b/migrations/inputs_io/testcases/empty/expected.conf new file mode 100644 index 000000000..807f2c7c7 --- /dev/null +++ b/migrations/inputs_io/testcases/empty/expected.conf @@ -0,0 +1,29 @@ +# Read metrics about disk IO by device +[[inputs.diskio]] + ## By default, telegraf will gather stats for all devices including + ## disk partitions. + ## Setting devices will restrict the stats to the specified devices. + ## NOTE: Globbing expressions (e.g. asterix) are not supported for + ## disk synonyms like '/dev/disk/by-id'. + # devices = ["sda", "sdb", "vd*", "/dev/disk/by-id/nvme-eui.00123deadc0de123"] + ## Uncomment the following line if you need disk serial numbers. + # skip_serial_number = false + # + ## On systems which support it, device metadata can be added in the form of + ## tags. + ## Currently only Linux is supported via udev properties. You can view + ## available properties for a device by running: + ## 'udevadm info -q property -n /dev/sda' + ## Note: Most, but not all, udev properties can be accessed this way. Properties + ## that are currently inaccessible include DEVTYPE, DEVNAME, and DEVPATH. + # device_tags = ["ID_FS_TYPE", "ID_FS_USAGE"] + # + ## Using the same metadata source as device_tags, you can also customize the + ## name of the device via templates. + ## The 'name_templates' parameter is a list of templates to try and apply to + ## the device. The template may contain variables in the form of '$PROPERTY' or + ## '${PROPERTY}'. The first template which does not contain any variables not + ## present for the device is used as the device name tag. + ## The typical use case is for LVM volumes, to get the VG/LV name instead of + ## the near-meaningless DM-0 name. + # name_templates = ["$ID_FS_LABEL","$DM_VG_NAME/$DM_LV_NAME"] \ No newline at end of file diff --git a/migrations/inputs_io/testcases/empty/telegraf.conf b/migrations/inputs_io/testcases/empty/telegraf.conf new file mode 100644 index 000000000..aaf35173f --- /dev/null +++ b/migrations/inputs_io/testcases/empty/telegraf.conf @@ -0,0 +1,29 @@ +# Read metrics about disk IO by device +[[inputs.io]] + ## By default, telegraf will gather stats for all devices including + ## disk partitions. + ## Setting devices will restrict the stats to the specified devices. + ## NOTE: Globbing expressions (e.g. asterix) are not supported for + ## disk synonyms like '/dev/disk/by-id'. + # devices = ["sda", "sdb", "vd*", "/dev/disk/by-id/nvme-eui.00123deadc0de123"] + ## Uncomment the following line if you need disk serial numbers. + # skip_serial_number = false + # + ## On systems which support it, device metadata can be added in the form of + ## tags. + ## Currently only Linux is supported via udev properties. You can view + ## available properties for a device by running: + ## 'udevadm info -q property -n /dev/sda' + ## Note: Most, but not all, udev properties can be accessed this way. Properties + ## that are currently inaccessible include DEVTYPE, DEVNAME, and DEVPATH. + # device_tags = ["ID_FS_TYPE", "ID_FS_USAGE"] + # + ## Using the same metadata source as device_tags, you can also customize the + ## name of the device via templates. + ## The 'name_templates' parameter is a list of templates to try and apply to + ## the device. The template may contain variables in the form of '$PROPERTY' or + ## '${PROPERTY}'. The first template which does not contain any variables not + ## present for the device is used as the device name tag. + ## The typical use case is for LVM volumes, to get the VG/LV name instead of + ## the near-meaningless DM-0 name. + # name_templates = ["$ID_FS_LABEL","$DM_VG_NAME/$DM_LV_NAME"] \ No newline at end of file diff --git a/migrations/inputs_io/testcases/full/expected.conf b/migrations/inputs_io/testcases/full/expected.conf new file mode 100644 index 000000000..5bcb5f4d4 --- /dev/null +++ b/migrations/inputs_io/testcases/full/expected.conf @@ -0,0 +1,10 @@ +# Read metrics about disk IO by device +[[inputs.diskio]] + name_override = "foo" + devices = ["nvme0n1", "sda", "sdb", "vd*", "/dev/disk/by-id/nvme-eui.00123deadc0de123"] + skip_serial_number = true + device_tags = ["ID_FS_TYPE"] + name_templates = ["$ID_FS_LABEL", "$DM_VG_NAME/$DM_LV_NAME", "test"] + + [[inputs.diskio.tags]] + should = "work" \ No newline at end of file diff --git a/migrations/inputs_io/testcases/full/telegraf.conf b/migrations/inputs_io/testcases/full/telegraf.conf new file mode 100644 index 000000000..50acb25bb --- /dev/null +++ b/migrations/inputs_io/testcases/full/telegraf.conf @@ -0,0 +1,34 @@ +# Read metrics about disk IO by device +[[inputs.io]] + name_override = "foo" + + # By default, telegraf will gather stats for all devices including + # disk partitions. + # Setting devices will restrict the stats to the specified devices. + # NOTE: Globbing expressions (e.g. asterix) are not supported for + # disk synonyms like '/dev/disk/by-id'. + devices = ["nvme0n1", "sda", "sdb", "vd*", "/dev/disk/by-id/nvme-eui.00123deadc0de123"] + # Uncomment the following line if you need disk serial numbers. + skip_serial_number = true + + # On systems which support it, device metadata can be added in the form of + # tags. + # Currently only Linux is supported via udev properties. You can view + # available properties for a device by running: + # 'udevadm info -q property -n /dev/sda' + # Note: Most, but not all, udev properties can be accessed this way. Properties + # that are currently inaccessible include DEVTYPE, DEVNAME, and DEVPATH. + device_tags = ["ID_FS_TYPE"] + + # Using the same metadata source as device_tags, you can also customize the + # name of the device via templates. + # The 'name_templates' parameter is a list of templates to try and apply to + # the device. The template may contain variables in the form of '$PROPERTY' or + # '${PROPERTY}'. The first template which does not contain any variables not + # present for the device is used as the device name tag. + # The typical use case is for LVM volumes, to get the VG/LV name instead of + # the near-meaningless DM-0 name. + name_templates = ["$ID_FS_LABEL","$DM_VG_NAME/$DM_LV_NAME", "test"] + + [[inputs.io.tags]] + should = "work" \ No newline at end of file