From 9ce131dfc096fe5484a5e3b2a225ef0fa03cc876 Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Thu, 14 Sep 2017 14:59:28 -0700 Subject: [PATCH] Fix skipped line with empty target in iptables (#3235) --- plugins/inputs/iptables/iptables.go | 19 ++-- plugins/inputs/iptables/iptables_test.go | 125 +++++++++++++---------- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/plugins/inputs/iptables/iptables.go b/plugins/inputs/iptables/iptables.go index b552b4657..01041fcc1 100644 --- a/plugins/inputs/iptables/iptables.go +++ b/plugins/inputs/iptables/iptables.go @@ -95,7 +95,7 @@ const measurement = "iptables" var errParse = errors.New("Cannot parse iptables list information") var chainNameRe = regexp.MustCompile(`^Chain\s+(\S+)`) var fieldsHeaderRe = regexp.MustCompile(`^\s*pkts\s+bytes\s+`) -var commentRe = regexp.MustCompile(`\s*/\*\s*(.+?)\s*\*/\s*`) +var valuesRe = regexp.MustCompile(`^\s*(\d+)\s+(\d+)\s+.*?/\*\s*(.+?)\s*\*/\s*`) func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error { lines := strings.Split(data, "\n") @@ -110,21 +110,14 @@ func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error return errParse } for _, line := range lines[2:] { - tokens := strings.Fields(line) - if len(tokens) < 10 { + matches := valuesRe.FindStringSubmatch(line) + if len(matches) != 4 { continue } - pkts := tokens[0] - bytes := tokens[1] - end := strings.Join(tokens[9:], " ") - - matches := commentRe.FindStringSubmatch(end) - if matches == nil { - continue - } - - comment := matches[1] + pkts := matches[1] + bytes := matches[2] + comment := matches[3] tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": comment} fields := make(map[string]interface{}) diff --git a/plugins/inputs/iptables/iptables_test.go b/plugins/inputs/iptables/iptables_test.go index cc53ecc99..cf2f9f913 100644 --- a/plugins/inputs/iptables/iptables_test.go +++ b/plugins/inputs/iptables/iptables_test.go @@ -154,68 +154,85 @@ func TestIptables_Gather(t *testing.T) { tags: []map[string]string{}, fields: [][]map[string]interface{}{}, }, + { // 11 - all target and ports + table: "all_recv", + chains: []string{"accountfwd"}, + values: []string{ + `Chain accountfwd (1 references) + pkts bytes target prot opt in out source destination + 123 456 all -- eth0 * 0.0.0.0/0 0.0.0.0/0 /* all_recv */ + `}, + tags: []map[string]string{ + map[string]string{"table": "all_recv", "chain": "accountfwd", "ruleid": "all_recv"}, + }, + fields: [][]map[string]interface{}{ + {map[string]interface{}{"pkts": uint64(123), "bytes": uint64(456)}}, + }, + }, } for i, tt := range tests { - i++ - ipt := &Iptables{ - Table: tt.table, - Chains: tt.chains, - lister: func(table, chain string) (string, error) { - if len(tt.values) > 0 { - v := tt.values[0] - tt.values = tt.values[1:] - return v, nil - } - return "", nil - }, - } - acc := new(testutil.Accumulator) - err := acc.GatherError(ipt.Gather) - if !reflect.DeepEqual(tt.err, err) { - t.Errorf("%d: expected error '%#v' got '%#v'", i, tt.err, err) - } - if tt.table == "" { - n := acc.NFields() - if n != 0 { - t.Errorf("%d: expected 0 fields if empty table got %d", i, n) + t.Run(tt.table, func(t *testing.T) { + i++ + ipt := &Iptables{ + Table: tt.table, + Chains: tt.chains, + lister: func(table, chain string) (string, error) { + if len(tt.values) > 0 { + v := tt.values[0] + tt.values = tt.values[1:] + return v, nil + } + return "", nil + }, } - continue - } - if len(tt.chains) == 0 { - n := acc.NFields() - if n != 0 { - t.Errorf("%d: expected 0 fields if empty chains got %d", i, n) + acc := new(testutil.Accumulator) + err := acc.GatherError(ipt.Gather) + if !reflect.DeepEqual(tt.err, err) { + t.Errorf("%d: expected error '%#v' got '%#v'", i, tt.err, err) } - continue - } - if len(tt.tags) == 0 { - n := acc.NFields() - if n != 0 { - t.Errorf("%d: expected 0 values got %d", i, n) + if tt.table == "" { + n := acc.NFields() + if n != 0 { + t.Errorf("%d: expected 0 fields if empty table got %d", i, n) + } + return } - continue - } - n := 0 - for j, tags := range tt.tags { - for k, fields := range tt.fields[j] { - if len(acc.Metrics) < n+1 { - t.Errorf("%d: expected at least %d values got %d", i, n+1, len(acc.Metrics)) - break + if len(tt.chains) == 0 { + n := acc.NFields() + if n != 0 { + t.Errorf("%d: expected 0 fields if empty chains got %d", i, n) } - m := acc.Metrics[n] - if !reflect.DeepEqual(m.Measurement, measurement) { - t.Errorf("%d %d %d: expected measurement '%#v' got '%#v'\n", i, j, k, measurement, m.Measurement) - } - if !reflect.DeepEqual(m.Tags, tags) { - t.Errorf("%d %d %d: expected tags\n%#v got\n%#v\n", i, j, k, tags, m.Tags) - } - if !reflect.DeepEqual(m.Fields, fields) { - t.Errorf("%d %d %d: expected fields\n%#v got\n%#v\n", i, j, k, fields, m.Fields) - } - n++ + return } - } + if len(tt.tags) == 0 { + n := acc.NFields() + if n != 0 { + t.Errorf("%d: expected 0 values got %d", i, n) + } + return + } + n := 0 + for j, tags := range tt.tags { + for k, fields := range tt.fields[j] { + if len(acc.Metrics) < n+1 { + t.Errorf("%d: expected at least %d values got %d", i, n+1, len(acc.Metrics)) + break + } + m := acc.Metrics[n] + if !reflect.DeepEqual(m.Measurement, measurement) { + t.Errorf("%d %d %d: expected measurement '%#v' got '%#v'\n", i, j, k, measurement, m.Measurement) + } + if !reflect.DeepEqual(m.Tags, tags) { + t.Errorf("%d %d %d: expected tags\n%#v got\n%#v\n", i, j, k, tags, m.Tags) + } + if !reflect.DeepEqual(m.Fields, fields) { + t.Errorf("%d %d %d: expected fields\n%#v got\n%#v\n", i, j, k, fields, m.Fields) + } + n++ + } + } + }) } }