Fix skipped line with empty target in iptables (#3235)

(cherry picked from commit d5f48e3e96)
This commit is contained in:
Daniel Nelson 2017-09-14 14:59:28 -07:00 committed by Daniel Nelson
parent 86537899b2
commit 72337a1c97
No known key found for this signature in database
GPG Key ID: CAAD59C9444F6155
2 changed files with 77 additions and 67 deletions

View File

@ -95,7 +95,7 @@ const measurement = "iptables"
var errParse = errors.New("Cannot parse iptables list information") var errParse = errors.New("Cannot parse iptables list information")
var chainNameRe = regexp.MustCompile(`^Chain\s+(\S+)`) var chainNameRe = regexp.MustCompile(`^Chain\s+(\S+)`)
var fieldsHeaderRe = regexp.MustCompile(`^\s*pkts\s+bytes\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 { func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error {
lines := strings.Split(data, "\n") lines := strings.Split(data, "\n")
@ -110,21 +110,14 @@ func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error
return errParse return errParse
} }
for _, line := range lines[2:] { for _, line := range lines[2:] {
tokens := strings.Fields(line) matches := valuesRe.FindStringSubmatch(line)
if len(tokens) < 10 { if len(matches) != 4 {
continue continue
} }
pkts := tokens[0] pkts := matches[1]
bytes := tokens[1] bytes := matches[2]
end := strings.Join(tokens[9:], " ") comment := matches[3]
matches := commentRe.FindStringSubmatch(end)
if matches == nil {
continue
}
comment := matches[1]
tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": comment} tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": comment}
fields := make(map[string]interface{}) fields := make(map[string]interface{})

View File

@ -154,68 +154,85 @@ func TestIptables_Gather(t *testing.T) {
tags: []map[string]string{}, tags: []map[string]string{},
fields: [][]map[string]interface{}{}, 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 { for i, tt := range tests {
i++ t.Run(tt.table, func(t *testing.T) {
ipt := &Iptables{ i++
Table: tt.table, ipt := &Iptables{
Chains: tt.chains, Table: tt.table,
lister: func(table, chain string) (string, error) { Chains: tt.chains,
if len(tt.values) > 0 { lister: func(table, chain string) (string, error) {
v := tt.values[0] if len(tt.values) > 0 {
tt.values = tt.values[1:] v := tt.values[0]
return v, nil tt.values = tt.values[1:]
} return v, nil
return "", 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)
} }
continue acc := new(testutil.Accumulator)
} err := acc.GatherError(ipt.Gather)
if len(tt.chains) == 0 { if !reflect.DeepEqual(tt.err, err) {
n := acc.NFields() t.Errorf("%d: expected error '%#v' got '%#v'", i, tt.err, err)
if n != 0 {
t.Errorf("%d: expected 0 fields if empty chains got %d", i, n)
} }
continue if tt.table == "" {
} n := acc.NFields()
if len(tt.tags) == 0 { if n != 0 {
n := acc.NFields() t.Errorf("%d: expected 0 fields if empty table got %d", i, n)
if n != 0 { }
t.Errorf("%d: expected 0 values got %d", i, n) return
} }
continue if len(tt.chains) == 0 {
} n := acc.NFields()
n := 0 if n != 0 {
for j, tags := range tt.tags { t.Errorf("%d: expected 0 fields if empty chains got %d", i, n)
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] return
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++
} }
} 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++
}
}
})
} }
} }