Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1090,8 +1090,11 @@ prune() { #{{{
update_diagnostic "system.docker.reclaimed_containers_images" "$reclaimed_containers_images"
update_diagnostic "system.docker.prune_filter" "$prune_filter"

# Volumes only. `system prune --volumes` also sweeps every non-running
# container regardless of age, deleting freshly created ECS task containers
# before the agent can start them.
local reclaimed_volumes
reclaimed_volumes=$($CONTAINER_ORCHESTRATOR system prune --volumes -f |
reclaimed_volumes=$($CONTAINER_ORCHESTRATOR volume prune -f |
cut -d: -f2 | tr -d ' ')
update_diagnostic "system.docker.reclaimed_volumes" "$reclaimed_volumes"

Expand Down
4 changes: 4 additions & 0 deletions test/mocks/bin/docker
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# ps -> $MOCK_DOCKER_PS_OUTPUT (default: empty)
# inspect -> $MOCK_DOCKER_INSPECT_OUTPUT (default: healthy)
# system -> $MOCK_DOCKER_SYSTEM_OUTPUT (default: "Total reclaimed space: 0B")
# volume -> $MOCK_DOCKER_VOLUME_OUTPUT (default: "Total reclaimed space: 0B")
# Exit code override: $MOCK_DOCKER_EXIT (default: 0).
printf '%s\n' "docker $*" >>"${MOCK_CALL_LOG}"

Expand All @@ -18,6 +19,9 @@ case "$1" in
system)
echo "${MOCK_DOCKER_SYSTEM_OUTPUT:-Total reclaimed space: 0B}"
;;
volume)
echo "${MOCK_DOCKER_VOLUME_OUTPUT:-Total reclaimed space: 0B}"
;;
esac

exit "${MOCK_DOCKER_EXIT:-0}"
65 changes: 65 additions & 0 deletions test/unit/prune.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env bats
#
# Unit tests for prune(), which the `0 */4 * * *` crontab entry installed by
# setup_cron() invokes on every registered runner.
#
# The container/image sweep is age-guarded with --filter until=4h. The volume
# sweep must never be able to delete a container: an unfiltered
# `docker system prune` removes every non-running container, including one in
# `created` state, which races the ECS agent between docker create and docker
# start and fails the task with CannotStartContainerError / No such container.

setup() {
load "${BATS_TEST_DIRNAME}/../helpers/load.bash"
load_main
CONTAINER_ORCHESTRATOR="docker"
init_diagnostic_dir
}

# Every recorded `docker ... prune` invocation, one per line.
prune_calls() {
mock_calls docker | grep -F "prune" || true
}

@test "prune age-guards the container and image sweep" {
run prune
assert_success

assert_called docker "system prune -f --filter until=4h"
}

@test "prune never issues a system prune without an age filter" {
run prune
assert_success

local unguarded
unguarded="$(prune_calls | grep -F "system prune" | grep -vF -- "--filter" || true)"
assert_equal "$unguarded" ""
}

@test "prune reclaims volumes without a container-deleting sweep" {
run prune
assert_success

assert_called docker "volume prune"

local container_deleting
container_deleting="$(prune_calls | grep -F "system prune --volumes" || true)"
assert_equal "$container_deleting" ""
}

@test "prune records the filter it actually applied to the guarded sweep" {
run prune
assert_success

assert_equal "$(jq -r '.system.docker.prune_filter' "$SG_DIAGNOSTIC_FILE")" "until=4h"
}

@test "prune records reclaimed space for both sweeps" {
run prune
assert_success

refute [ "$(jq -r '.system.docker.last_prune' "$SG_DIAGNOSTIC_FILE")" = "null" ]
refute [ "$(jq -r '.system.docker.reclaimed_containers_images' "$SG_DIAGNOSTIC_FILE")" = "null" ]
refute [ "$(jq -r '.system.docker.reclaimed_volumes' "$SG_DIAGNOSTIC_FILE")" = "null" ]
}