Skip to content

Commit 4083c86

Browse files
committed
Show container logs and healthcheck status on failure
1 parent 6117ce5 commit 4083c86

File tree

7 files changed

+31
-14
lines changed

7 files changed

+31
-14
lines changed

lib/kamal/cli/app.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def boot
1515
end
1616

1717
#  Primary hosts and roles are returned first, so they can open the barrier
18-
barrier = Kamal::Cli::Healthcheck::Barrier.new if KAMAL.roles.many?
18+
barrier = Kamal::Cli::Healthcheck::Barrier.new
1919

2020
on(KAMAL.hosts, **KAMAL.boot_strategy) do |host|
2121
KAMAL.roles_on(host).each do |role|

lib/kamal/cli/app/boot.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class Kamal::Cli::App::Boot
22
attr_reader :host, :role, :version, :barrier, :sshkit
3-
delegate :execute, :capture_with_info, :info, to: :sshkit
3+
delegate :execute, :capture_with_info, :capture_with_pretty_json, :info, :error, to: :sshkit
44
delegate :uses_cord?, :assets?, :running_traefik?, to: :role
55

66
def initialize(host, role, sshkit, version, barrier)
@@ -43,7 +43,11 @@ def start_new_version
4343

4444
reach_barrier
4545
rescue => e
46-
close_barrier if barrier_role?
46+
if barrier_role? && barrier.close
47+
info "Deploy failed, so closed barrier (#{host})"
48+
error capture_with_info(*app.logs(version: version))
49+
error capture_with_info(*app.container_health_log(version: version))
50+
end
4751
execute *app.stop(version: version), raise_on_non_zero_exit: false
4852

4953
raise
@@ -80,14 +84,10 @@ def wait_for_barrier
8084
barrier.wait
8185
info "Barrier opened (#{host})"
8286
rescue Kamal::Cli::Healthcheck::Error
83-
info "Barrier closed, shutting down new container... (#{host})"
87+
info "Barrier closed, shutting down new container (#{host})..."
8488
raise
8589
end
8690

87-
def close_barrier
88-
barrier&.close
89-
end
90-
9191
def barrier_role?
9292
role == KAMAL.primary_role
9393
end

lib/kamal/commands/app/containers.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
module Kamal::Commands::App::Containers
2+
DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
3+
24
def list_containers
35
docker :container, :ls, "--all", *filter_args
46
end
@@ -20,4 +22,10 @@ def rename_container(version:, new_version:)
2022
def remove_containers
2123
docker :container, :prune, "--force", *filter_args
2224
end
25+
26+
def container_health_log(version:)
27+
pipe \
28+
container_id_for(container_name: container_name(version)),
29+
xargs(docker(:inspect, "--format", DOCKER_HEALTH_LOG_FORMAT))
30+
end
2331
end

lib/kamal/commands/app/logging.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module Kamal::Commands::App::Logging
2-
def logs(since: nil, lines: nil, grep: nil)
2+
def logs(version: nil, since: nil, lines: nil, grep: nil)
33
pipe \
4-
current_running_container_id,
4+
version ? container_id_for_version(version) : current_running_container_id,
55
"xargs docker logs#{" --since #{since}" if since}#{" --tail #{lines}" if lines} 2>&1",
66
("grep '#{grep}'" if grep)
77
end

lib/kamal/commands/base.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ class Base
33
delegate :sensitive, :argumentize, to: Kamal::Utils
44

55
DOCKER_HEALTH_STATUS_FORMAT = "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'"
6-
DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
76

87
attr_accessor :config
98

test/cli/app_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ class CliAppTest < CliTestCase
136136
run_command("boot", config: :with_roles, host: nil, allow_execute_error: true).tap do |output|
137137
assert_match "Waiting at web barrier (1.1.1.3)...", output
138138
assert_match "Waiting at web barrier (1.1.1.4)...", output
139-
assert_match "Barrier closed, shutting down new container... (1.1.1.3)", output
140-
assert_match "Barrier closed, shutting down new container... (1.1.1.4)", output
139+
assert_match "Barrier closed, shutting down new container (1.1.1.3)...", output
140+
assert_match "Barrier closed, shutting down new container (1.1.1.4)...", output
141141
assert_match "Running docker container ls --all --filter name=^app-web-latest$ --quiet | xargs docker stop on 1.1.1.1", output
142142
assert_match "Running docker container ls --all --filter name=^app-web-latest$ --quiet | xargs docker stop on 1.1.1.2", output
143143
assert_match "Running docker container ls --all --filter name=^app-workers-latest$ --quiet | xargs docker stop on 1.1.1.3", output

test/integration/broken_deploy_test.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,20 @@ class BrokenDeployTest < IntegrationTest
1515

1616
second_version = break_app
1717

18-
kamal :deploy, raise_on_error: false
18+
output = kamal :deploy, raise_on_error: false, capture: true
1919

20+
assert_failed_deploy output
2021
assert_app_is_up version: first_version
2122
assert_container_running host: :vm3, name: "app-workers-#{first_version}"
2223
assert_container_not_running host: :vm3, name: "app-workers-#{second_version}"
2324
end
25+
26+
private
27+
def assert_failed_deploy(output)
28+
assert_match "Waiting at web barrier (vm3)...", output
29+
assert_match /Deploy failed, so closed barrier \(vm[12]\)/, output
30+
assert_match "Barrier closed, shutting down new container (vm3)...", output
31+
assert_match "nginx: [emerg] unexpected end of file, expecting \";\" or \"}\" in /etc/nginx/conf.d/default.conf:2", output
32+
assert_match 'ERROR {"Status":"unhealthy","FailingStreak":0,"Log":[]}', output
33+
end
2434
end

0 commit comments

Comments
 (0)