Browse Source

error: add Error.IsNotExist

Small method to determine if the error is due to the desired target not
existing.
Casey Callendrello 7 years ago
parent
commit
afafc097ec
2 changed files with 73 additions and 0 deletions
  1. 7 0
      iptables/iptables.go
  2. 66 0
      iptables/iptables_test.go

+ 7 - 0
iptables/iptables.go

@@ -41,6 +41,13 @@ func (e *Error) Error() string {
 	return fmt.Sprintf("running %v: exit status %v: %v", e.cmd.Args, e.ExitStatus(), e.msg)
 }
 
+// IsNotExist returns true if the error is due to the chain or rule not existing
+func (e *Error) IsNotExist() bool {
+	return e.ExitStatus() == 1 &&
+		(e.msg == "iptables: Bad rule (does a matching rule exist in that chain?).\n" ||
+			e.msg == "iptables: No chain/target/match by that name.\n")
+}
+
 // Protocol to differentiate between IPv4 and IPv6
 type Protocol byte
 

+ 66 - 0
iptables/iptables_test.go

@@ -145,6 +145,10 @@ func runChainTests(t *testing.T, ipt *IPTables) {
 	if err == nil {
 		t.Fatalf("DeleteChain of non-empty chain did not fail")
 	}
+	e, ok := err.(*Error)
+	if ok && e.IsNotExist() {
+		t.Fatal("DeleteChain of non-empty chain returned IsNotExist")
+	}
 
 	err = ipt.ClearChain("filter", chain)
 	if err != nil {
@@ -342,3 +346,65 @@ func TestError(t *testing.T) {
 		t.Fatalf("expected type os.PathError, got %t", e)
 	}
 }
+
+func TestIsNotExist(t *testing.T) {
+	ipt, err := New()
+	if err != nil {
+		t.Fatalf("failed to init: %v", err)
+	}
+	// Create a chain, add a rule
+	chainName := randChain(t)
+	err = ipt.NewChain("filter", chainName)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		ipt.ClearChain("filter", chainName)
+		ipt.DeleteChain("filter", chainName)
+	}()
+
+	err = ipt.Append("filter", chainName, "-p", "tcp", "-j", "DROP")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Delete rule twice
+	err = ipt.Delete("filter", chainName, "-p", "tcp", "-j", "DROP")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = ipt.Delete("filter", chainName, "-p", "tcp", "-j", "DROP")
+	if err == nil {
+		t.Fatal("delete twice got no error...")
+	}
+
+	e, ok := err.(*Error)
+	if !ok {
+		t.Fatalf("Got wrong error type, expected iptables.Error, got %T", err)
+	}
+
+	if !e.IsNotExist() {
+		t.Fatal("IsNotExist returned false, expected true")
+	}
+
+	// Delete chain
+	err = ipt.DeleteChain("filter", chainName)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = ipt.DeleteChain("filter", chainName)
+	if err == nil {
+		t.Fatal("deletechain twice got no error...")
+	}
+
+	e, ok = err.(*Error)
+	if !ok {
+		t.Fatalf("Got wrong error type, expected iptables.Error, got %T", err)
+	}
+
+	if !e.IsNotExist() {
+		t.Fatal("IsNotExist returned false, expected true")
+	}
+}