From 1df0646b018882c35d73d1bf14c9cdfe1a0c47bd Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Mon, 27 Sep 2021 15:34:28 +0200
Subject: [PATCH 1/2] CNI: network remove do not error for ENOENT

Make podman network rm more robust by checking for ENOENT if we cannot
remove the config file. If it does not exists there is no reason to
error. This is especially useful for podman network prune.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 libpod/network/cni/config.go      |  6 +++++-
 libpod/network/cni/config_test.go | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/libpod/network/cni/config.go b/libpod/network/cni/config.go
index 670ee0c654..3df155637b 100644
--- a/libpod/network/cni/config.go
+++ b/libpod/network/cni/config.go
@@ -170,7 +170,11 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error {
 	file := network.filename
 	delete(n.networks, network.libpodNet.Name)
 
-	return os.Remove(file)
+	// make sure to not error for ErrNotExist
+	if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) {
+		return err
+	}
+	return nil
 }
 
 // NetworkList will return all known Networks. Optionally you can
diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go
index a0a0ea1af8..288cf4626c 100644
--- a/libpod/network/cni/config_test.go
+++ b/libpod/network/cni/config_test.go
@@ -1021,6 +1021,27 @@ var _ = Describe("Config", func() {
 			Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config"))
 		})
 
+		It("remove network should not error when config file does not exists on disk", func() {
+			name := "mynet"
+			network := types.Network{Name: name}
+			_, err := libpodNet.NetworkCreate(network)
+			Expect(err).To(BeNil())
+
+			path := filepath.Join(cniConfDir, name+".conflist")
+			Expect(path).To(BeARegularFile())
+
+			err = os.Remove(path)
+			Expect(err).To(BeNil())
+			Expect(path).ToNot(BeARegularFile())
+
+			err = libpodNet.NetworkRemove(name)
+			Expect(err).To(BeNil())
+
+			nets, err := libpodNet.NetworkList()
+			Expect(err).To(BeNil())
+			Expect(nets).To(HaveLen(1))
+			Expect(nets).ToNot(ContainElement(HaveNetworkName(name)))
+		})
 	})
 
 	Context("network load valid existing ones", func() {

From ca3c08bf9c647f4c8300b34919bf0107c2ef2718 Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Mon, 27 Sep 2021 15:47:37 +0200
Subject: [PATCH 2/2] fix podman network prune integration test flakes

The podman integration tests run in parallel. Because all tests use the
same CNI config dir the podman network prune test will remove networks
which are used by other tests at the moment and thus creating
unexpected flakes.

The solution use an extra cni config dir for the network prune test.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 test/e2e/network_test.go | 52 +++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 25 deletions(-)

diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 7e56b8a25a..8e47fac759 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -603,6 +603,11 @@ var _ = Describe("Podman network", func() {
 	})
 
 	It("podman network prune --filter", func() {
+		// set custom cni directory to prevent flakes
+		podmanTest.CNIConfigDir = tempdir
+		if IsRemote() {
+			podmanTest.RestartRemoteService()
+		}
 		net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1"
 
 		nc := podmanTest.Podman([]string{"network", "create", net1})
@@ -613,11 +618,10 @@ var _ = Describe("Podman network", func() {
 		list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
 		list.WaitWithDefaultTimeout()
 		Expect(list).Should(Exit(0))
+		Expect(list.OutputToStringArray()).Should(HaveLen(2))
 
-		Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
-		if !isRootless() {
-			Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
-		}
+		Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+		Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
 
 		// -f needed only to skip y/n question
 		prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=50"})
@@ -627,11 +631,10 @@ var _ = Describe("Podman network", func() {
 		listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
 		listAgain.WaitWithDefaultTimeout()
 		Expect(listAgain).Should(Exit(0))
+		Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
 
-		Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeTrue())
-		if !isRootless() {
-			Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
-		}
+		Expect(listAgain.OutputToStringArray()).Should(ContainElement(net1))
+		Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
 
 		// -f needed only to skip y/n question
 		prune = podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=5000000000000"})
@@ -641,14 +644,18 @@ var _ = Describe("Podman network", func() {
 		listAgain = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
 		listAgain.WaitWithDefaultTimeout()
 		Expect(listAgain).Should(Exit(0))
+		Expect(listAgain.OutputToStringArray()).Should(HaveLen(1))
 
-		Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
-		if !isRootless() {
-			Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
-		}
+		Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+		Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
 	})
 
 	It("podman network prune", func() {
+		// set custom cni directory to prevent flakes
+		podmanTest.CNIConfigDir = tempdir
+		if IsRemote() {
+			podmanTest.RestartRemoteService()
+		}
 		// Create two networks
 		// Check they are there
 		// Run a container on one of them
@@ -669,13 +676,11 @@ var _ = Describe("Podman network", func() {
 
 		list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
 		list.WaitWithDefaultTimeout()
-		Expect(list).Should(Exit(0))
+		Expect(list.OutputToStringArray()).Should(HaveLen(3))
 
-		Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
-		Expect(StringInSlice(net2, list.OutputToStringArray())).To(BeTrue())
-		if !isRootless() {
-			Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
-		}
+		Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+		Expect(list.OutputToStringArray()).Should(ContainElement(net2))
+		Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
 
 		session := podmanTest.Podman([]string{"run", "-dt", "--net", net2, ALPINE, "top"})
 		session.WaitWithDefaultTimeout()
@@ -688,13 +693,10 @@ var _ = Describe("Podman network", func() {
 		listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
 		listAgain.WaitWithDefaultTimeout()
 		Expect(listAgain).Should(Exit(0))
+		Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
 
-		Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
-		Expect(StringInSlice(net2, listAgain.OutputToStringArray())).To(BeTrue())
-		// Make sure default network 'podman' still exists
-		if !isRootless() {
-			Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
-		}
-
+		Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+		Expect(listAgain.OutputToStringArray()).Should(ContainElement(net2))
+		Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
 	})
 })