kamal 2.0.0.alpha → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/kamal/cli/accessory.rb +44 -20
  4. data/lib/kamal/cli/app/boot.rb +22 -16
  5. data/lib/kamal/cli/app.rb +37 -3
  6. data/lib/kamal/cli/base.rb +9 -48
  7. data/lib/kamal/cli/build.rb +8 -3
  8. data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
  9. data/lib/kamal/cli/healthcheck/poller.rb +18 -39
  10. data/lib/kamal/cli/lock.rb +2 -3
  11. data/lib/kamal/cli/main.rb +54 -51
  12. data/lib/kamal/cli/proxy.rb +224 -0
  13. data/lib/kamal/cli/prune.rb +0 -1
  14. data/lib/kamal/cli/secrets.rb +36 -0
  15. data/lib/kamal/cli/server.rb +0 -2
  16. data/lib/kamal/cli/templates/deploy.yml +0 -11
  17. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  18. data/lib/kamal/cli/templates/secrets +16 -0
  19. data/lib/kamal/cli.rb +1 -0
  20. data/lib/kamal/commander/specifics.rb +3 -3
  21. data/lib/kamal/commander.rb +17 -9
  22. data/lib/kamal/commands/accessory.rb +7 -7
  23. data/lib/kamal/commands/app/assets.rb +8 -8
  24. data/lib/kamal/commands/app/proxy.rb +16 -0
  25. data/lib/kamal/commands/app.rb +7 -15
  26. data/lib/kamal/commands/auditor.rb +6 -3
  27. data/lib/kamal/commands/base.rb +8 -0
  28. data/lib/kamal/commands/builder/base.rb +2 -6
  29. data/lib/kamal/commands/builder/hybrid.rb +1 -1
  30. data/lib/kamal/commands/builder/remote.rb +27 -4
  31. data/lib/kamal/commands/builder.rb +1 -1
  32. data/lib/kamal/commands/docker.rb +4 -0
  33. data/lib/kamal/commands/hook.rb +5 -2
  34. data/lib/kamal/commands/lock.rb +2 -6
  35. data/lib/kamal/commands/proxy.rb +77 -0
  36. data/lib/kamal/commands/prune.rb +1 -9
  37. data/lib/kamal/commands/server.rb +11 -1
  38. data/lib/kamal/configuration/accessory.rb +14 -2
  39. data/lib/kamal/configuration/builder.rb +9 -3
  40. data/lib/kamal/configuration/docs/builder.yml +20 -10
  41. data/lib/kamal/configuration/docs/configuration.yml +16 -16
  42. data/lib/kamal/configuration/docs/env.yml +10 -11
  43. data/lib/kamal/configuration/docs/proxy.yml +100 -0
  44. data/lib/kamal/configuration/docs/registry.yml +4 -2
  45. data/lib/kamal/configuration/docs/role.yml +3 -5
  46. data/lib/kamal/configuration/env/tag.rb +4 -3
  47. data/lib/kamal/configuration/env.rb +10 -17
  48. data/lib/kamal/configuration/proxy.rb +66 -0
  49. data/lib/kamal/configuration/registry.rb +3 -2
  50. data/lib/kamal/configuration/role.rb +63 -94
  51. data/lib/kamal/configuration/validator/builder.rb +2 -0
  52. data/lib/kamal/configuration/validator/proxy.rb +11 -0
  53. data/lib/kamal/configuration/validator.rb +3 -1
  54. data/lib/kamal/configuration.rb +90 -33
  55. data/lib/kamal/env_file.rb +4 -0
  56. data/lib/kamal/secrets/adapters/base.rb +18 -0
  57. data/lib/kamal/secrets/adapters/bitwarden.rb +64 -0
  58. data/lib/kamal/secrets/adapters/last_pass.rb +30 -0
  59. data/lib/kamal/secrets/adapters/one_password.rb +61 -0
  60. data/lib/kamal/secrets/adapters/test.rb +10 -0
  61. data/lib/kamal/secrets/adapters.rb +14 -0
  62. data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +32 -0
  63. data/lib/kamal/secrets.rb +37 -0
  64. data/lib/kamal/sshkit_with_ext.rb +1 -0
  65. data/lib/kamal/utils.rb +12 -0
  66. data/lib/kamal/version.rb +1 -1
  67. data/lib/kamal.rb +3 -1
  68. metadata +23 -16
  69. data/lib/kamal/cli/env.rb +0 -54
  70. data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
  71. data/lib/kamal/cli/templates/template.env +0 -2
  72. data/lib/kamal/cli/traefik.rb +0 -122
  73. data/lib/kamal/commands/app/cord.rb +0 -22
  74. data/lib/kamal/commands/traefik.rb +0 -85
  75. data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
  76. data/lib/kamal/configuration/docs/traefik.yml +0 -62
  77. data/lib/kamal/configuration/healthcheck.rb +0 -63
  78. data/lib/kamal/configuration/traefik.rb +0 -60
  79. /data/lib/kamal/cli/templates/sample_hooks/{pre-traefik-reboot.sample → pre-proxy-reboot.sample} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4df682847a5becbc623450203537d42aa29fb4b001026a6b39ab266913660d4d
4
- data.tar.gz: 97ceb4c375f99605f1d874637273168f7274e95c615611d1d324cb0d635523e3
3
+ metadata.gz: c08e90e760f2392afcd73847fa1d9f7e987c684d687f49f227b808fda6cc28d5
4
+ data.tar.gz: c0945022760eeca770901d2c163c58a4a46a11f917e29f2d516d95d4af51ef3c
5
5
  SHA512:
6
- metadata.gz: 619e959821a7bd1590f0dcf6d3d3956e02c0832a51528b8f15d655ddcfe636a29a6c82fd0080a2d7d3104437368c63f607fd2f61623f230e547693a4accf65ea
7
- data.tar.gz: 1733b8db747dd71b1cb41ef7ca359856af278e5fb7ef29b0ed0cb677f67cdc82039246fb836bfd7c4260e992830f9a309315d5f98e83dcc3a2a7c5a2656e47a3
6
+ metadata.gz: 80ee86cd4b2ee5f5369cb6b1a7b81165a313cdedfd11352eb9215c5b6bf792be627927fad72c3bf25f69d12bcbf02a1fd088771ac495b45c0272145f16536f3f
7
+ data.tar.gz: df01ab908c65534003c0f089727c5ec6165be5ad72e72fab0f71c73c181ba0c8d7230a1887a2a3d7650c1f0ecfe2db349ebc2367ed64fbf052863d3bf37e4b57
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Kamal: Deploy web apps anywhere
2
2
 
3
- From bare metal to cloud VMs, deploy web apps anywhere with zero downtime. Kamal has the dynamic reverse-proxy Traefik hold requests while a new app container is started and the old one is stopped. Works seamlessly across multiple hosts, using SSHKit to execute commands. Originally built for Rails apps, Kamal will work with any type of web app that can be containerized with Docker.
3
+ From bare metal to cloud VMs, deploy web apps anywhere with zero downtime. Kamal uses [kamal-proxy](https://github.com/basecamp/kamal-proxy) to seamlessly switch requests between containers. Works seamlessly across multiple servers, using SSHKit to execute commands. Originally built for Rails apps, Kamal will work with any type of web app that can be containerized with Docker.
4
4
 
5
5
  ➡️ See [kamal-deploy.org](https://kamal-deploy.org) for documentation on [installation](https://kamal-deploy.org/docs/installation), [configuration](https://kamal-deploy.org/docs/configuration), and [commands](https://kamal-deploy.org/docs/commands).
6
6
 
@@ -1,17 +1,20 @@
1
1
  class Kamal::Cli::Accessory < Kamal::Cli::Base
2
2
  desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
3
- def boot(name, login: true)
3
+ def boot(name, prepare: true)
4
4
  with_lock do
5
5
  if name == "all"
6
6
  KAMAL.accessory_names.each { |accessory_name| boot(accessory_name) }
7
7
  else
8
+ prepare(name) if prepare
9
+
8
10
  with_accessory(name) do |accessory, hosts|
9
11
  directories(name)
10
12
  upload(name)
11
13
 
12
14
  on(hosts) do
13
- execute *KAMAL.registry.login if login
14
15
  execute *KAMAL.auditor.record("Booted #{name} accessory"), verbosity: :debug
16
+ execute *accessory.ensure_env_directory
17
+ upload! accessory.secrets_io, accessory.secrets_path, mode: "0600"
15
18
  execute *accessory.run
16
19
  end
17
20
  end
@@ -55,15 +58,10 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
55
58
  if name == "all"
56
59
  KAMAL.accessory_names.each { |accessory_name| reboot(accessory_name) }
57
60
  else
58
- with_accessory(name) do |accessory, hosts|
59
- on(hosts) do
60
- execute *KAMAL.registry.login
61
- end
62
-
63
- stop(name)
64
- remove_container(name)
65
- boot(name, login: false)
66
- end
61
+ prepare(name)
62
+ stop(name)
63
+ remove_container(name)
64
+ boot(name, prepare: false)
67
65
  end
68
66
  end
69
67
  end
@@ -95,10 +93,8 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
95
93
  desc "restart [NAME]", "Restart existing accessory container on host"
96
94
  def restart(name)
97
95
  with_lock do
98
- with_accessory(name) do
99
- stop(name)
100
- start(name)
101
- end
96
+ stop(name)
97
+ start(name)
102
98
  end
103
99
  end
104
100
 
@@ -222,6 +218,25 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
222
218
  end
223
219
  end
224
220
 
221
+ desc "upgrade", "Upgrade accessories from Kamal 1.x to 2.0 (restart them in 'kamal' network)"
222
+ option :rolling, type: :boolean, default: false, desc: "Upgrade one host at a time"
223
+ option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
224
+ def upgrade(name)
225
+ confirming "This will restart all accessories" do
226
+ with_lock do
227
+ host_groups = options[:rolling] ? KAMAL.accessory_hosts : [ KAMAL.accessory_hosts ]
228
+ host_groups.each do |hosts|
229
+ host_list = Array(hosts).join(",")
230
+ KAMAL.with_specific_hosts(hosts) do
231
+ say "Upgrading #{name} accessories on #{host_list}...", :magenta
232
+ reboot name
233
+ say "Upgraded #{name} accessories on #{host_list}...", :magenta
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+
225
240
  private
226
241
  def with_accessory(name)
227
242
  if KAMAL.config.accessory(name)
@@ -249,11 +264,20 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
249
264
  end
250
265
 
251
266
  def remove_accessory(name)
252
- with_accessory(name) do
253
- stop(name)
254
- remove_container(name)
255
- remove_image(name)
256
- remove_service_directory(name)
267
+ stop(name)
268
+ remove_container(name)
269
+ remove_image(name)
270
+ remove_service_directory(name)
271
+ end
272
+
273
+ def prepare(name)
274
+ with_accessory(name) do |accessory, hosts|
275
+ on(hosts) do
276
+ execute *KAMAL.registry.login
277
+ execute *KAMAL.docker.create_network
278
+ rescue SSHKit::Command::Failed => e
279
+ raise unless e.message.include?("already exists")
280
+ end
257
281
  end
258
282
  end
259
283
  end
@@ -1,7 +1,7 @@
1
1
  class Kamal::Cli::App::Boot
2
2
  attr_reader :host, :role, :version, :barrier, :sshkit
3
- delegate :execute, :capture_with_info, :capture_with_pretty_json, :info, :error, to: :sshkit
4
- delegate :uses_cord?, :assets?, :running_traefik?, to: :role
3
+ delegate :execute, :capture_with_info, :capture_with_pretty_json, :info, :error, :upload!, to: :sshkit
4
+ delegate :assets?, :running_proxy?, to: :role
5
5
 
6
6
  def initialize(host, role, sshkit, version, barrier)
7
7
  @host = host
@@ -45,11 +45,22 @@ class Kamal::Cli::App::Boot
45
45
 
46
46
  def start_new_version
47
47
  audit "Booted app version #{version}"
48
-
49
- execute *app.tie_cord(role.cord_host_file) if uses_cord?
50
48
  hostname = "#{host.to_s[0...51].gsub(/\.+$/, '')}-#{SecureRandom.hex(6)}"
49
+
50
+ execute *app.ensure_env_directory
51
+ upload! role.secrets_io(host), role.secrets_path, mode: "0600"
52
+
51
53
  execute *app.run(hostname: hostname)
52
- Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
54
+ if running_proxy?
55
+ endpoint = capture_with_info(*app.container_id_for_version(version)).strip
56
+ raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
57
+ execute *app.deploy(target: endpoint)
58
+ else
59
+ Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
60
+ end
61
+ rescue => e
62
+ error "Failed to boot #{role} on #{host}"
63
+ raise e
53
64
  end
54
65
 
55
66
  def stop_new_version
@@ -57,16 +68,7 @@ class Kamal::Cli::App::Boot
57
68
  end
58
69
 
59
70
  def stop_old_version(version)
60
- if uses_cord?
61
- cord = capture_with_info(*app.cord(version: version), raise_on_non_zero_exit: false).strip
62
- if cord.present?
63
- execute *app.cut_cord(cord)
64
- Kamal::Cli::Healthcheck::Poller.wait_for_unhealthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
65
- end
66
- end
67
-
68
71
  execute *app.stop(version: version), raise_on_non_zero_exit: false
69
-
70
72
  execute *app.clean_up_assets if assets?
71
73
  end
72
74
 
@@ -88,8 +90,12 @@ class Kamal::Cli::App::Boot
88
90
  def close_barrier
89
91
  if barrier.close
90
92
  info "First #{KAMAL.primary_role} container is unhealthy on #{host}, not booting any other roles"
91
- error capture_with_info(*app.logs(version: version))
92
- error capture_with_info(*app.container_health_log(version: version))
93
+ begin
94
+ error capture_with_info(*app.logs(version: version))
95
+ error capture_with_info(*app.container_health_log(version: version))
96
+ rescue SSHKit::Command::Failed
97
+ error "Could not fetch logs for #{version}"
98
+ end
93
99
  end
94
100
  end
95
101
 
data/lib/kamal/cli/app.rb CHANGED
@@ -4,7 +4,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
4
4
  with_lock do
5
5
  say "Get most recent version available as an image...", :magenta unless options[:version]
6
6
  using_version(version_or_latest) do |version|
7
- say "Start container with version #{version} using a #{KAMAL.config.readiness_delay}s readiness delay (or reboot if already running)...", :magenta
7
+ say "Start container with version #{version} (or reboot if already running)...", :magenta
8
8
 
9
9
  # Assets are prepared in a separate step to ensure they are on all hosts before booting
10
10
  on(KAMAL.hosts) do
@@ -38,8 +38,17 @@ class Kamal::Cli::App < Kamal::Cli::Base
38
38
  roles = KAMAL.roles_on(host)
39
39
 
40
40
  roles.each do |role|
41
+ app = KAMAL.app(role: role, host: host)
41
42
  execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug
42
- execute *KAMAL.app(role: role, host: host).start, raise_on_non_zero_exit: false
43
+ execute *app.start, raise_on_non_zero_exit: false
44
+
45
+ if role.running_proxy?
46
+ version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
47
+ endpoint = capture_with_info(*app.container_id_for_version(version)).strip
48
+ raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
49
+
50
+ execute *app.deploy(target: endpoint)
51
+ end
43
52
  end
44
53
  end
45
54
  end
@@ -52,8 +61,18 @@ class Kamal::Cli::App < Kamal::Cli::Base
52
61
  roles = KAMAL.roles_on(host)
53
62
 
54
63
  roles.each do |role|
64
+ app = KAMAL.app(role: role, host: host)
55
65
  execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug
56
- execute *KAMAL.app(role: role, host: host).stop, raise_on_non_zero_exit: false
66
+
67
+ if role.running_proxy?
68
+ version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
69
+ endpoint = capture_with_info(*app.container_id_for_version(version)).strip
70
+ if endpoint.present?
71
+ execute *app.remove(target: endpoint), raise_on_non_zero_exit: false
72
+ end
73
+ end
74
+
75
+ execute *app.stop, raise_on_non_zero_exit: false
57
76
  end
58
77
  end
59
78
  end
@@ -212,6 +231,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
212
231
  stop
213
232
  remove_containers
214
233
  remove_images
234
+ remove_app_directory
215
235
  end
216
236
  end
217
237
 
@@ -253,6 +273,20 @@ class Kamal::Cli::App < Kamal::Cli::Base
253
273
  end
254
274
  end
255
275
 
276
+ desc "remove_app_directory", "Remove the service directory from servers", hide: true
277
+ def remove_app_directory
278
+ with_lock do
279
+ on(KAMAL.hosts) do |host|
280
+ roles = KAMAL.roles_on(host)
281
+
282
+ roles.each do |role|
283
+ execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory} on all servers", role: role), verbosity: :debug
284
+ execute *KAMAL.server.remove_app_directory, raise_on_non_zero_exit: false
285
+ end
286
+ end
287
+ end
288
+ end
289
+
256
290
  desc "version", "Show app version currently running on servers"
257
291
  def version
258
292
  on(KAMAL.hosts) do |host|
@@ -1,5 +1,4 @@
1
1
  require "thor"
2
- require "dotenv"
3
2
  require "kamal/sshkit_with_ext"
4
3
 
5
4
  module Kamal::Cli
@@ -31,53 +30,15 @@ module Kamal::Cli
31
30
  else
32
31
  super
33
32
  end
34
- @original_env = ENV.to_h.dup
35
- load_env
36
- initialize_commander(options_with_subcommand_class_options)
33
+ initialize_commander unless KAMAL.configured?
37
34
  end
38
35
 
39
36
  private
40
- def reload_env
41
- reset_env
42
- load_env
43
- end
44
-
45
- def load_env
46
- if destination = options[:destination]
47
- Dotenv.load(".env.#{destination}", ".env")
48
- else
49
- Dotenv.load(".env")
50
- end
51
- end
52
-
53
- def reset_env
54
- replace_env @original_env
55
- end
56
-
57
- def replace_env(env)
58
- ENV.clear
59
- ENV.update(env)
60
- end
61
-
62
- def with_original_env
63
- keeping_current_env do
64
- reset_env
65
- yield
66
- end
67
- end
68
-
69
- def keeping_current_env
70
- current_env = ENV.to_h.dup
71
- yield
72
- ensure
73
- replace_env(current_env)
74
- end
75
-
76
37
  def options_with_subcommand_class_options
77
38
  options.merge(@_initializer.last[:class_options] || {})
78
39
  end
79
40
 
80
- def initialize_commander(options)
41
+ def initialize_commander
81
42
  KAMAL.tap do |commander|
82
43
  if options[:verbose]
83
44
  ENV["VERBOSE"] = "1" # For backtraces via cli/start
@@ -112,8 +73,6 @@ module Kamal::Cli
112
73
  if KAMAL.holding_lock?
113
74
  yield
114
75
  else
115
- ensure_run_and_locks_directory
116
-
117
76
  acquire_lock
118
77
 
119
78
  begin
@@ -142,6 +101,8 @@ module Kamal::Cli
142
101
  end
143
102
 
144
103
  def acquire_lock
104
+ ensure_run_directory
105
+
145
106
  raise_if_locked do
146
107
  say "Acquiring the deploy lock...", :magenta
147
108
  on(KAMAL.primary_host) { execute *KAMAL.lock.acquire("Automatic deploy lock", KAMAL.config.version), verbosity: :debug }
@@ -213,14 +174,14 @@ module Kamal::Cli
213
174
  instance_variable_get("@_invocations").first
214
175
  end
215
176
 
216
- def ensure_run_and_locks_directory
177
+ def reset_invocation(cli_class)
178
+ instance_variable_get("@_invocations")[cli_class].pop
179
+ end
180
+
181
+ def ensure_run_directory
217
182
  on(KAMAL.hosts) do
218
183
  execute(*KAMAL.server.ensure_run_directory)
219
184
  end
220
-
221
- on(KAMAL.primary_host) do
222
- execute(*KAMAL.lock.ensure_locks_directory)
223
- end
224
185
  end
225
186
  end
226
187
  end
@@ -32,10 +32,15 @@ class Kamal::Cli::Build < Kamal::Cli::Base
32
32
 
33
33
  run_locally do
34
34
  begin
35
- execute *KAMAL.builder.buildx_inspect
35
+ execute *KAMAL.builder.inspect_builder
36
36
  rescue SSHKit::Command::Failed => e
37
- if e.message =~ /(context not found|no builder|does not exist)/
37
+ if e.message =~ /(context not found|no builder|no compatible builder|does not exist)/
38
38
  warn "Missing compatible builder, so creating a new one first"
39
+ begin
40
+ cli.remove
41
+ rescue SSHKit::Command::Failed
42
+ raise unless e.message =~ /(context not found|no builder|does not exist)/
43
+ end
39
44
  cli.create
40
45
  else
41
46
  raise
@@ -46,7 +51,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
46
51
  push = KAMAL.builder.push
47
52
 
48
53
  KAMAL.with_verbosity(:debug) do
49
- Dir.chdir(KAMAL.config.builder.build_directory) { execute *push }
54
+ Dir.chdir(KAMAL.config.builder.build_directory) { execute *push, env: KAMAL.config.builder.secrets }
50
55
  end
51
56
  end
52
57
  end
@@ -1,3 +1,5 @@
1
+ require "concurrent/ivar"
2
+
1
3
  class Kamal::Cli::Healthcheck::Barrier
2
4
  def initialize
3
5
  @ivar = Concurrent::IVar.new
@@ -1,51 +1,30 @@
1
1
  module Kamal::Cli::Healthcheck::Poller
2
2
  extend self
3
3
 
4
- TRAEFIK_UPDATE_DELAY = 5
5
-
6
-
7
- def wait_for_healthy(pause_after_ready: false, &block)
4
+ def wait_for_healthy(role, &block)
8
5
  attempt = 1
9
- max_attempts = KAMAL.config.healthcheck.max_attempts
6
+ timeout_at = Time.now + KAMAL.config.deploy_timeout
7
+ readiness_delay = KAMAL.config.readiness_delay
10
8
 
11
9
  begin
12
- case status = block.call
13
- when "healthy"
14
- sleep TRAEFIK_UPDATE_DELAY if pause_after_ready
15
- when "running" # No health check configured
16
- sleep KAMAL.config.readiness_delay if pause_after_ready
17
- else
18
- raise Kamal::Cli::Healthcheck::Error, "container not ready (#{status})"
19
- end
20
- rescue Kamal::Cli::Healthcheck::Error => e
21
- if attempt <= max_attempts
22
- info "#{e.message}, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..."
23
- sleep attempt
24
- attempt += 1
25
- retry
26
- else
27
- raise
10
+ status = block.call
11
+
12
+ if status == "running"
13
+ # Wait for the readiness delay and confirm it is still running
14
+ if readiness_delay > 0
15
+ info "Container is running, waiting for readiness delay of #{readiness_delay} seconds"
16
+ sleep readiness_delay
17
+ status = block.call
18
+ end
28
19
  end
29
- end
30
20
 
31
- info "Container is healthy!"
32
- end
33
-
34
- def wait_for_unhealthy(pause_after_ready: false, &block)
35
- attempt = 1
36
- max_attempts = KAMAL.config.healthcheck.max_attempts
37
-
38
- begin
39
- case status = block.call
40
- when "unhealthy"
41
- sleep TRAEFIK_UPDATE_DELAY if pause_after_ready
42
- else
43
- raise Kamal::Cli::Healthcheck::Error, "container not unhealthy (#{status})"
21
+ unless %w[ running healthy ].include?(status)
22
+ raise Kamal::Cli::Healthcheck::Error, "container not ready after #{KAMAL.config.deploy_timeout} seconds (#{status})"
44
23
  end
45
24
  rescue Kamal::Cli::Healthcheck::Error => e
46
- if attempt <= max_attempts
47
- info "#{e.message}, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..."
48
- sleep attempt
25
+ time_left = timeout_at - Time.now
26
+ if time_left > 0
27
+ sleep [ attempt, time_left ].min
49
28
  attempt += 1
50
29
  retry
51
30
  else
@@ -53,7 +32,7 @@ module Kamal::Cli::Healthcheck::Poller
53
32
  end
54
33
  end
55
34
 
56
- info "Container is unhealthy!"
35
+ info "Container is healthy!"
57
36
  end
58
37
 
59
38
  private
@@ -3,7 +3,6 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
3
3
  def status
4
4
  handle_missing_lock do
5
5
  on(KAMAL.primary_host) do
6
- execute *KAMAL.server.ensure_run_directory
7
6
  puts capture_with_debug(*KAMAL.lock.status)
8
7
  end
9
8
  end
@@ -13,9 +12,10 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
13
12
  option :message, aliases: "-m", type: :string, desc: "A lock message", required: true
14
13
  def acquire
15
14
  message = options[:message]
15
+ ensure_run_directory
16
+
16
17
  raise_if_locked do
17
18
  on(KAMAL.primary_host) do
18
- execute *KAMAL.server.ensure_run_directory
19
19
  execute *KAMAL.lock.acquire(message, KAMAL.config.version), verbosity: :debug
20
20
  end
21
21
  say "Acquired the deploy lock"
@@ -26,7 +26,6 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
26
26
  def release
27
27
  handle_missing_lock do
28
28
  on(KAMAL.primary_host) do
29
- execute *KAMAL.server.ensure_run_directory
30
29
  execute *KAMAL.lock.release, verbosity: :debug
31
30
  end
32
31
  say "Released the deploy lock"