Read volume sizes only when asked and remove in bounded batches, so docker_volumes_remove_anonymous answers on a machine with over a thousand volumes (issue 1796)
mesh/merge-gate building on shanks since 00:21
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate building on shanks since 00:21
mesh/delivery superseded: a newer head of the same pull request
This commit is contained in:
@@ -445,7 +445,7 @@ func TestRemoveAnonymousVolumesTakesOnlyTheUnmountedAnonymousOnes(t *testing.T)
|
||||
on("docker volume rm old", Ran{Stdout: "old\n"})
|
||||
c := client(f, 1000)
|
||||
before := time.Date(2026, 10, 3, 0, 0, 0, 0, time.UTC)
|
||||
got, err := c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{DryRun: true, CreatedBefore: &before})
|
||||
got, err := c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{DryRun: true, Sizes: true, CreatedBefore: &before})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -463,7 +463,7 @@ func TestRemoveAnonymousVolumesTakesOnlyTheUnmountedAnonymousOnes(t *testing.T)
|
||||
if len(why) != 3 || !strings.Contains(why["webdata"], "mesh holds") || why["young"] == "" || why["named"] == "" {
|
||||
t.Fatalf("skipped: %v", skipped)
|
||||
}
|
||||
got, err = c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{Why: "leftovers", CreatedBefore: &before})
|
||||
got, err = c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{Why: "leftovers", Sizes: true, CreatedBefore: &before})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -501,3 +501,27 @@ func TestRemoveAnonymousVolumesRefusesANamedVolumeAndKeepsWhatTheMeshHolds(t *te
|
||||
}
|
||||
t.Fatal("tool not served")
|
||||
}
|
||||
|
||||
// 1796/AC3: on a machine with a very large set of volumes docker's size listing does not answer in
|
||||
// time; the tool still answers, and removal never depends on it.
|
||||
func TestRemoveAnonymousVolumesAnswersWhenTheSizeListingDoesNot(t *testing.T) {
|
||||
f := (&fake{}).
|
||||
on("docker ps --all --quiet --no-trunc", Ran{}).
|
||||
on("docker volume ls --quiet", Ran{Stdout: "a1\na2\na3\n"}).
|
||||
on("docker volume inspect", Ran{Stdout: `[{"Name":"a1","Labels":{"com.docker.volume.anonymous":""}},{"Name":"a2","Labels":{"com.docker.volume.anonymous":""}},{"Name":"a3","Labels":{"com.docker.volume.anonymous":""}}]`}).
|
||||
on("docker system df", Ran{Status: 124, Err: "no answer within 20 s"}).
|
||||
on("docker volume rm", Ran{Stdout: "ok\n"})
|
||||
c := client(f, 1000)
|
||||
got, err := c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{DryRun: true})
|
||||
if err != nil || f.ran("docker system df") || !reflect.DeepEqual(got["would_remove"], []string{"a1", "a2", "a3"}) {
|
||||
t.Fatalf("default dry run: %v %v %+v", got, err, f.calls)
|
||||
}
|
||||
got, err = c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{DryRun: true, Sizes: true})
|
||||
if err != nil || !reflect.DeepEqual(got["would_remove"], []string{"a1", "a2", "a3"}) || got["sizes_unknown"] == nil {
|
||||
t.Fatalf("sizes asked, df silent: %v %v", got, err)
|
||||
}
|
||||
got, err = c.RemoveAnonymousVolumes(context.Background(), RemoveVolumesAsk{Why: "w", Sizes: true, Limit: 2})
|
||||
if err != nil || got["count"] != 2 || got["remaining"] != 1 || !f.ran("docker volume rm a1 a2") {
|
||||
t.Fatalf("removal: %v %v %+v", got, err, f.calls)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user