From 38c85e802161fcab047d6be9b5747964abd2c047 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 2 May 2023 17:23:10 +0200 Subject: [PATCH 1/4] Bump version for 0.12.0 --- Gemfile.lock | 2 +- lib/mrsk/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e1973f80..d668d6f4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - mrsk (0.11.0) + mrsk (0.12.0) activesupport (>= 7.0) bcrypt_pbkdf (~> 1.0) dotenv (~> 2.8) diff --git a/lib/mrsk/version.rb b/lib/mrsk/version.rb index 2713048d..87d04a68 100644 --- a/lib/mrsk/version.rb +++ b/lib/mrsk/version.rb @@ -1,3 +1,3 @@ module Mrsk - VERSION = "0.11.0" + VERSION = "0.12.0" end From 0e19ead37cacf0234eea5d512b0142be2a32326d Mon Sep 17 00:00:00 2001 From: Jberczel Date: Wed, 3 May 2023 14:15:46 -0400 Subject: [PATCH 2/4] Capture container health log when unhealthy --- lib/mrsk/cli/healthcheck.rb | 1 + lib/mrsk/commands/base.rb | 1 + lib/mrsk/commands/healthcheck.rb | 4 ++++ lib/mrsk/sshkit_with_ext.rb | 5 +++++ test/cli/healthcheck_test.rb | 5 +++++ test/commands/healthcheck_test.rb | 6 ++++++ 6 files changed, 22 insertions(+) diff --git a/lib/mrsk/cli/healthcheck.rb b/lib/mrsk/cli/healthcheck.rb index 81677d62..2db63ce7 100644 --- a/lib/mrsk/cli/healthcheck.rb +++ b/lib/mrsk/cli/healthcheck.rb @@ -9,6 +9,7 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base Mrsk::Utils::HealthcheckPoller.wait_for_healthy { capture_with_info(*MRSK.healthcheck.status) } rescue Mrsk::Utils::HealthcheckPoller::HealthcheckError => e error capture_with_info(*MRSK.healthcheck.logs) + error capture_with_pretty_json(*MRSK.healthcheck.container_health_log) raise ensure execute *MRSK.healthcheck.stop, raise_on_non_zero_exit: false diff --git a/lib/mrsk/commands/base.rb b/lib/mrsk/commands/base.rb index 49911a04..4ca57fa0 100644 --- a/lib/mrsk/commands/base.rb +++ b/lib/mrsk/commands/base.rb @@ -3,6 +3,7 @@ module Mrsk::Commands delegate :sensitive, :argumentize, to: Mrsk::Utils DOCKER_HEALTH_STATUS_FORMAT = "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'" + DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'" attr_accessor :config diff --git a/lib/mrsk/commands/healthcheck.rb b/lib/mrsk/commands/healthcheck.rb index 14932f3a..ad8070df 100644 --- a/lib/mrsk/commands/healthcheck.rb +++ b/lib/mrsk/commands/healthcheck.rb @@ -22,6 +22,10 @@ class Mrsk::Commands::Healthcheck < Mrsk::Commands::Base pipe container_id, xargs(docker(:inspect, "--format", DOCKER_HEALTH_STATUS_FORMAT)) end + def container_health_log + pipe container_id, xargs(docker(:inspect, "--format", DOCKER_HEALTH_LOG_FORMAT)) + end + def logs pipe container_id, xargs(docker(:logs, "--tail", 50, "2>&1")) end diff --git a/lib/mrsk/sshkit_with_ext.rb b/lib/mrsk/sshkit_with_ext.rb index 075c2643..a32e0b4b 100644 --- a/lib/mrsk/sshkit_with_ext.rb +++ b/lib/mrsk/sshkit_with_ext.rb @@ -1,5 +1,6 @@ require "sshkit" require "sshkit/dsl" +require "json" class SSHKit::Backend::Abstract def capture_with_info(*args, **kwargs) @@ -9,4 +10,8 @@ class SSHKit::Backend::Abstract def puts_by_host(host, output, type: "App") puts "#{type} Host: #{host}\n#{output}\n\n" end + + def capture_with_pretty_json(*args, **kwargs) + JSON.pretty_generate(JSON.parse(capture(*args, **kwargs))) + end end diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb index a3577aa4..67c3314f 100644 --- a/test/cli/healthcheck_test.rb +++ b/test/cli/healthcheck_test.rb @@ -53,6 +53,11 @@ class CliHealthcheckTest < CliTestCase .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1") .returns("some log output") + # Capture container health log when failing + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_pretty_json) + .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{json .State.Health}}'") + .returns('{"Status":"unhealthy","Log":[{"ExitCode": 1,"Output": "/bin/sh: 1: curl: not found\n"}]}"') + exception = assert_raises do run_command("perform") end diff --git a/test/commands/healthcheck_test.rb b/test/commands/healthcheck_test.rb index 68387487..4bf46ac0 100644 --- a/test/commands/healthcheck_test.rb +++ b/test/commands/healthcheck_test.rb @@ -51,6 +51,12 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase new_command.status.join(" ") end + test "container_health_log" do + assert_equal \ + "docker container ls --all --filter name=^healthcheck-app-123$ --quiet | xargs docker inspect --format '{{json .State.Health}}'", + new_command.container_health_log.join(" ") + end + test "stop" do assert_equal \ "docker container ls --all --filter name=^healthcheck-app-123$ --quiet | xargs docker stop", From 01483140f56a272d60fe7dae94ebe7ea2136b766 Mon Sep 17 00:00:00 2001 From: Jberczel Date: Wed, 3 May 2023 14:16:02 -0400 Subject: [PATCH 3/4] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ae2121c..375a9023 100644 --- a/README.md +++ b/README.md @@ -714,7 +714,7 @@ servers: The healthcheck allows for an optional `max_attempts` setting, which will attempt the healthcheck up to the specified number of times before failing the deploy. This is useful for applications that take a while to start up. The default is 7. -Note that the HTTP health checks assume that the `curl` command is avilable inside the container. If that's not the case, use the healthcheck's `cmd` option to specify an alternative check that the container supports. +Note: The HTTP health checks assume that the `curl` command is available inside the container. If that's not the case, use the healthcheck's `cmd` option to specify an alternative check that the container supports. ## Commands From 1bf4b6b76f4cfb214882168bc57cb6b26067a51e Mon Sep 17 00:00:00 2001 From: Dan Goodman Date: Thu, 4 May 2023 17:47:17 -0400 Subject: [PATCH 4/4] Fix staging label bug I think this is the correct fix based on the `service-role-destination` format, but seeing as it wasn't changed I assumed it was incorrect. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ae2121c..64f82e76 100644 --- a/README.md +++ b/README.md @@ -308,7 +308,7 @@ You can specialize the default Traefik rules by setting labels on the containers labels: traefik.http.routers.hey-web.rule: Host(`app.hey.com`) ``` -Traefik rules are in the "service-role-destination" format. The default role will be `web` if no rule is specified. If the destination is not specified, it is not included. To give an example, the above rule would become "traefik.http.routers.hey-web.rule" if it was for the "staging" destination. +Traefik rules are in the "service-role-destination" format. The default role will be `web` if no rule is specified. If the destination is not specified, it is not included. To give an example, the above rule would become "traefik.http.routers.hey-web-staging.rule" if it was for the "staging" destination. Note: The backticks are needed to ensure the rule is passed in correctly and not treated as command substitution by Bash!