From 1f721739d662c7a6fa1dd9dbec85265c21a1224e Mon Sep 17 00:00:00 2001 From: Donal McBreen Date: Mon, 16 Sep 2024 15:51:58 +0100 Subject: [PATCH] Use version 0.1.0 of kamal-proxy and add minimum version check --- lib/kamal/cli/proxy.rb | 6 +++++ lib/kamal/commands/proxy.rb | 6 +++++ lib/kamal/configuration/proxy.rb | 5 ++-- lib/kamal/utils.rb | 4 ++++ test/cli/proxy_test.rb | 40 +++++++++++++++++++++++++++++--- test/commands/proxy_test.rb | 14 +++++++---- test/integration/main_test.rb | 2 +- test/integration/proxy_test.rb | 4 ++-- 8 files changed, 69 insertions(+), 12 deletions(-) diff --git a/lib/kamal/cli/proxy.rb b/lib/kamal/cli/proxy.rb index 3ac02c76..108d7855 100644 --- a/lib/kamal/cli/proxy.rb +++ b/lib/kamal/cli/proxy.rb @@ -10,6 +10,12 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base on(KAMAL.proxy_hosts) do |host| execute *KAMAL.registry.login + + version = capture_with_info(*KAMAL.proxy.version).strip.presence + + if version && Kamal::Utils.older_version?(version, Kamal::Configuration::Proxy::MINIMUM_VERSION) + raise "kamal-proxy version #{version} is too old, please reboot to update to at least #{Kamal::Configuration::Proxy::MINIMUM_VERSION}" + end execute *KAMAL.proxy.start_or_run end end diff --git a/lib/kamal/commands/proxy.rb b/lib/kamal/commands/proxy.rb index f5ea8cf4..354493db 100644 --- a/lib/kamal/commands/proxy.rb +++ b/lib/kamal/commands/proxy.rb @@ -46,6 +46,12 @@ class Kamal::Commands::Proxy < Kamal::Commands::Base docker :ps, "--filter", "name=^#{container_name}$" end + def version + pipe \ + docker(:inspect, container_name, "--format '{{.Config.Image}}'"), + [ :cut, "-d:", "-f2" ] + end + def logs(since: nil, lines: nil, grep: nil, grep_options: nil) pipe \ docker(:logs, container_name, (" --since #{since}" if since), (" --tail #{lines}" if lines), "--timestamps", "2>&1"), diff --git a/lib/kamal/configuration/proxy.rb b/lib/kamal/configuration/proxy.rb index 810f7517..a3161e1b 100644 --- a/lib/kamal/configuration/proxy.rb +++ b/lib/kamal/configuration/proxy.rb @@ -1,9 +1,10 @@ class Kamal::Configuration::Proxy include Kamal::Configuration::Validation + MINIMUM_VERSION = "v0.1.0" DEFAULT_HTTP_PORT = 80 DEFAULT_HTTPS_PORT = 443 - DEFAULT_IMAGE = "basecamp/kamal-proxy:latest" + DEFAULT_IMAGE = "basecamp/kamal-proxy:#{MINIMUM_VERSION}" DEFAULT_LOG_REQUEST_HEADERS = [ "Cache-Control", "Last-Modified", "User-Agent" ] delegate :argumentize, :optionize, to: Kamal::Utils @@ -62,7 +63,7 @@ class Kamal::Configuration::Proxy def config_volume Kamal::Configuration::Volume.new \ host_path: File.join(config.proxy_directory, "config"), - container_path: "/root/.config/kamal-proxy" + container_path: "/home/kamal-proxy/.config/kamal-proxy" end private diff --git a/lib/kamal/utils.rb b/lib/kamal/utils.rb index 266d6a96..ab8dd50e 100644 --- a/lib/kamal/utils.rb +++ b/lib/kamal/utils.rb @@ -101,4 +101,8 @@ module Kamal::Utils arch end end + + def older_version?(version, other_version) + Gem::Version.new(version.delete_prefix("v")) < Gem::Version.new(other_version.delete_prefix("v")) + end end diff --git a/test/cli/proxy_test.rb b/test/cli/proxy_test.rb index 8bc0f895..2a0834fc 100644 --- a/test/cli/proxy_test.rb +++ b/test/cli/proxy_test.rb @@ -4,10 +4,44 @@ class CliProxyTest < CliTestCase test "boot" do run_command("boot").tap do |output| assert_match "docker login", output - assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output end end + test "boot old version" do + Thread.report_on_exception = false + SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) + .with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2") + .returns("v0.0.1") + .at_least_once + + exception = assert_raises do + run_command("boot").tap do |output| + assert_match "docker login", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output + end + end + + assert_includes exception.message, "kamal-proxy version v0.0.1 is too old, please reboot to update to at least v0.1.0" + ensure + Thread.report_on_exception = false + end + + test "boot correct version" do + Thread.report_on_exception = false + SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) + .with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2") + .returns("v0.1.0") + .at_least_once + + run_command("boot").tap do |output| + assert_match "docker login", output + assert_match "docker container start kamal-proxy || docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output + end + ensure + Thread.report_on_exception = false + end + test "reboot" do SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) .with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet") @@ -23,13 +57,13 @@ class CliProxyTest < CliTestCase assert_match "docker container stop kamal-proxy on 1.1.1.1", output assert_match "Running docker container stop traefik ; docker container prune --force --filter label=org.opencontainers.image.title=Traefik && docker image prune --all --force --filter label=org.opencontainers.image.title=Traefik on 1.1.1.1", output assert_match "docker container prune --force --filter label=org.opencontainers.image.title=kamal-proxy on 1.1.1.1", output - assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.1", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.1", output assert_match "docker exec kamal-proxy kamal-proxy deploy app-web --target \"abcdefabcdef:80\" --deploy-timeout \"6s\" --buffer-requests --buffer-responses --log-request-header \"Cache-Control\" --log-request-header \"Last-Modified\" --log-request-header \"User-Agent\" on 1.1.1.1", output assert_match "docker container stop kamal-proxy on 1.1.1.2", output assert_match "Running docker container stop traefik ; docker container prune --force --filter label=org.opencontainers.image.title=Traefik && docker image prune --all --force --filter label=org.opencontainers.image.title=Traefik on 1.1.1.2", output assert_match "docker container prune --force --filter label=org.opencontainers.image.title=kamal-proxy on 1.1.1.2", output - assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.2", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.2", output assert_match "docker exec kamal-proxy kamal-proxy deploy app-web --target \"abcdefabcdef:80\" --deploy-timeout \"6s\" --buffer-requests --buffer-responses --log-request-header \"Cache-Control\" --log-request-header \"Last-Modified\" --log-request-header \"User-Agent\" on 1.1.1.2", output end end diff --git a/test/commands/proxy_test.rb b/test/commands/proxy_test.rb index 36e04c7b..349e1a1b 100644 --- a/test/commands/proxy_test.rb +++ b/test/commands/proxy_test.rb @@ -15,13 +15,13 @@ class CommandsProxyTest < ActiveSupport::TestCase test "run" do assert_equal \ - "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end test "run with ports configured" do assert_equal \ - "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end @@ -29,7 +29,7 @@ class CommandsProxyTest < ActiveSupport::TestCase @config.delete(:proxy) assert_equal \ - "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end @@ -37,7 +37,7 @@ class CommandsProxyTest < ActiveSupport::TestCase @config[:logging] = { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => "3" } } assert_equal \ - "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/root/.config/kamal-proxy --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end @@ -119,6 +119,12 @@ class CommandsProxyTest < ActiveSupport::TestCase new_command.remove("service", target: "172.1.0.2").join(" ") end + test "version" do + assert_equal \ + "docker inspect kamal-proxy --format '{{.Config.Image}}' | cut -d: -f2", + new_command.version.join(" ") + end + private def new_command Kamal::Commands::Proxy.new(Kamal::Configuration.new(@config, version: "123")) diff --git a/test/integration/main_test.rb b/test/integration/main_test.rb index cefe2100..5a4eb91c 100644 --- a/test/integration/main_test.rb +++ b/test/integration/main_test.rb @@ -28,7 +28,7 @@ class MainTest < IntegrationTest assert_match /Proxy Host: vm2/, details assert_match /App Host: vm1/, details assert_match /App Host: vm2/, details - assert_match /basecamp\/kamal-proxy:latest/, details + assert_match /basecamp\/kamal-proxy:v0.1.0/, details assert_match /registry:4443\/app:#{first_version}/, details audit = kamal :audit, capture: true diff --git a/test/integration/proxy_test.rb b/test/integration/proxy_test.rb index efab2583..f9c7133b 100644 --- a/test/integration/proxy_test.rb +++ b/test/integration/proxy_test.rb @@ -53,11 +53,11 @@ class ProxyTest < IntegrationTest private def assert_proxy_running - assert_match /basecamp\/kamal-proxy:latest \"kamal-proxy run\"/, proxy_details + assert_match /basecamp\/kamal-proxy:v0.1.0 \"kamal-proxy run\"/, proxy_details end def assert_proxy_not_running - assert_no_match /basecamp\/kamal-proxy:latest \"kamal-proxy run\"/, proxy_details + assert_no_match /basecamp\/kamal-proxy:v0.1.0 \"kamal-proxy run\"/, proxy_details end def proxy_details