From cad9578b0e3e163cc2e468b3f36dfce34cf7d88b Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Thu, 5 Oct 2023 14:28:22 -0400 Subject: [PATCH] Use logical AND on chained label! filters Fixes the filter matching for chained negated labels (label!) on containers and volumes. When pruning with chained label! filters, the filters will be ANDed instead of ORed. Fixes #17413 Signed-off-by: Jake Correnti --- pkg/domain/filters/containers.go | 2 +- pkg/domain/filters/volumes.go | 4 +-- test/e2e/network_test.go | 45 ++++++++++++++++++++++++++++++++ test/e2e/prune_test.go | 24 +++++++++++++++++ test/e2e/volume_prune_test.go | 30 +++++++++++++++++++++ 5 files changed, 102 insertions(+), 3 deletions(-) diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 6c4aa49251..55091b50f6 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -306,7 +306,7 @@ func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r * }, nil case "label!": return func(c *libpod.Container) bool { - return !filters.MatchLabelFilters(filterValues, c.Labels()) + return filters.MatchNegatedLabelFilters(filterValues, c.Labels()) }, nil case "until": return prepareUntilFilterFunc(filterValues) diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go index 4c534e44cf..09772269c5 100644 --- a/pkg/domain/filters/volumes.go +++ b/pkg/domain/filters/volumes.go @@ -42,7 +42,7 @@ func GenerateVolumeFilters(filter string, filterValues []string, runtime *libpod }, nil case "label!": return func(v *libpod.Volume) bool { - return !filters.MatchLabelFilters(filterValues, v.Labels()) + return filters.MatchNegatedLabelFilters(filterValues, v.Labels()) }, nil case "opt": return func(v *libpod.Volume) bool { @@ -111,7 +111,7 @@ func GeneratePruneVolumeFilters(filter string, filterValues []string, runtime *l }, nil case "label!": return func(v *libpod.Volume) bool { - return !filters.MatchLabelFilters(filterValues, v.Labels()) + return filters.MatchNegatedLabelFilters(filterValues, v.Labels()) }, nil case "until": return createUntilFilterVolumeFunction(filterValues) diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 2d94f3f903..cb7ec79725 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -744,4 +744,49 @@ var _ = Describe("Podman network", func() { Expect(listAgain.OutputToStringArray()).Should(ContainElement(net2)) Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman")) }) + + It("podman network prune with chained label!", func() { + useCustomNetworkDir(podmanTest, tempdir) + net := "macvlan" + stringid.GenerateRandomID() + net1 := net + "1" + net2 := net + "2" + net3 := net + "3" + nc := podmanTest.Podman([]string{"network", "create", "--label=foo", net1}) + nc.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net1) + Expect(nc).Should(ExitCleanly()) + + nc2 := podmanTest.Podman([]string{"network", "create", "--label=bar", net2}) + nc2.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net2) + Expect(nc2).Should(ExitCleanly()) + + nc3 := podmanTest.Podman([]string{"network", "create", "--label=foobar", net3}) + nc3.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net3) + Expect(nc3).Should(ExitCleanly()) + + list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) + list.WaitWithDefaultTimeout() + Expect(list.OutputToStringArray()).Should(HaveLen(4)) + + Expect(list.OutputToStringArray()).Should(ContainElement(net1)) + Expect(list.OutputToStringArray()).Should(ContainElement(net2)) + Expect(list.OutputToStringArray()).Should(ContainElement(net3)) + Expect(list.OutputToStringArray()).Should(ContainElement("podman")) + + prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "label!=foo", "--filter", "label!=foobar"}) + prune.WaitWithDefaultTimeout() + Expect(prune).Should(ExitCleanly()) + + listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) + listAgain.WaitWithDefaultTimeout() + Expect(listAgain).Should(ExitCleanly()) + Expect(listAgain.OutputToStringArray()).Should(HaveLen(3)) + + Expect(listAgain.OutputToStringArray()).Should(ContainElement(net1)) + Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net2)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement(net3)) + Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman")) + }) }) diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 01e8484785..0a629b7008 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -593,4 +593,28 @@ var _ = Describe("Podman prune", func() { Expect(err).ToNot(HaveOccurred()) Expect(dirents).To(HaveLen(3)) }) + + It("podman container prune with chained label!", func() { + foobar := podmanTest.Podman([]string{"create", "--label", "foobar", "--name", "foobar", ALPINE}) + foobar.WaitWithDefaultTimeout() + Expect(foobar).Should(ExitCleanly()) + + foo := podmanTest.Podman([]string{"create", "--label", "foo", "--name", "foo", ALPINE}) + foo.WaitWithDefaultTimeout() + Expect(foo).Should(ExitCleanly()) + + bar := podmanTest.Podman([]string{"create", "--label", "bar", "--name", "bar", ALPINE}) + bar.WaitWithDefaultTimeout() + Expect(bar).Should(ExitCleanly()) + + Expect(podmanTest.NumberOfContainers()).To(Equal(3)) + + prune := podmanTest.Podman([]string{"container", "prune", "--force", "--filter", "label!=foo", "--filter", "label!=foobar"}) + prune.WaitWithDefaultTimeout() + Expect(prune).Should(ExitCleanly()) + + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + Expect(prune.OutputToStringArray()).To(HaveLen(1)) + Expect(prune.OutputToString()).To(Equal(bar.OutputToString())) + }) }) diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go index 82f0b35c4f..dd0158518c 100644 --- a/test/e2e/volume_prune_test.go +++ b/test/e2e/volume_prune_test.go @@ -190,4 +190,34 @@ var _ = Describe("Podman volume prune", func() { Expect(session.OutputToStringArray()).To(HaveLen(1)) Expect(session.OutputToStringArray()[0]).To(Equal(vol1)) }) + + It("podman volume prune with chained label!", func() { + foobar := podmanTest.Podman([]string{"volume", "create", "--label", "foobar", "foobar"}) + foobar.WaitWithDefaultTimeout() + Expect(foobar).Should(ExitCleanly()) + + foo := podmanTest.Podman([]string{"volume", "create", "--label", "foo", "foo"}) + foo.WaitWithDefaultTimeout() + Expect(foo).Should(ExitCleanly()) + + bar := podmanTest.Podman([]string{"volume", "create", "--label", "bar", "bar"}) + bar.WaitWithDefaultTimeout() + Expect(bar).Should(ExitCleanly()) + + ls := podmanTest.Podman([]string{"volume", "list", "-q"}) + ls.WaitWithDefaultTimeout() + Expect(ls).Should(ExitCleanly()) + Expect(ls.OutputToStringArray()).To(HaveLen(3)) + + prune := podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label!=foo", "--filter", "label!=foobar"}) + prune.WaitWithDefaultTimeout() + Expect(prune).Should(ExitCleanly()) + + ls = podmanTest.Podman([]string{"volume", "list", "-q"}) + ls.WaitWithDefaultTimeout() + Expect(ls).Should(ExitCleanly()) + Expect(ls.OutputToStringArray()).To(HaveLen(2)) + Expect(prune.OutputToStringArray()).To(HaveLen(1)) + Expect(prune.OutputToString()).To(Equal("bar")) + }) })