Maintenance mode
Adds support for maintenance mode to Kamal. There are two new commands: - `kamal app maintenance` - puts the app in maintenance mode - `kamal app live` - puts the app back in live mode In maintenance mode, the kamal proxy will respond to requests with a 503 status code. It will use an error page built into kamal proxy. You can use your own error page by setting `error_pages_path` in the configuration. This will copy any 4xx.html or 5xx.html files from that page to a volume mounted into the proxy container.
This commit is contained in:
@@ -192,6 +192,19 @@ class CliAppTest < CliTestCase
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "boot with error pages" do
|
||||
with_error_pages(directory: "public") do
|
||||
stub_running
|
||||
run_command("boot", config: :with_error_pages).tap do |output|
|
||||
assert_match /Uploading .*kamal-error-pages.*\/latest to \.kamal\/proxy\/apps-config\/app\/error_pages/, output
|
||||
assert_match "docker tag dhh/app:latest dhh/app:latest", output
|
||||
assert_match /docker run --detach --restart unless-stopped --name app-web-latest --network kamal --hostname 1.1.1.1-[0-9a-f]{12} /, output
|
||||
assert_match "docker container ls --all --filter name=^app-web-123$ --quiet | xargs docker stop", output
|
||||
assert_match "Running /usr/bin/env find .kamal/proxy/apps-config/app/error_pages -mindepth 1 -maxdepth 1 ! -name latest -exec rm -rf {} + on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "start" do
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info).returns("999") # old version
|
||||
|
||||
@@ -244,9 +257,11 @@ class CliAppTest < CliTestCase
|
||||
|
||||
test "remove" do
|
||||
run_command("remove").tap do |output|
|
||||
assert_match /#{Regexp.escape("sh -c 'docker ps --latest --quiet --filter label=service=app --filter label=destination= --filter label=role=web --filter status=running --filter status=restarting --filter ancestor=$(docker image ls --filter reference=dhh/app:latest --format '\\''{{.ID}}'\\'') ; docker ps --latest --quiet --filter label=service=app --filter label=destination= --filter label=role=web --filter status=running --filter status=restarting' | head -1 | xargs docker stop")}/, output
|
||||
assert_match /#{Regexp.escape("docker container prune --force --filter label=service=app")}/, output
|
||||
assert_match /#{Regexp.escape("docker image prune --all --force --filter label=service=app")}/, output
|
||||
assert_match "sh -c 'docker ps --latest --quiet --filter label=service=app --filter label=destination= --filter label=role=web --filter status=running --filter status=restarting --filter ancestor=$(docker image ls --filter reference=dhh/app:latest --format '\\''{{.ID}}'\\'') ; docker ps --latest --quiet --filter label=service=app --filter label=destination= --filter label=role=web --filter status=running --filter status=restarting' | head -1 | xargs docker stop", output
|
||||
assert_match "docker container prune --force --filter label=service=app", output
|
||||
assert_match "docker image prune --all --force --filter label=service=app", output
|
||||
assert_match "rm -r .kamal/apps/app on 1.1.1.1", output
|
||||
assert_match "rm -r .kamal/proxy/apps-config/app on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -268,6 +283,13 @@ class CliAppTest < CliTestCase
|
||||
end
|
||||
end
|
||||
|
||||
test "remove_app_directories" do
|
||||
run_command("remove_app_directories").tap do |output|
|
||||
assert_match "rm -r .kamal/apps/app on 1.1.1.1", output
|
||||
assert_match "rm -r .kamal/proxy/apps-config/app on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
|
||||
test "exec" do
|
||||
run_command("exec", "ruby -v").tap do |output|
|
||||
assert_match "docker run --rm --network kamal --env-file .kamal/apps/app/env/roles/web.env --log-opt max-size=\"10m\" dhh/app:latest ruby -v", output
|
||||
@@ -437,6 +459,24 @@ class CliAppTest < CliTestCase
|
||||
end
|
||||
end
|
||||
|
||||
test "live" do
|
||||
run_command("live").tap do |output|
|
||||
assert_match "docker exec kamal-proxy kamal-proxy resume app-web on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
|
||||
test "maintenance" do
|
||||
run_command("maintenance").tap do |output|
|
||||
assert_match "docker exec kamal-proxy kamal-proxy stop app-web --drain-timeout=\"30s\" on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
|
||||
test "maintenance with options" do
|
||||
run_command("maintenance", "--message", "Hello", "--drain_timeout", "10").tap do |output|
|
||||
assert_match "docker exec kamal-proxy kamal-proxy stop app-web --drain-timeout=\"10s\" --message=\"Hello\" on 1.1.1.1", output
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def run_command(*command, config: :with_accessories, host: "1.1.1.1", allow_execute_error: false)
|
||||
stdouted do
|
||||
|
||||
@@ -56,12 +56,12 @@ class CliProxyTest < CliTestCase
|
||||
run_command("reboot", "-y").tap do |output|
|
||||
assert_match "docker container stop kamal-proxy 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 "echo $(cat .kamal/proxy/options 2> /dev/null || echo \"--publish 80:80 --publish 443:443 --log-opt max-size=10m\") $(cat .kamal/proxy/image 2> /dev/null || echo \"basecamp/kamal-proxy\"):$(cat .kamal/proxy/image_version 2> /dev/null || echo \"#{Kamal::Configuration::PROXY_MINIMUM_VERSION}\") | xargs docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --volume kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy --volume $(pwd)/.kamal/proxy/app-config:/home/kamal-proxy/.app-config on 1.1.1.1", output
|
||||
assert_match "echo $(cat .kamal/proxy/options 2> /dev/null || echo \"--publish 80:80 --publish 443:443 --log-opt max-size=10m\") $(cat .kamal/proxy/image 2> /dev/null || echo \"basecamp/kamal-proxy\"):$(cat .kamal/proxy/image_version 2> /dev/null || echo \"#{Kamal::Configuration::PROXY_MINIMUM_VERSION}\") | xargs docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --volume kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy --volume $(pwd)/.kamal/proxy/apps-config:/home/kamal-proxy/.apps-config on 1.1.1.1", output
|
||||
assert_match "docker exec kamal-proxy kamal-proxy deploy app-web --target=\"abcdefabcdef:80\" --deploy-timeout=\"6s\" --drain-timeout=\"30s\" --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 "docker container prune --force --filter label=org.opencontainers.image.title=kamal-proxy on 1.1.1.2", output
|
||||
assert_match "echo $(cat .kamal/proxy/options 2> /dev/null || echo \"--publish 80:80 --publish 443:443 --log-opt max-size=10m\") $(cat .kamal/proxy/image 2> /dev/null || echo \"basecamp/kamal-proxy\"):$(cat .kamal/proxy/image_version 2> /dev/null || echo \"#{Kamal::Configuration::PROXY_MINIMUM_VERSION}\") | xargs docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --volume kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy --volume $(pwd)/.kamal/proxy/app-config:/home/kamal-proxy/.app-config on 1.1.1.2", output
|
||||
assert_match "echo $(cat .kamal/proxy/options 2> /dev/null || echo \"--publish 80:80 --publish 443:443 --log-opt max-size=10m\") $(cat .kamal/proxy/image 2> /dev/null || echo \"basecamp/kamal-proxy\"):$(cat .kamal/proxy/image_version 2> /dev/null || echo \"#{Kamal::Configuration::PROXY_MINIMUM_VERSION}\") | xargs docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --volume kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy --volume $(pwd)/.kamal/proxy/apps-config:/home/kamal-proxy/.apps-config on 1.1.1.2", output
|
||||
assert_match "docker exec kamal-proxy kamal-proxy deploy app-web --target=\"abcdefabcdef:80\" --deploy-timeout=\"6s\" --drain-timeout=\"30s\" --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
|
||||
|
||||
Reference in New Issue
Block a user