Merge pull request #650 from basecamp/retained-containers

Config the number of containers to keep
This commit is contained in:
Donal McBreen
2024-03-04 12:05:35 +00:00
committed by GitHub
6 changed files with 42 additions and 7 deletions

View File

@@ -18,12 +18,16 @@ class Kamal::Cli::Prune < Kamal::Cli::Base
end
end
desc "containers", "Prune all stopped containers, except the last 5"
desc "containers", "Prune all stopped containers, except the last n (default 5)"
option :retain, type: :numeric, default: nil, desc: "Number of containers to retain"
def containers
retain = options.fetch(:retain, KAMAL.config.retain_containers)
raise "retain must be at least 1" if retain < 1
mutating do
on(KAMAL.hosts) do
execute *KAMAL.auditor.record("Pruned containers"), verbosity: :debug
execute *KAMAL.prune.app_containers
execute *KAMAL.prune.app_containers(retain: retain)
execute *KAMAL.prune.healthcheck_containers
end
end

View File

@@ -13,10 +13,10 @@ class Kamal::Commands::Prune < Kamal::Commands::Base
"while read image tag; do docker rmi $tag; done"
end
def app_containers(keep_last: 5)
def app_containers(retain:)
pipe \
docker(:ps, "-q", "-a", *service_filter, *stopped_containers_filters),
"tail -n +#{keep_last + 1}",
"tail -n +#{retain + 1}",
"while read container_id; do docker rm $container_id; done"
end

View File

@@ -127,6 +127,10 @@ class Kamal::Configuration
raw_config.require_destination
end
def retain_containers
raw_config.retain_containers || 5
end
def volume_args
if raw_config.volumes.present?
@@ -218,7 +222,7 @@ class Kamal::Configuration
def valid?
ensure_destination_if_required && ensure_required_keys_present && ensure_valid_kamal_version
ensure_destination_if_required && ensure_required_keys_present && ensure_valid_kamal_version && ensure_retain_containers_valid
end
def to_h
@@ -291,6 +295,12 @@ class Kamal::Configuration
true
end
def ensure_retain_containers_valid
raise ArgumentError, "Must retain at least 1 container" if retain_containers < 1
true
end
def role_names
raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort

View File

@@ -20,6 +20,15 @@ class CliPruneTest < CliTestCase
assert_match /docker ps -q -a --filter label=service=app --filter status=created --filter status=exited --filter status=dead | tail -n +6 | while read container_id; do docker rm $container_id; done on 1.1.1.\d/, output
assert_match /docker container prune --force --filter label=service=healthcheck-app on 1.1.1.\d/, output
end
run_command("containers", "--retain", "10").tap do |output|
assert_match /docker ps -q -a --filter label=service=app --filter status=created --filter status=exited --filter status=dead | tail -n +11 | while read container_id; do docker rm $container_id; done on 1.1.1.\d/, output
assert_match /docker container prune --force --filter label=service=healthcheck-app on 1.1.1.\d/, output
end
assert_raises(RuntimeError, "retain must be at least 1") do
run_command("containers", "--retain", "0")
end
end
private

View File

@@ -23,7 +23,11 @@ class CommandsPruneTest < ActiveSupport::TestCase
test "app containers" do
assert_equal \
"docker ps -q -a --filter label=service=app --filter status=created --filter status=exited --filter status=dead | tail -n +6 | while read container_id; do docker rm $container_id; done",
new_command.app_containers.join(" ")
new_command.app_containers(retain: 5).join(" ")
assert_equal \
"docker ps -q -a --filter label=service=app --filter status=created --filter status=exited --filter status=dead | tail -n +4 | while read container_id; do docker rm $container_id; done",
new_command.app_containers(retain: 3).join(" ")
end
test "healthcheck containers" do

View File

@@ -299,7 +299,7 @@ class ConfigurationTest < ActiveSupport::TestCase
assert_equal "alternate_web", config.primary_role
assert_equal "1.1.1.4", config.primary_host
assert config.role(:alternate_web).primary?
assert config.role(:alternate_web).primary?
assert config.role(:alternate_web).running_traefik?
end
@@ -309,4 +309,12 @@ class ConfigurationTest < ActiveSupport::TestCase
end
assert_match /bar isn't defined/, error.message
end
test "retain_containers" do
assert_equal 5, @config.retain_containers
config = Kamal::Configuration.new(@deploy_with_roles.merge(retain_containers: 2))
assert_equal 2, config.retain_containers
assert_raises(ArgumentError) { Kamal::Configuration.new(@deploy_with_roles.merge(retain_containers: 0)) }
end
end