From 8024949fe747fe3d4c12209ba971b98ca177a471 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 3 Feb 2023 13:20:03 +0100 Subject: [PATCH] Remove only specific container needed for rebooting --- lib/mrsk/cli/app.rb | 17 ++++++++++++----- lib/mrsk/commands/app.rb | 18 ++++++++++++++++-- lib/mrsk/commands/concerns/repository.rb | 4 ++++ test/cli/app_test.rb | 21 +++++++++++++++++---- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/mrsk/cli/app.rb b/lib/mrsk/cli/app.rb index 06fd552d..ba64535b 100644 --- a/lib/mrsk/cli/app.rb +++ b/lib/mrsk/cli/app.rb @@ -21,10 +21,12 @@ class Mrsk::Cli::App < Mrsk::Cli::Base end end - desc "reboot", "Reboot app on host (stop container, remove containers, start new container)" + desc "reboot", "Reboot app on host (stop container, remove container, start new container with latest image)" def reboot + old_version = current_running_version + stop - remove_containers + remove_container old_version boot end @@ -147,7 +149,12 @@ class Mrsk::Cli::App < Mrsk::Cli::Base remove_images end - desc "remove_containers", "Remove app containers from servers" + desc "remove_container [VERSION]", "Remove app container with given version from servers" + def remove_container(version) + on(MRSK.hosts) { execute *MRSK.app.remove_container(version: version) } + end + + desc "remove_containers", "Remove all app containers from servers" def remove_containers on(MRSK.hosts) { execute *MRSK.app.remove_containers } end @@ -184,9 +191,9 @@ class Mrsk::Cli::App < Mrsk::Cli::Base version end - def current_running_version(host:) + def current_running_version(host: MRSK.primary_host) version = nil on(host) { version = capture_with_info(*MRSK.app.current_running_version).strip } - version + version.presence end end diff --git a/lib/mrsk/commands/app.rb b/lib/mrsk/commands/app.rb index 237277fd..c95aa1e1 100644 --- a/lib/mrsk/commands/app.rb +++ b/lib/mrsk/commands/app.rb @@ -10,7 +10,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base docker :run, "-d", "--restart unless-stopped", - "--name", config.service_with_version, + "--name", service_with_version, *rails_master_key_arg, *role.env_args, *config.volume_args, @@ -20,7 +20,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base end def start(version: config.version) - docker :start, "#{config.service}-#{version}" + docker :start, service_with_version(version) end def current_container_id @@ -84,6 +84,12 @@ class Mrsk::Commands::App < Mrsk::Commands::Base docker :container, :ls, "-a", *service_filter end + def remove_container(version:) + pipe \ + container_id_for(container_name: service_with_version(version)), + docker(:container, :rm) + end + def remove_containers docker :container, :prune, "-f", *service_filter end @@ -97,6 +103,14 @@ class Mrsk::Commands::App < Mrsk::Commands::Base end private + def service_with_version(version = nil) + if version + "#{config.service}-#{version}" + else + config.service_with_version + end + end + def service_filter [ "--filter", "label=service=#{config.service}" ] end diff --git a/lib/mrsk/commands/concerns/repository.rb b/lib/mrsk/commands/concerns/repository.rb index 6e8a4f24..18a8f5fd 100644 --- a/lib/mrsk/commands/concerns/repository.rb +++ b/lib/mrsk/commands/concerns/repository.rb @@ -1,5 +1,9 @@ module Mrsk::Commands::Concerns module Repository + def container_id_for(container_name:) + docker :container, :ls, "-a", "-f", "name=#{container_name}", "-q" + end + def current_running_version # FIXME: Find more graceful way to extract the version from "app-version" than using sed and tail! pipe \ diff --git a/test/cli/app_test.rb b/test/cli/app_test.rb index e63838ef..d3856c98 100644 --- a/test/cli/app_test.rb +++ b/test/cli/app_test.rb @@ -5,11 +5,24 @@ class CliAppTest < CliTestCase assert_match /Running docker run -d --restart unless-stopped/, run_command("boot") end - test "reboot" do + test "reboot to default version" do run_command("reboot").tap do |output| - assert_match /docker stop/, output - assert_match /docker container prune/, output - assert_match /docker run -d --restart unless-stopped/, output + assert_match /docker ps --filter label=service=app/, output # Find current container + assert_match /docker stop/, output # Stop old container + assert_match /docker container rm/, output # Remove old container + assert_match /docker run -d --restart unless-stopped .* dhh\/app:999/, output # Start new container + end + end + + test "reboot to specific version" do + run_command("reboot", "--version", "456").tap do |output| + assert_match /docker run -d --restart unless-stopped .* dhh\/app:456/, output + end + end + + test "remove_container" do + run_command("remove_container", "1234567").tap do |output| + assert_match /docker container ls -a -f name=app-1234567 -q | docker container rm/, output end end