ソースを参照

Added StructuredStats method to returned structured stat data

Alex Silver 6 年 前
コミット
f5321a7c41
2 ファイル変更54 行追加0 行削除
  1. 37 0
      iptables/iptables.go
  2. 17 0
      iptables/iptables_test.go

+ 37 - 0
iptables/iptables.go

@@ -72,6 +72,20 @@ type IPTables struct {
 	mode           string // the underlying iptables operating mode, e.g. nf_tables
 }
 
+// Stat represents a structured statistic entry.
+type Stat struct {
+	Packets     string `json:"pkts"`
+	Bytes       string `json:"bytes"`
+	Target      string `json:"target"`
+	Protocol    string `json:"prot"`
+	Opt         string `json:"opt"`
+	Input       string `json:"in"`
+	Output      string `json:"out"`
+	Source      string `json:"source"`
+	Destination string `json:"destination"`
+	Options     string `json:"options"`
+}
+
 // New creates a new IPTables.
 // For backwards compatibility, this always uses IPv4, i.e. "iptables".
 func New() (*IPTables, error) {
@@ -263,6 +277,29 @@ func (ipt *IPTables) Stats(table, chain string) ([][]string, error) {
 	return rows, nil
 }
 
+// StructuredStats returns statistics as structured data which may be further
+// parsed and marshaled.
+func (ipt *IPTables) StructuredStats(table, chain string) ([]Stat, error) {
+	rawStats, err := ipt.Stats(table, chain)
+	if err != nil {
+		return nil, err
+	}
+
+	structStats := []Stat{}
+	for _, rawStat := range rawStats {
+		if len(rawStat) != 10 {
+			return nil, fmt.Errorf("raw stat contained unexpected fields")
+		}
+		structStat := Stat{
+			rawStat[0], rawStat[1], rawStat[2], rawStat[3], rawStat[4],
+			rawStat[5], rawStat[6], rawStat[7], rawStat[8], rawStat[9],
+		}
+		structStats = append(structStats, structStat)
+	}
+
+	return structStats, nil
+}
+
 func (ipt *IPTables) executeList(args []string) ([]string, error) {
 	var stdout bytes.Buffer
 	if err := ipt.runWithOutput(args, &stdout); err != nil {

+ 17 - 0
iptables/iptables_test.go

@@ -307,6 +307,23 @@ func runRulesTests(t *testing.T, ipt *IPTables) {
 		t.Fatalf("Stats mismatch: \ngot  %#v \nneed %#v", stats, expectedStats)
 	}
 
+	structStats, err := ipt.StructuredStats("filter", chain)
+	if err != nil {
+		t.Fatalf("StructuredStats failed: %v", err)
+	}
+
+	expectedStructStats := []Stat{
+		{"0", "0", "ACCEPT", "all", opt, "*", "*", subnet1, address1, ""},
+		{"0", "0", "ACCEPT", "all", opt, "*", "*", subnet2, address2, ""},
+		{"0", "0", "ACCEPT", "all", opt, "*", "*", subnet2, address1, ""},
+		{"0", "0", "ACCEPT", "all", opt, "*", "*", address1, subnet2, ""},
+	}
+
+	if !reflect.DeepEqual(structStats, expectedStructStats) {
+		t.Fatalf("StructuredStats mismatch: \ngot  %#v \nneed %#v",
+			structStats, expectedStructStats)
+	}
+
 	// Clear the chain that was created.
 	err = ipt.ClearChain("filter", chain)
 	if err != nil {