kamal 2.8.2 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kamal/cli/accessory.rb +14 -7
  3. data/lib/kamal/cli/app/boot.rb +1 -1
  4. data/lib/kamal/cli/app.rb +74 -115
  5. data/lib/kamal/cli/healthcheck/poller.rb +1 -1
  6. data/lib/kamal/cli/main.rb +2 -1
  7. data/lib/kamal/cli/proxy.rb +42 -35
  8. data/lib/kamal/cli/secrets.rb +2 -1
  9. data/lib/kamal/cli/server.rb +2 -1
  10. data/lib/kamal/cli/templates/secrets +1 -0
  11. data/lib/kamal/commander.rb +3 -2
  12. data/lib/kamal/commands/app/execution.rb +7 -1
  13. data/lib/kamal/commands/app.rb +1 -1
  14. data/lib/kamal/commands/proxy.rb +21 -2
  15. data/lib/kamal/configuration/accessory.rb +63 -26
  16. data/lib/kamal/configuration/boot.rb +4 -0
  17. data/lib/kamal/configuration/builder.rb +10 -3
  18. data/lib/kamal/configuration/docs/accessory.yml +37 -5
  19. data/lib/kamal/configuration/docs/boot.yml +12 -10
  20. data/lib/kamal/configuration/docs/configuration.yml +10 -1
  21. data/lib/kamal/configuration/docs/proxy.yml +24 -0
  22. data/lib/kamal/configuration/docs/ssh.yml +7 -4
  23. data/lib/kamal/configuration/docs/sshkit.yml +8 -0
  24. data/lib/kamal/configuration/env.rb +7 -3
  25. data/lib/kamal/configuration/proxy/boot.rb +4 -9
  26. data/lib/kamal/configuration/proxy/run.rb +143 -0
  27. data/lib/kamal/configuration/proxy.rb +2 -2
  28. data/lib/kamal/configuration/role.rb +15 -3
  29. data/lib/kamal/configuration/ssh.rb +18 -3
  30. data/lib/kamal/configuration/sshkit.rb +4 -0
  31. data/lib/kamal/configuration/validator/proxy.rb +20 -0
  32. data/lib/kamal/configuration/validator.rb +34 -1
  33. data/lib/kamal/configuration/volume.rb +11 -4
  34. data/lib/kamal/configuration.rb +32 -1
  35. data/lib/kamal/secrets/adapters/passbolt.rb +1 -2
  36. data/lib/kamal/secrets/adapters/test.rb +3 -1
  37. data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +15 -1
  38. data/lib/kamal/secrets.rb +17 -6
  39. data/lib/kamal/sshkit_with_ext.rb +127 -10
  40. data/lib/kamal/utils.rb +3 -3
  41. data/lib/kamal/version.rb +1 -1
  42. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee017d64694e5a35507b9cfc9693e6a6c5fc876e0cfb731d58f0de7dba281f41
4
- data.tar.gz: bcbc84a444f0aa5efb08fd0ab63ea87d5892821f04e9c6ac51d938d78e2547a5
3
+ metadata.gz: 2e202f2e473f8a69d65631a19fa06631927aea76463158b02652f76ad05d927e
4
+ data.tar.gz: 485084a59d60985fb25a19ad3b8bfb53498e3af04b657366637aa73061dd6857
5
5
  SHA512:
6
- metadata.gz: b285597e99a5d2d90a324e9be64332a71afd66269ac27c8550eebf692758cac14535a14164058fd246d0001fd3b371382ed0b4e4bc9a75e19f8d42e40b4d9365
7
- data.tar.gz: fca4902b9da04bab86d087b0582ed956e2ee174259e47f1a491a4b68c928dc16a501cb0b137d443daeda25c00fd99bcf0f234ce54bf85da7b61002ce90402de0
6
+ metadata.gz: c8d1f1663c8a338950d40f64e1364d33f00ee7b2a6c4f244fde4d9fba5c3513274fcf344a4498e34adb72c4b139b33cc8d8a58ca15a05a551d59e26498092227
7
+ data.tar.gz: fd1b593b23a88bec6f7cfedd98222b5fda0cae9bb57132cd043bbacd3f4c8d1221f795b5a0eb5dd1ba6aa5918a041a7978322c35a9f42a22008c9b1378c51393
@@ -45,12 +45,14 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
45
45
  with_lock do
46
46
  with_accessory(name) do |accessory, hosts|
47
47
  on(hosts) do
48
- accessory.files.each do |(local, remote)|
48
+ accessory.files.each do |(local, config)|
49
+ remote = config[:host_path]
49
50
  accessory.ensure_local_file_present(local)
50
51
 
51
52
  execute *accessory.make_directory_for(remote)
52
53
  upload! local, remote
53
- execute :chmod, "755", remote
54
+ execute :chmod, config[:mode], remote
55
+ execute :chown, config[:owner], remote if config[:owner]
54
56
  end
55
57
  end
56
58
  end
@@ -62,8 +64,10 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
62
64
  with_lock do
63
65
  with_accessory(name) do |accessory, hosts|
64
66
  on(hosts) do
65
- accessory.directories.keys.each do |host_path|
66
- execute *accessory.make_directory(host_path)
67
+ accessory.directories.each do |(local, config)|
68
+ execute *accessory.make_directory(local)
69
+ execute :chmod, config[:mode], local if config[:mode]
70
+ execute :chown, config[:owner], local if config[:owner]
67
71
  end
68
72
  end
69
73
  end
@@ -128,12 +132,13 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
128
132
 
129
133
  desc "details [NAME]", "Show details about accessory on host (use NAME=all to show all accessories)"
130
134
  def details(name)
135
+ quiet = options[:quiet]
131
136
  if name == "all"
132
137
  KAMAL.accessory_names.each { |accessory_name| details(accessory_name) }
133
138
  else
134
139
  type = "Accessory #{name}"
135
140
  with_accessory(name) do |accessory, hosts|
136
- on(hosts) { puts_by_host host, capture_with_info(*accessory.info), type: type }
141
+ on(hosts) { puts_by_host host, capture_with_info(*accessory.info), type: type, quiet: quiet }
137
142
  end
138
143
  end
139
144
  end
@@ -145,6 +150,8 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
145
150
  pre_connect_if_required
146
151
 
147
152
  cmd = Kamal::Utils.join_commands(cmd)
153
+ quiet = options[:quiet]
154
+
148
155
  with_accessory(name) do |accessory, hosts|
149
156
  case
150
157
  when options[:interactive] && options[:reuse]
@@ -160,7 +167,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
160
167
  say "Launching command from existing container...", :magenta
161
168
  on(hosts) do |host|
162
169
  execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
163
- puts_by_host host, capture_with_info(*accessory.execute_in_existing_container(cmd))
170
+ puts_by_host host, capture_with_info(*accessory.execute_in_existing_container(cmd)), quiet: quiet
164
171
  end
165
172
 
166
173
  else
@@ -168,7 +175,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
168
175
  on(hosts) do |host|
169
176
  execute *KAMAL.registry.login
170
177
  execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
171
- puts_by_host host, capture_with_info(*accessory.execute_in_new_container(cmd))
178
+ puts_by_host host, capture_with_info(*accessory.execute_in_new_container(cmd)), quiet: quiet
172
179
  end
173
180
  end
174
181
  end
@@ -56,7 +56,7 @@ class Kamal::Cli::App::Boot
56
56
  raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
57
57
  execute *app.deploy(target: endpoint)
58
58
  else
59
- Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
59
+ Kamal::Cli::Healthcheck::Poller.wait_for_healthy { capture_with_info(*app.status(version: version)) }
60
60
  end
61
61
  rescue => e
62
62
  error "Failed to boot #{role} on #{host}"
data/lib/kamal/cli/app.rb CHANGED
@@ -23,10 +23,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
23
23
  host_list = Array(hosts).join(",")
24
24
  run_hook "pre-app-boot", hosts: host_list
25
25
 
26
- on(hosts) do |host|
27
- KAMAL.roles_on(host).each do |role|
28
- Kamal::Cli::App::Boot.new(host, role, self, version, barrier).run
29
- end
26
+ on_roles(KAMAL.roles, hosts: hosts, parallel: KAMAL.config.boot.parallel_roles) do |host, role|
27
+ Kamal::Cli::App::Boot.new(host, role, self, version, barrier).run
30
28
  end
31
29
 
32
30
  run_hook "post-app-boot", hosts: host_list
@@ -45,21 +43,17 @@ class Kamal::Cli::App < Kamal::Cli::Base
45
43
  desc "start", "Start existing app container on servers"
46
44
  def start
47
45
  with_lock do
48
- on(KAMAL.app_hosts) do |host|
49
- roles = KAMAL.roles_on(host)
50
-
51
- roles.each do |role|
52
- app = KAMAL.app(role: role, host: host)
53
- execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug
54
- execute *app.start, raise_on_non_zero_exit: false
46
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts, parallel: KAMAL.config.boot.parallel_roles) do |host, role|
47
+ app = KAMAL.app(role: role, host: host)
48
+ execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug
49
+ execute *app.start, raise_on_non_zero_exit: false
55
50
 
56
- if role.running_proxy?
57
- version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
58
- endpoint = capture_with_info(*app.container_id_for_version(version)).strip
59
- raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
51
+ if role.running_proxy?
52
+ version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
53
+ endpoint = capture_with_info(*app.container_id_for_version(version)).strip
54
+ raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
60
55
 
61
- execute *app.deploy(target: endpoint)
62
- end
56
+ execute *app.deploy(target: endpoint)
63
57
  end
64
58
  end
65
59
  end
@@ -68,23 +62,19 @@ class Kamal::Cli::App < Kamal::Cli::Base
68
62
  desc "stop", "Stop app container on servers"
69
63
  def stop
70
64
  with_lock do
71
- on(KAMAL.app_hosts) do |host|
72
- roles = KAMAL.roles_on(host)
73
-
74
- roles.each do |role|
75
- app = KAMAL.app(role: role, host: host)
76
- execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug
77
-
78
- if role.running_proxy?
79
- version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
80
- endpoint = capture_with_info(*app.container_id_for_version(version)).strip
81
- if endpoint.present?
82
- execute *app.remove, raise_on_non_zero_exit: false
83
- end
84
- end
65
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts, parallel: KAMAL.config.boot.parallel_roles) do |host, role|
66
+ app = KAMAL.app(role: role, host: host)
67
+ execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug
85
68
 
86
- execute *app.stop, raise_on_non_zero_exit: false
69
+ if role.running_proxy?
70
+ version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
71
+ endpoint = capture_with_info(*app.container_id_for_version(version)).strip
72
+ if endpoint.present?
73
+ execute *app.remove, raise_on_non_zero_exit: false
74
+ end
87
75
  end
76
+
77
+ execute *app.stop, raise_on_non_zero_exit: false
88
78
  end
89
79
  end
90
80
  end
@@ -92,12 +82,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
92
82
  # FIXME: Drop in favor of just containers?
93
83
  desc "details", "Show details about app containers"
94
84
  def details
95
- on(KAMAL.app_hosts) do |host|
96
- roles = KAMAL.roles_on(host)
97
-
98
- roles.each do |role|
99
- puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).info)
100
- end
85
+ quiet = options[:quiet]
86
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
87
+ puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).info), quiet: quiet
101
88
  end
102
89
  end
103
90
 
@@ -120,6 +107,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
120
107
  cmd = Kamal::Utils.join_commands(cmd)
121
108
  env = options[:env]
122
109
  detach = options[:detach]
110
+ quiet = options[:quiet]
123
111
  case
124
112
  when options[:interactive] && options[:reuse]
125
113
  say "Get current version of running container...", :magenta unless options[:version]
@@ -143,13 +131,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
143
131
  using_version(options[:version] || current_running_version) do |version|
144
132
  say "Launching command with version #{version} from existing container...", :magenta
145
133
 
146
- on(KAMAL.app_hosts) do |host|
147
- roles = KAMAL.roles_on(host)
148
-
149
- roles.each do |role|
150
- execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}", role: role), verbosity: :debug
151
- puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_existing_container(cmd, env: env))
152
- end
134
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
135
+ execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}", role: role), verbosity: :debug
136
+ puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_existing_container(cmd, env: env)), quiet: quiet
153
137
  end
154
138
  end
155
139
 
@@ -157,15 +141,11 @@ class Kamal::Cli::App < Kamal::Cli::Base
157
141
  say "Get most recent version available as an image...", :magenta unless options[:version]
158
142
  using_version(version_or_latest) do |version|
159
143
  say "Launching command with version #{version} from new container...", :magenta
160
- on(KAMAL.app_hosts) do |host|
161
- execute *KAMAL.registry.login
162
-
163
- roles = KAMAL.roles_on(host)
144
+ on(KAMAL.app_hosts) { execute *KAMAL.registry.login }
164
145
 
165
- roles.each do |role|
166
- execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug
167
- puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_new_container(cmd, env: env, detach: detach))
168
- end
146
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
147
+ execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug
148
+ puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_new_container(cmd, env: env, detach: detach)), quiet: quiet
169
149
  end
170
150
  end
171
151
  end
@@ -173,30 +153,28 @@ class Kamal::Cli::App < Kamal::Cli::Base
173
153
 
174
154
  desc "containers", "Show app containers on servers"
175
155
  def containers
176
- on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_containers) }
156
+ quiet = options[:quiet]
157
+ on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_containers), quiet: quiet }
177
158
  end
178
159
 
179
160
  desc "stale_containers", "Detect app stale containers"
180
161
  option :stop, aliases: "-s", type: :boolean, default: false, desc: "Stop the stale containers found"
181
162
  def stale_containers
163
+ quiet = options[:quiet]
182
164
  stop = options[:stop]
183
165
 
184
166
  with_lock_if_stopping do
185
- on(KAMAL.app_hosts) do |host|
186
- roles = KAMAL.roles_on(host)
187
-
188
- roles.each do |role|
189
- app = KAMAL.app(role: role, host: host)
190
- versions = capture_with_info(*app.list_versions, raise_on_non_zero_exit: false).split("\n")
191
- versions -= [ capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip ]
192
-
193
- versions.each do |version|
194
- if stop
195
- puts_by_host host, "Stopping stale container for role #{role} with version #{version}"
196
- execute *app.stop(version: version), raise_on_non_zero_exit: false
197
- else
198
- puts_by_host host, "Detected stale container for role #{role} with version #{version} (use `kamal app stale_containers --stop` to stop)"
199
- end
167
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
168
+ app = KAMAL.app(role: role, host: host)
169
+ versions = capture_with_info(*app.list_versions, raise_on_non_zero_exit: false).split("\n")
170
+ versions -= [ capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip ]
171
+
172
+ versions.each do |version|
173
+ if stop
174
+ puts_by_host host, "Stopping stale container for role #{role} with version #{version}", quiet: quiet
175
+ execute *app.stop(version: version), raise_on_non_zero_exit: false
176
+ else
177
+ puts_by_host host, "Detected stale container for role #{role} with version #{version} (use `kamal app stale_containers --stop` to stop)", quiet: quiet
200
178
  end
201
179
  end
202
180
  end
@@ -205,7 +183,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
205
183
 
206
184
  desc "images", "Show app images on servers"
207
185
  def images
208
- on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_images) }
186
+ quiet = options[:quiet]
187
+ on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_images), quiet: quiet }
209
188
  end
210
189
 
211
190
  desc "logs", "Show log lines from app on servers (use --help to show options)"
@@ -224,6 +203,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
224
203
  since = options[:since]
225
204
  container_id = options[:container_id]
226
205
  timestamps = !options[:skip_timestamps]
206
+ quiet = options[:quiet]
227
207
 
228
208
  if options[:follow]
229
209
  lines = options[:lines].presence || ((since || grep) ? nil : 10) # Default to 10 lines if since or grep isn't set
@@ -241,15 +221,11 @@ class Kamal::Cli::App < Kamal::Cli::Base
241
221
  else
242
222
  lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
243
223
 
244
- on(KAMAL.app_hosts) do |host|
245
- roles = KAMAL.roles_on(host)
246
-
247
- roles.each do |role|
248
- begin
249
- puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).logs(container_id: container_id, timestamps: timestamps, since: since, lines: lines, grep: grep, grep_options: grep_options))
250
- rescue SSHKit::Command::Failed
251
- puts_by_host host, "Nothing found"
252
- end
224
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
225
+ begin
226
+ puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).logs(container_id: container_id, timestamps: timestamps, since: since, lines: lines, grep: grep, grep_options: grep_options)), quiet: quiet
227
+ rescue SSHKit::Command::Failed
228
+ puts_by_host host, "Nothing found", quiet: quiet
253
229
  end
254
230
  end
255
231
  end
@@ -268,12 +244,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
268
244
  desc "live", "Set the app to live mode"
269
245
  def live
270
246
  with_lock do
271
- on(KAMAL.proxy_hosts) do |host|
272
- roles = KAMAL.roles_on(host)
273
-
274
- roles.each do |role|
275
- execute *KAMAL.app(role: role, host: host).live if role.running_proxy?
276
- end
247
+ on_roles(KAMAL.roles, hosts: KAMAL.proxy_hosts) do |host, role|
248
+ execute *KAMAL.app(role: role, host: host).live if role.running_proxy?
277
249
  end
278
250
  end
279
251
  end
@@ -285,12 +257,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
285
257
  maintenance_options = { drain_timeout: options[:drain_timeout] || KAMAL.config.drain_timeout, message: options[:message] }
286
258
 
287
259
  with_lock do
288
- on(KAMAL.proxy_hosts) do |host|
289
- roles = KAMAL.roles_on(host)
290
-
291
- roles.each do |role|
292
- execute *KAMAL.app(role: role, host: host).maintenance(**maintenance_options) if role.running_proxy?
293
- end
260
+ on_roles(KAMAL.roles, hosts: KAMAL.proxy_hosts) do |host, role|
261
+ execute *KAMAL.app(role: role, host: host).maintenance(**maintenance_options) if role.running_proxy?
294
262
  end
295
263
  end
296
264
  end
@@ -298,13 +266,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
298
266
  desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true
299
267
  def remove_container(version)
300
268
  with_lock do
301
- on(KAMAL.app_hosts) do |host|
302
- roles = KAMAL.roles_on(host)
303
-
304
- roles.each do |role|
305
- execute *KAMAL.auditor.record("Removed app container with version #{version}", role: role), verbosity: :debug
306
- execute *KAMAL.app(role: role, host: host).remove_container(version: version)
307
- end
269
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
270
+ execute *KAMAL.auditor.record("Removed app container with version #{version}", role: role), verbosity: :debug
271
+ execute *KAMAL.app(role: role, host: host).remove_container(version: version)
308
272
  end
309
273
  end
310
274
  end
@@ -312,13 +276,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
312
276
  desc "remove_containers", "Remove all app containers from servers", hide: true
313
277
  def remove_containers
314
278
  with_lock do
315
- on(KAMAL.app_hosts) do |host|
316
- roles = KAMAL.roles_on(host)
317
-
318
- roles.each do |role|
319
- execute *KAMAL.auditor.record("Removed all app containers", role: role), verbosity: :debug
320
- execute *KAMAL.app(role: role, host: host).remove_containers
321
- end
279
+ on_roles(KAMAL.roles, hosts: KAMAL.app_hosts) do |host, role|
280
+ execute *KAMAL.auditor.record("Removed all app containers", role: role), verbosity: :debug
281
+ execute *KAMAL.app(role: role, host: host).remove_containers
322
282
  end
323
283
  end
324
284
  end
@@ -326,7 +286,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
326
286
  desc "remove_images", "Remove all app images from servers", hide: true
327
287
  def remove_images
328
288
  with_lock do
329
- on(KAMAL.app_hosts) do
289
+ on(hosts_removing_all_roles) do
330
290
  execute *KAMAL.auditor.record("Removed all app images"), verbosity: :debug
331
291
  execute *KAMAL.app.remove_images
332
292
  end
@@ -336,14 +296,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
336
296
  desc "remove_app_directories", "Remove the app directories from servers", hide: true
337
297
  def remove_app_directories
338
298
  with_lock do
339
- on(KAMAL.app_hosts) do |host|
340
- roles = KAMAL.roles_on(host)
341
-
342
- roles.each do |role|
343
- execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory}", role: role), verbosity: :debug
344
- execute *KAMAL.server.remove_app_directory, raise_on_non_zero_exit: false
345
- end
346
-
299
+ on(hosts_removing_all_roles) do |host|
300
+ execute *KAMAL.server.remove_app_directory, raise_on_non_zero_exit: false
347
301
  execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory}"), verbosity: :debug
348
302
  execute *KAMAL.app.remove_proxy_app_directory, raise_on_non_zero_exit: false
349
303
  end
@@ -352,13 +306,18 @@ class Kamal::Cli::App < Kamal::Cli::Base
352
306
 
353
307
  desc "version", "Show app version currently running on servers"
354
308
  def version
309
+ quiet = options[:quiet]
355
310
  on(KAMAL.app_hosts) do |host|
356
311
  role = KAMAL.roles_on(host).first
357
- puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).current_running_version).strip
312
+ puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).current_running_version).strip, quiet: quiet
358
313
  end
359
314
  end
360
315
 
361
316
  private
317
+ def hosts_removing_all_roles
318
+ KAMAL.app_hosts.select { |host| KAMAL.roles_on(host).map(&:name).sort == KAMAL.config.host_roles(host.to_s).map(&:name).sort }
319
+ end
320
+
362
321
  def using_version(new_version)
363
322
  if new_version
364
323
  begin
@@ -1,7 +1,7 @@
1
1
  module Kamal::Cli::Healthcheck::Poller
2
2
  extend self
3
3
 
4
- def wait_for_healthy(role, &block)
4
+ def wait_for_healthy(&block)
5
5
  attempt = 1
6
6
  timeout_at = Time.now + KAMAL.config.deploy_timeout
7
7
  readiness_delay = KAMAL.config.readiness_delay
@@ -112,8 +112,9 @@ class Kamal::Cli::Main < Kamal::Cli::Base
112
112
 
113
113
  desc "audit", "Show audit log from servers"
114
114
  def audit
115
+ quiet = options[:quiet]
115
116
  on(KAMAL.hosts) do |host|
116
- puts_by_host host, capture_with_info(*KAMAL.auditor.reveal)
117
+ puts_by_host host, capture_with_info(*KAMAL.auditor.reveal), quiet: quiet
117
118
  end
118
119
  end
119
120
 
@@ -11,13 +11,13 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
11
11
  on(KAMAL.proxy_hosts) do |host|
12
12
  execute *KAMAL.registry.login
13
13
 
14
- version = capture_with_info(*KAMAL.proxy.version).strip.presence
14
+ version = capture_with_info(*KAMAL.proxy(host).version).strip.presence
15
15
 
16
- if version && Kamal::Utils.older_version?(version, Kamal::Configuration::Proxy::Boot::MINIMUM_VERSION)
17
- raise "kamal-proxy version #{version} is too old, run `kamal proxy reboot` in order to update to at least #{Kamal::Configuration::Proxy::Boot::MINIMUM_VERSION}"
16
+ if version && Kamal::Utils.older_version?(version, Kamal::Configuration::Proxy::Run::MINIMUM_VERSION)
17
+ raise "kamal-proxy version #{version} is too old, run `kamal proxy reboot` in order to update to at least #{Kamal::Configuration::Proxy::Run::MINIMUM_VERSION}"
18
18
  end
19
- execute *KAMAL.proxy.ensure_apps_config_directory
20
- execute *KAMAL.proxy.start_or_run
19
+ execute *KAMAL.proxy(host).ensure_apps_config_directory
20
+ execute *KAMAL.proxy(host).start_or_run
21
21
  end
22
22
  end
23
23
  end
@@ -25,9 +25,9 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
25
25
  desc "boot_config <set|get|reset>", "Manage kamal-proxy boot configuration"
26
26
  option :publish, type: :boolean, default: true, desc: "Publish the proxy ports on the host"
27
27
  option :publish_host_ip, type: :string, repeatable: true, default: nil, desc: "Host IP address to bind HTTP/HTTPS traffic to. Defaults to all interfaces"
28
- option :http_port, type: :numeric, default: Kamal::Configuration::Proxy::Boot::DEFAULT_HTTP_PORT, desc: "HTTP port to publish on the host"
29
- option :https_port, type: :numeric, default: Kamal::Configuration::Proxy::Boot::DEFAULT_HTTPS_PORT, desc: "HTTPS port to publish on the host"
30
- option :log_max_size, type: :string, default: Kamal::Configuration::Proxy::Boot::DEFAULT_LOG_MAX_SIZE, desc: "Max size of proxy logs"
28
+ option :http_port, type: :numeric, default: Kamal::Configuration::Proxy::Run::DEFAULT_HTTP_PORT, desc: "HTTP port to publish on the host"
29
+ option :https_port, type: :numeric, default: Kamal::Configuration::Proxy::Run::DEFAULT_HTTPS_PORT, desc: "HTTPS port to publish on the host"
30
+ option :log_max_size, type: :string, default: Kamal::Configuration::Proxy::Run::DEFAULT_LOG_MAX_SIZE, desc: "Max size of proxy logs"
31
31
  option :registry, type: :string, default: nil, desc: "Registry to use for the proxy image"
32
32
  option :repository, type: :string, default: nil, desc: "Repository for the proxy image"
33
33
  option :image_version, type: :string, default: nil, desc: "Version of the proxy to run"
@@ -35,6 +35,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
35
35
  option :debug, type: :boolean, default: false, desc: "Whether to run the proxy in debug mode"
36
36
  option :docker_options, type: :array, default: [], desc: "Docker options to pass to the proxy container", banner: "option=value option2=value2"
37
37
  def boot_config(subcommand)
38
+ say "The proxy boot_config command is deprecated - set the config in the deploy YAML at proxy/run instead", :yellow
38
39
  proxy_boot_config = KAMAL.config.proxy_boot
39
40
 
40
41
  case subcommand
@@ -58,42 +59,44 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
58
59
  run_command = "kamal-proxy run #{Kamal::Utils.optionize(run_command_options).join(" ")}" if run_command_options.any?
59
60
 
60
61
  on(KAMAL.proxy_hosts) do |host|
61
- execute(*KAMAL.proxy.ensure_proxy_directory)
62
+ proxy = KAMAL.proxy(host)
63
+ execute(*proxy.ensure_proxy_directory)
62
64
  if boot_options != proxy_boot_config.default_boot_options
63
65
  upload! StringIO.new(boot_options.join(" ")), proxy_boot_config.options_file
64
66
  else
65
- execute *KAMAL.proxy.reset_boot_options, raise_on_non_zero_exit: false
67
+ execute *proxy.reset_boot_options, raise_on_non_zero_exit: false
66
68
  end
67
69
 
68
70
  if image != proxy_boot_config.image_default
69
71
  upload! StringIO.new(image), proxy_boot_config.image_file
70
72
  else
71
- execute *KAMAL.proxy.reset_image, raise_on_non_zero_exit: false
73
+ execute *proxy.reset_image, raise_on_non_zero_exit: false
72
74
  end
73
75
 
74
76
  if image_version
75
77
  upload! StringIO.new(image_version), proxy_boot_config.image_version_file
76
78
  else
77
- execute *KAMAL.proxy.reset_image_version, raise_on_non_zero_exit: false
79
+ execute *proxy.reset_image_version, raise_on_non_zero_exit: false
78
80
  end
79
81
 
80
82
  if run_command
81
83
  upload! StringIO.new(run_command), proxy_boot_config.run_command_file
82
84
  else
83
- execute *KAMAL.proxy.reset_run_command, raise_on_non_zero_exit: false
85
+ execute *proxy.reset_run_command, raise_on_non_zero_exit: false
84
86
  end
85
87
  end
86
88
  when "get"
87
89
 
88
90
  on(KAMAL.proxy_hosts) do |host|
89
- puts "Host #{host}: #{capture_with_info(*KAMAL.proxy.boot_config)}"
91
+ puts "Host #{host}: #{capture_with_info(*KAMAL.proxy(host).boot_config)}"
90
92
  end
91
93
  when "reset"
92
94
  on(KAMAL.proxy_hosts) do |host|
93
- execute *KAMAL.proxy.reset_boot_options, raise_on_non_zero_exit: false
94
- execute *KAMAL.proxy.reset_image, raise_on_non_zero_exit: false
95
- execute *KAMAL.proxy.reset_image_version, raise_on_non_zero_exit: false
96
- execute *KAMAL.proxy.reset_run_command, raise_on_non_zero_exit: false
95
+ proxy = KAMAL.proxy(host)
96
+ execute *proxy.reset_boot_options, raise_on_non_zero_exit: false
97
+ execute *proxy.reset_image, raise_on_non_zero_exit: false
98
+ execute *proxy.reset_image_version, raise_on_non_zero_exit: false
99
+ execute *proxy.reset_run_command, raise_on_non_zero_exit: false
97
100
  end
98
101
  else
99
102
  raise ArgumentError, "Unknown boot_config subcommand #{subcommand}"
@@ -111,15 +114,16 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
111
114
  host_list = Array(hosts).join(",")
112
115
  run_hook "pre-proxy-reboot", hosts: host_list
113
116
  on(hosts) do |host|
117
+ proxy = KAMAL.proxy(host)
114
118
  execute *KAMAL.auditor.record("Rebooted proxy"), verbosity: :debug
115
119
  execute *KAMAL.registry.login
116
120
 
117
121
  "Stopping and removing kamal-proxy on #{host}, if running..."
118
- execute *KAMAL.proxy.stop, raise_on_non_zero_exit: false
119
- execute *KAMAL.proxy.remove_container
120
- execute *KAMAL.proxy.ensure_apps_config_directory
122
+ execute *proxy.stop, raise_on_non_zero_exit: false
123
+ execute *proxy.remove_container
124
+ execute *proxy.ensure_apps_config_directory
121
125
 
122
- execute *KAMAL.proxy.run
126
+ execute *proxy.run
123
127
  end
124
128
  run_hook "post-proxy-reboot", hosts: host_list
125
129
  end
@@ -140,16 +144,17 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
140
144
  say "Upgrading proxy on #{host_list}...", :magenta
141
145
  run_hook "pre-proxy-reboot", hosts: host_list
142
146
  on(hosts) do |host|
147
+ proxy = KAMAL.proxy(host)
143
148
  execute *KAMAL.auditor.record("Rebooted proxy"), verbosity: :debug
144
149
  execute *KAMAL.registry.login
145
150
 
146
151
  "Stopping and removing Traefik on #{host}, if running..."
147
- execute *KAMAL.proxy.cleanup_traefik
152
+ execute *proxy.cleanup_traefik
148
153
 
149
154
  "Stopping and removing kamal-proxy on #{host}, if running..."
150
- execute *KAMAL.proxy.stop, raise_on_non_zero_exit: false
151
- execute *KAMAL.proxy.remove_container
152
- execute *KAMAL.proxy.remove_image
155
+ execute *proxy.stop, raise_on_non_zero_exit: false
156
+ execute *proxy.remove_container
157
+ execute *proxy.remove_image
153
158
  end
154
159
 
155
160
  KAMAL.with_specific_hosts(hosts) do
@@ -172,7 +177,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
172
177
  with_lock do
173
178
  on(KAMAL.proxy_hosts) do |host|
174
179
  execute *KAMAL.auditor.record("Started proxy"), verbosity: :debug
175
- execute *KAMAL.proxy.start
180
+ execute *KAMAL.proxy(host).start
176
181
  end
177
182
  end
178
183
  end
@@ -182,7 +187,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
182
187
  with_lock do
183
188
  on(KAMAL.proxy_hosts) do |host|
184
189
  execute *KAMAL.auditor.record("Stopped proxy"), verbosity: :debug
185
- execute *KAMAL.proxy.stop, raise_on_non_zero_exit: false
190
+ execute *KAMAL.proxy(host).stop, raise_on_non_zero_exit: false
186
191
  end
187
192
  end
188
193
  end
@@ -197,7 +202,8 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
197
202
 
198
203
  desc "details", "Show details about proxy container from servers"
199
204
  def details
200
- on(KAMAL.proxy_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.proxy.info), type: "Proxy" }
205
+ quiet = options[:quiet]
206
+ on(KAMAL.proxy_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.proxy(host).info), type: "Proxy", quiet: quiet }
201
207
  end
202
208
 
203
209
  desc "logs", "Show log lines from proxy on servers"
@@ -212,16 +218,17 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
212
218
 
213
219
  if options[:follow]
214
220
  run_locally do
221
+ proxy = KAMAL.proxy(KAMAL.primary_host)
215
222
  info "Following logs on #{KAMAL.primary_host}..."
216
- info KAMAL.proxy.follow_logs(host: KAMAL.primary_host, timestamps: timestamps, grep: grep)
217
- exec KAMAL.proxy.follow_logs(host: KAMAL.primary_host, timestamps: timestamps, grep: grep)
223
+ info proxy.follow_logs(host: KAMAL.primary_host, timestamps: timestamps, grep: grep)
224
+ exec proxy.follow_logs(host: KAMAL.primary_host, timestamps: timestamps, grep: grep)
218
225
  end
219
226
  else
220
227
  since = options[:since]
221
228
  lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
222
229
 
223
230
  on(KAMAL.proxy_hosts) do |host|
224
- puts_by_host host, capture(*KAMAL.proxy.logs(timestamps: timestamps, since: since, lines: lines, grep: grep)), type: "Proxy"
231
+ puts_by_host host, capture(*KAMAL.proxy(host).logs(timestamps: timestamps, since: since, lines: lines, grep: grep)), type: "Proxy"
225
232
  end
226
233
  end
227
234
  end
@@ -244,7 +251,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
244
251
  with_lock do
245
252
  on(KAMAL.proxy_hosts) do
246
253
  execute *KAMAL.auditor.record("Removed proxy container"), verbosity: :debug
247
- execute *KAMAL.proxy.remove_container
254
+ execute *KAMAL.proxy(host).remove_container
248
255
  end
249
256
  end
250
257
  end
@@ -254,7 +261,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
254
261
  with_lock do
255
262
  on(KAMAL.proxy_hosts) do
256
263
  execute *KAMAL.auditor.record("Removed proxy image"), verbosity: :debug
257
- execute *KAMAL.proxy.remove_image
264
+ execute *KAMAL.proxy(host).remove_image
258
265
  end
259
266
  end
260
267
  end
@@ -263,7 +270,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
263
270
  def remove_proxy_directory
264
271
  with_lock do
265
272
  on(KAMAL.proxy_hosts) do
266
- execute *KAMAL.proxy.remove_proxy_directory, raise_on_non_zero_exit: false
273
+ execute *KAMAL.proxy(host).remove_proxy_directory, raise_on_non_zero_exit: false
267
274
  end
268
275
  end
269
276
  end