github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration-cli/docker_cli_prune_unix_test.go (about) 1 //go:build !windows 2 3 package main 4 5 import ( 6 "context" 7 "os" 8 "path/filepath" 9 "strconv" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/Prakhar-Agarwal-byte/moby/integration-cli/checker" 15 "github.com/Prakhar-Agarwal-byte/moby/integration-cli/cli" 16 "github.com/Prakhar-Agarwal-byte/moby/integration-cli/cli/build" 17 "github.com/Prakhar-Agarwal-byte/moby/integration-cli/daemon" 18 "github.com/Prakhar-Agarwal-byte/moby/testutil" 19 "gotest.tools/v3/assert" 20 "gotest.tools/v3/icmd" 21 "gotest.tools/v3/poll" 22 ) 23 24 func (s *DockerCLIPruneSuite) TearDownTest(ctx context.Context, c *testing.T) { 25 s.ds.TearDownTest(ctx, c) 26 } 27 28 func (s *DockerCLIPruneSuite) OnTimeout(c *testing.T) { 29 s.ds.OnTimeout(c) 30 } 31 32 func pruneNetworkAndVerify(c *testing.T, d *daemon.Daemon, kept, pruned []string) { 33 _, err := d.Cmd("network", "prune", "--force") 34 assert.NilError(c, err) 35 36 for _, s := range kept { 37 poll.WaitOn(c, pollCheck(c, func(*testing.T) (interface{}, string) { 38 out, err := d.Cmd("network", "ls", "--format", "{{.Name}}") 39 assert.NilError(c, err) 40 return out, "" 41 }, checker.Contains(s)), poll.WithTimeout(defaultReconciliationTimeout)) 42 } 43 44 for _, s := range pruned { 45 poll.WaitOn(c, pollCheck(c, func(*testing.T) (interface{}, string) { 46 out, err := d.Cmd("network", "ls", "--format", "{{.Name}}") 47 assert.NilError(c, err) 48 return out, "" 49 }, checker.Not(checker.Contains(s))), poll.WithTimeout(defaultReconciliationTimeout)) 50 } 51 } 52 53 func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) { 54 ctx := testutil.GetContext(c) 55 d := s.AddDaemon(ctx, c, true, true) 56 _, err := d.Cmd("network", "create", "n1") // used by container (testprune) 57 assert.NilError(c, err) 58 _, err = d.Cmd("network", "create", "n2") 59 assert.NilError(c, err) 60 _, err = d.Cmd("network", "create", "n3", "--driver", "overlay") // used by service (testprunesvc) 61 assert.NilError(c, err) 62 _, err = d.Cmd("network", "create", "n4", "--driver", "overlay") 63 assert.NilError(c, err) 64 65 cName := "testprune" 66 _, err = d.Cmd("run", "-d", "--name", cName, "--net", "n1", "busybox", "top") 67 assert.NilError(c, err) 68 69 serviceName := "testprunesvc" 70 replicas := 1 71 out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", 72 "--name", serviceName, 73 "--replicas", strconv.Itoa(replicas), 74 "--network", "n3", 75 "busybox", "top") 76 assert.NilError(c, err) 77 assert.Assert(c, strings.TrimSpace(out) != "") 78 poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(replicas+1)), poll.WithTimeout(defaultReconciliationTimeout)) 79 80 // prune and verify 81 pruneNetworkAndVerify(c, d, []string{"n1", "n3"}, []string{"n2", "n4"}) 82 83 // remove containers, then prune and verify again 84 _, err = d.Cmd("rm", "-f", cName) 85 assert.NilError(c, err) 86 _, err = d.Cmd("service", "rm", serviceName) 87 assert.NilError(c, err) 88 poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) 89 90 pruneNetworkAndVerify(c, d, []string{}, []string{"n1", "n3"}) 91 } 92 93 func (s *DockerDaemonSuite) TestPruneImageDangling(c *testing.T) { 94 ctx := testutil.GetContext(c) 95 s.d.StartWithBusybox(ctx, c) 96 97 result := cli.BuildCmd(c, "test", cli.Daemon(s.d), 98 build.WithDockerfile(`FROM busybox 99 LABEL foo=bar`), 100 cli.WithFlags("-q"), 101 ) 102 result.Assert(c, icmd.Success) 103 id := strings.TrimSpace(result.Combined()) 104 105 out, err := s.d.Cmd("images", "-q", "--no-trunc") 106 assert.NilError(c, err) 107 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id)) 108 out, err = s.d.Cmd("image", "prune", "--force") 109 assert.NilError(c, err) 110 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id)) 111 out, err = s.d.Cmd("images", "-q", "--no-trunc") 112 assert.NilError(c, err) 113 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id)) 114 out, err = s.d.Cmd("image", "prune", "--force", "--all") 115 assert.NilError(c, err) 116 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id)) 117 out, err = s.d.Cmd("images", "-q", "--no-trunc") 118 assert.NilError(c, err) 119 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id)) 120 } 121 122 func (s *DockerCLIPruneSuite) TestPruneContainerUntil(c *testing.T) { 123 out := cli.DockerCmd(c, "run", "-d", "busybox").Combined() 124 id1 := strings.TrimSpace(out) 125 cli.WaitExited(c, id1, 5*time.Second) 126 127 until := daemonUnixTime(c) 128 129 out = cli.DockerCmd(c, "run", "-d", "busybox").Combined() 130 id2 := strings.TrimSpace(out) 131 cli.WaitExited(c, id2, 5*time.Second) 132 133 out = cli.DockerCmd(c, "container", "prune", "--force", "--filter", "until="+until).Combined() 134 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 135 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 136 out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc").Combined() 137 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 138 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 139 } 140 141 func (s *DockerCLIPruneSuite) TestPruneContainerLabel(c *testing.T) { 142 out := cli.DockerCmd(c, "run", "-d", "--label", "foo", "busybox").Combined() 143 id1 := strings.TrimSpace(out) 144 cli.WaitExited(c, id1, 5*time.Second) 145 146 out = cli.DockerCmd(c, "run", "-d", "--label", "bar", "busybox").Combined() 147 id2 := strings.TrimSpace(out) 148 cli.WaitExited(c, id2, 5*time.Second) 149 150 out = cli.DockerCmd(c, "run", "-d", "busybox").Combined() 151 id3 := strings.TrimSpace(out) 152 cli.WaitExited(c, id3, 5*time.Second) 153 154 out = cli.DockerCmd(c, "run", "-d", "--label", "foobar", "busybox").Combined() 155 id4 := strings.TrimSpace(out) 156 cli.WaitExited(c, id4, 5*time.Second) 157 158 // Add a config file of label=foobar, that will have no impact if cli is label!=foobar 159 config := `{"pruneFilters": ["label=foobar"]}` 160 d, err := os.MkdirTemp("", "integration-cli-") 161 assert.NilError(c, err) 162 defer os.RemoveAll(d) 163 err = os.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0o644) 164 assert.NilError(c, err) 165 166 // With config.json only, prune based on label=foobar 167 out = cli.DockerCmd(c, "--config", d, "container", "prune", "--force").Combined() 168 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 169 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 170 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 171 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id4)) 172 173 out = cli.DockerCmd(c, "container", "prune", "--force", "--filter", "label=foo").Combined() 174 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 175 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 176 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 177 178 out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc").Combined() 179 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 180 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 181 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 182 183 out = cli.DockerCmd(c, "container", "prune", "--force", "--filter", "label!=bar").Combined() 184 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 185 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 186 187 out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc").Combined() 188 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 189 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 190 191 // With config.json label=foobar and CLI label!=foobar, CLI label!=foobar supersede 192 out = cli.DockerCmd(c, "--config", d, "container", "prune", "--force", "--filter", "label!=foobar").Combined() 193 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 194 195 out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc").Combined() 196 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 197 } 198 199 func (s *DockerCLIPruneSuite) TestPruneVolumeLabel(c *testing.T) { 200 id1 := cli.DockerCmd(c, "volume", "create", "--label", "foo").Stdout() 201 id1 = strings.TrimSpace(id1) 202 assert.Assert(c, id1 != "") 203 204 id2 := cli.DockerCmd(c, "volume", "create", "--label", "bar").Stdout() 205 id2 = strings.TrimSpace(id2) 206 assert.Assert(c, id2 != "") 207 208 id3 := cli.DockerCmd(c, "volume", "create").Stdout() 209 id3 = strings.TrimSpace(id3) 210 assert.Assert(c, id3 != "") 211 212 id4 := cli.DockerCmd(c, "volume", "create", "--label", "foobar").Stdout() 213 id4 = strings.TrimSpace(id4) 214 assert.Assert(c, id4 != "") 215 216 // Add a config file of label=foobar, that will have no impact if cli is label!=foobar 217 config := `{"pruneFilters": ["label=foobar"]}` 218 d, err := os.MkdirTemp("", "integration-cli-") 219 assert.NilError(c, err) 220 defer os.RemoveAll(d) 221 err = os.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0o644) 222 assert.NilError(c, err) 223 224 // With config.json only, prune based on label=foobar 225 out := cli.DockerCmd(c, "--config", d, "volume", "prune", "--force").Combined() 226 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 227 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 228 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 229 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id4)) 230 231 out = cli.DockerCmd(c, "volume", "prune", "--force", "--filter", "label=foo").Combined() 232 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 233 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 234 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 235 236 out = cli.DockerCmd(c, "volume", "ls", "--format", "{{.Name}}").Stdout() 237 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 238 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 239 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 240 241 out = cli.DockerCmd(c, "volume", "prune", "--force", "--filter", "label!=bar").Combined() 242 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 243 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id3)) 244 245 out = cli.DockerCmd(c, "volume", "ls", "--format", "{{.Name}}").Stdout() 246 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 247 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id3)) 248 249 // With config.json label=foobar and CLI label!=foobar, CLI label!=foobar supersede 250 out = cli.DockerCmd(c, "--config", d, "volume", "prune", "--force", "--filter", "label!=foobar").Combined() 251 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 252 out = cli.DockerCmd(c, "volume", "ls", "--format", "{{.Name}}").Stdout() 253 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 254 } 255 256 func (s *DockerCLIPruneSuite) TestPruneNetworkLabel(c *testing.T) { 257 cli.DockerCmd(c, "network", "create", "--label", "foo", "n1") 258 cli.DockerCmd(c, "network", "create", "--label", "bar", "n2") 259 cli.DockerCmd(c, "network", "create", "n3") 260 261 out := cli.DockerCmd(c, "network", "prune", "--force", "--filter", "label=foo").Combined() 262 assert.Assert(c, strings.Contains(strings.TrimSpace(out), "n1")) 263 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n2")) 264 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n3")) 265 266 out = cli.DockerCmd(c, "network", "prune", "--force", "--filter", "label!=bar").Combined() 267 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n1")) 268 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n2")) 269 assert.Assert(c, strings.Contains(strings.TrimSpace(out), "n3")) 270 271 out = cli.DockerCmd(c, "network", "prune", "--force").Combined() 272 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n1")) 273 assert.Assert(c, strings.Contains(strings.TrimSpace(out), "n2")) 274 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), "n3")) 275 } 276 277 func (s *DockerDaemonSuite) TestPruneImageLabel(c *testing.T) { 278 ctx := testutil.GetContext(c) 279 s.d.StartWithBusybox(ctx, c) 280 281 result := cli.BuildCmd(c, "test1", cli.Daemon(s.d), 282 build.WithDockerfile(`FROM busybox 283 LABEL foo=bar`), 284 cli.WithFlags("-q"), 285 ) 286 result.Assert(c, icmd.Success) 287 id1 := strings.TrimSpace(result.Combined()) 288 out, err := s.d.Cmd("images", "-q", "--no-trunc") 289 assert.NilError(c, err) 290 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 291 result = cli.BuildCmd(c, "test2", cli.Daemon(s.d), 292 build.WithDockerfile(`FROM busybox 293 LABEL bar=foo`), 294 cli.WithFlags("-q"), 295 ) 296 result.Assert(c, icmd.Success) 297 id2 := strings.TrimSpace(result.Combined()) 298 299 out, err = s.d.Cmd("images", "-q", "--no-trunc") 300 assert.NilError(c, err) 301 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 302 303 out, err = s.d.Cmd("image", "prune", "--force", "--all", "--filter", "label=foo=bar") 304 assert.NilError(c, err) 305 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id1)) 306 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 307 308 out, err = s.d.Cmd("image", "prune", "--force", "--all", "--filter", "label!=bar=foo") 309 assert.NilError(c, err) 310 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 311 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id2)) 312 313 out, err = s.d.Cmd("image", "prune", "--force", "--all", "--filter", "label=bar=foo") 314 assert.NilError(c, err) 315 assert.Assert(c, !strings.Contains(strings.TrimSpace(out), id1)) 316 assert.Assert(c, strings.Contains(strings.TrimSpace(out), id2)) 317 }