kamal 2.5.3 → 2.6.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.
- checksums.yaml +4 -4
- data/lib/kamal/cli/accessory.rb +16 -5
- data/lib/kamal/cli/app/{prepare_assets.rb → assets.rb} +1 -1
- data/lib/kamal/cli/app/boot.rb +1 -0
- data/lib/kamal/cli/app/error_pages.rb +33 -0
- data/lib/kamal/cli/app.rb +66 -22
- data/lib/kamal/cli/base.rb +13 -3
- data/lib/kamal/cli/build.rb +20 -4
- data/lib/kamal/cli/main.rb +4 -7
- data/lib/kamal/cli/proxy.rb +57 -10
- data/lib/kamal/cli/server.rb +4 -2
- data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/pre-build.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/pre-connect.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample +6 -5
- data/lib/kamal/commander/specifics.rb +4 -0
- data/lib/kamal/commander.rb +2 -2
- data/lib/kamal/commands/accessory/proxy.rb +1 -1
- data/lib/kamal/commands/accessory.rb +2 -3
- data/lib/kamal/commands/app/error_pages.rb +9 -0
- data/lib/kamal/commands/app/proxy.rb +13 -1
- data/lib/kamal/commands/app.rb +1 -1
- data/lib/kamal/commands/auditor.rb +11 -5
- data/lib/kamal/commands/base.rb +4 -0
- data/lib/kamal/commands/builder/base.rb +2 -1
- data/lib/kamal/commands/proxy.rb +55 -15
- data/lib/kamal/configuration/accessory.rb +24 -2
- data/lib/kamal/configuration/docs/accessory.yml +6 -1
- data/lib/kamal/configuration/docs/configuration.yml +6 -0
- data/lib/kamal/configuration/docs/env.yml +31 -0
- data/lib/kamal/configuration/docs/proxy.yml +7 -0
- data/lib/kamal/configuration/env.rb +13 -4
- data/lib/kamal/configuration/proxy/boot.rb +121 -0
- data/lib/kamal/configuration/proxy.rb +18 -1
- data/lib/kamal/configuration/servers.rb +8 -1
- data/lib/kamal/configuration/validator/accessory.rb +4 -2
- data/lib/kamal/configuration/validator/role.rb +1 -0
- data/lib/kamal/configuration/validator/servers.rb +1 -1
- data/lib/kamal/configuration/validator.rb +6 -0
- data/lib/kamal/configuration.rb +36 -74
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +1 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +2 -1
- data/lib/kamal/version.rb +1 -1
- metadata +9 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3b89316447c79f85f3be2a7b1592d32e19350571b81f7438aab1ffd7602da86
|
4
|
+
data.tar.gz: '065904d4073e24495c27b0f32d468b384a93ac3bfb0c9303cf9ceb060d7d68cc'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58e4102f80bb090dbe76f325429b8e74fcf689f92fcf18ffe6ca46b6f67f2acd0ba93adee9411c4790e71f29b5989d7e3a3f7ec26a08bdab7d679e339dbd3cae
|
7
|
+
data.tar.gz: 10038a978ad0755cdd25c732bd5886b9c6d59f80292041eaa8449cbaceaa2f8e9f61d1c3775c8eeb9a8a8d772046497f0b84016e0c8f7ab61b7907616182c617
|
data/lib/kamal/cli/accessory.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "active_support/core_ext/array/conversions"
|
2
|
+
require "concurrent/array"
|
2
3
|
|
3
4
|
class Kamal::Cli::Accessory < Kamal::Cli::Base
|
4
5
|
desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
|
@@ -10,6 +11,16 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
10
11
|
prepare(name) if prepare
|
11
12
|
|
12
13
|
with_accessory(name) do |accessory, hosts|
|
14
|
+
booted_hosts = Concurrent::Array.new
|
15
|
+
on(hosts) do |host|
|
16
|
+
booted_hosts << host.to_s if capture_with_info(*accessory.info(all: true, quiet: true)).strip.presence
|
17
|
+
end
|
18
|
+
|
19
|
+
if booted_hosts.any?
|
20
|
+
say "Skipping booting `#{name}` on #{booted_hosts.sort.join(", ")}, a container already exists", :yellow
|
21
|
+
hosts -= booted_hosts
|
22
|
+
end
|
23
|
+
|
13
24
|
directories(name)
|
14
25
|
upload(name)
|
15
26
|
|
@@ -130,6 +141,8 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
130
141
|
option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
|
131
142
|
option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
|
132
143
|
def exec(name, *cmd)
|
144
|
+
pre_connect_if_required
|
145
|
+
|
133
146
|
cmd = Kamal::Utils.join_commands(cmd)
|
134
147
|
with_accessory(name) do |accessory, hosts|
|
135
148
|
case
|
@@ -139,6 +152,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
139
152
|
|
140
153
|
when options[:interactive]
|
141
154
|
say "Launching interactive command via SSH from new container...", :magenta
|
155
|
+
on(accessory.hosts.first) { execute *KAMAL.registry.login }
|
142
156
|
run_locally { exec accessory.execute_in_new_container_over_ssh(cmd) }
|
143
157
|
|
144
158
|
when options[:reuse]
|
@@ -151,6 +165,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
151
165
|
else
|
152
166
|
say "Launching command from new container...", :magenta
|
153
167
|
on(hosts) do |host|
|
168
|
+
execute *KAMAL.registry.login
|
154
169
|
execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
|
155
170
|
puts_by_host host, capture_with_info(*accessory.execute_in_new_container(cmd))
|
156
171
|
end
|
@@ -275,11 +290,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
275
290
|
end
|
276
291
|
|
277
292
|
def accessory_hosts(accessory)
|
278
|
-
|
279
|
-
KAMAL.specific_hosts & accessory.hosts
|
280
|
-
else
|
281
|
-
accessory.hosts
|
282
|
-
end
|
293
|
+
KAMAL.accessory_hosts & accessory.hosts
|
283
294
|
end
|
284
295
|
|
285
296
|
def remove_accessory(name)
|
data/lib/kamal/cli/app/boot.rb
CHANGED
@@ -70,6 +70,7 @@ class Kamal::Cli::App::Boot
|
|
70
70
|
def stop_old_version(version)
|
71
71
|
execute *app.stop(version: version), raise_on_non_zero_exit: false
|
72
72
|
execute *app.clean_up_assets if assets?
|
73
|
+
execute *app.clean_up_error_pages if KAMAL.config.error_pages_path
|
73
74
|
end
|
74
75
|
|
75
76
|
def release_barrier
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Kamal::Cli::App::ErrorPages
|
2
|
+
ERROR_PAGES_GLOB = "{4??.html,5??.html}"
|
3
|
+
|
4
|
+
attr_reader :host, :sshkit
|
5
|
+
delegate :upload!, :execute, to: :sshkit
|
6
|
+
|
7
|
+
def initialize(host, sshkit)
|
8
|
+
@host = host
|
9
|
+
@sshkit = sshkit
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
if KAMAL.config.error_pages_path
|
14
|
+
with_error_pages_tmpdir do |local_error_pages_dir|
|
15
|
+
execute *KAMAL.app.create_error_pages_directory
|
16
|
+
upload! local_error_pages_dir, KAMAL.config.proxy_boot.error_pages_directory, mode: "0700", recursive: true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def with_error_pages_tmpdir
|
23
|
+
Dir.mktmpdir("kamal-error-pages") do |tmpdir|
|
24
|
+
error_pages_dir = File.join(tmpdir, KAMAL.config.version)
|
25
|
+
FileUtils.mkdir(error_pages_dir)
|
26
|
+
|
27
|
+
if (files = Dir[File.join(KAMAL.config.error_pages_path, ERROR_PAGES_GLOB)]).any?
|
28
|
+
FileUtils.cp(files, error_pages_dir)
|
29
|
+
yield error_pages_dir
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/kamal/cli/app.rb
CHANGED
@@ -7,9 +7,11 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
7
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
|
-
on(KAMAL.
|
10
|
+
on(KAMAL.app_hosts) do
|
11
|
+
Kamal::Cli::App::ErrorPages.new(host, self).run
|
12
|
+
|
11
13
|
KAMAL.roles_on(host).each do |role|
|
12
|
-
Kamal::Cli::App::
|
14
|
+
Kamal::Cli::App::Assets.new(host, role, self).run
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
@@ -31,7 +33,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
31
33
|
end
|
32
34
|
|
33
35
|
# Tag once the app booted on all hosts
|
34
|
-
on(KAMAL.
|
36
|
+
on(KAMAL.app_hosts) do |host|
|
35
37
|
execute *KAMAL.auditor.record("Tagging #{KAMAL.config.absolute_image} as the latest image"), verbosity: :debug
|
36
38
|
execute *KAMAL.app.tag_latest_image
|
37
39
|
end
|
@@ -42,7 +44,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
42
44
|
desc "start", "Start existing app container on servers"
|
43
45
|
def start
|
44
46
|
with_lock do
|
45
|
-
on(KAMAL.
|
47
|
+
on(KAMAL.app_hosts) do |host|
|
46
48
|
roles = KAMAL.roles_on(host)
|
47
49
|
|
48
50
|
roles.each do |role|
|
@@ -65,7 +67,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
65
67
|
desc "stop", "Stop app container on servers"
|
66
68
|
def stop
|
67
69
|
with_lock do
|
68
|
-
on(KAMAL.
|
70
|
+
on(KAMAL.app_hosts) do |host|
|
69
71
|
roles = KAMAL.roles_on(host)
|
70
72
|
|
71
73
|
roles.each do |role|
|
@@ -89,7 +91,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
89
91
|
# FIXME: Drop in favor of just containers?
|
90
92
|
desc "details", "Show details about app containers"
|
91
93
|
def details
|
92
|
-
on(KAMAL.
|
94
|
+
on(KAMAL.app_hosts) do |host|
|
93
95
|
roles = KAMAL.roles_on(host)
|
94
96
|
|
95
97
|
roles.each do |role|
|
@@ -104,10 +106,16 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
104
106
|
option :env, aliases: "-e", type: :hash, desc: "Set environment variables for the command"
|
105
107
|
option :detach, type: :boolean, default: false, desc: "Execute command in a detached container"
|
106
108
|
def exec(*cmd)
|
109
|
+
pre_connect_if_required
|
110
|
+
|
107
111
|
if (incompatible_options = [ :interactive, :reuse ].select { |key| options[:detach] && options[key] }.presence)
|
108
112
|
raise ArgumentError, "Detach is not compatible with #{incompatible_options.join(" or ")}"
|
109
113
|
end
|
110
114
|
|
115
|
+
if cmd.empty?
|
116
|
+
raise ArgumentError, "No command provided. You must specify a command to execute."
|
117
|
+
end
|
118
|
+
|
111
119
|
cmd = Kamal::Utils.join_commands(cmd)
|
112
120
|
env = options[:env]
|
113
121
|
detach = options[:detach]
|
@@ -123,6 +131,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
123
131
|
say "Get most recent version available as an image...", :magenta unless options[:version]
|
124
132
|
using_version(version_or_latest) do |version|
|
125
133
|
say "Launching interactive command with version #{version} via SSH from new container on #{KAMAL.primary_host}...", :magenta
|
134
|
+
on(KAMAL.primary_host) { execute *KAMAL.registry.login }
|
126
135
|
run_locally do
|
127
136
|
exec KAMAL.app(role: KAMAL.primary_role, host: KAMAL.primary_host).execute_in_new_container_over_ssh(cmd, env: env)
|
128
137
|
end
|
@@ -133,7 +142,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
133
142
|
using_version(options[:version] || current_running_version) do |version|
|
134
143
|
say "Launching command with version #{version} from existing container...", :magenta
|
135
144
|
|
136
|
-
on(KAMAL.
|
145
|
+
on(KAMAL.app_hosts) do |host|
|
137
146
|
roles = KAMAL.roles_on(host)
|
138
147
|
|
139
148
|
roles.each do |role|
|
@@ -147,7 +156,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
147
156
|
say "Get most recent version available as an image...", :magenta unless options[:version]
|
148
157
|
using_version(version_or_latest) do |version|
|
149
158
|
say "Launching command with version #{version} from new container...", :magenta
|
150
|
-
on(KAMAL.
|
159
|
+
on(KAMAL.app_hosts) do |host|
|
160
|
+
execute *KAMAL.registry.login
|
161
|
+
|
151
162
|
roles = KAMAL.roles_on(host)
|
152
163
|
|
153
164
|
roles.each do |role|
|
@@ -161,7 +172,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
161
172
|
|
162
173
|
desc "containers", "Show app containers on servers"
|
163
174
|
def containers
|
164
|
-
on(KAMAL.
|
175
|
+
on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_containers) }
|
165
176
|
end
|
166
177
|
|
167
178
|
desc "stale_containers", "Detect app stale containers"
|
@@ -170,7 +181,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
170
181
|
stop = options[:stop]
|
171
182
|
|
172
183
|
with_lock_if_stopping do
|
173
|
-
on(KAMAL.
|
184
|
+
on(KAMAL.app_hosts) do |host|
|
174
185
|
roles = KAMAL.roles_on(host)
|
175
186
|
|
176
187
|
roles.each do |role|
|
@@ -193,7 +204,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
193
204
|
|
194
205
|
desc "images", "Show app images on servers"
|
195
206
|
def images
|
196
|
-
on(KAMAL.
|
207
|
+
on(KAMAL.app_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_images) }
|
197
208
|
end
|
198
209
|
|
199
210
|
desc "logs", "Show log lines from app on servers (use --help to show options)"
|
@@ -229,7 +240,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
229
240
|
else
|
230
241
|
lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
|
231
242
|
|
232
|
-
on(KAMAL.
|
243
|
+
on(KAMAL.app_hosts) do |host|
|
233
244
|
roles = KAMAL.roles_on(host)
|
234
245
|
|
235
246
|
roles.each do |role|
|
@@ -249,14 +260,44 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
249
260
|
stop
|
250
261
|
remove_containers
|
251
262
|
remove_images
|
252
|
-
|
263
|
+
remove_app_directories
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
desc "live", "Set the app to live mode"
|
268
|
+
def live
|
269
|
+
with_lock do
|
270
|
+
on(KAMAL.proxy_hosts) do |host|
|
271
|
+
roles = KAMAL.roles_on(host)
|
272
|
+
|
273
|
+
roles.each do |role|
|
274
|
+
execute *KAMAL.app(role: role, host: host).live if role.running_proxy?
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
desc "maintenance", "Set the app to maintenance mode"
|
281
|
+
option :drain_timeout, type: :numeric, desc: "How long to allow in-flight requests to complete (defaults to drain_timeout from config)"
|
282
|
+
option :message, type: :string, desc: "Message to display to clients while stopped"
|
283
|
+
def maintenance
|
284
|
+
maintenance_options = { drain_timeout: options[:drain_timeout] || KAMAL.config.drain_timeout, message: options[:message] }
|
285
|
+
|
286
|
+
with_lock do
|
287
|
+
on(KAMAL.proxy_hosts) do |host|
|
288
|
+
roles = KAMAL.roles_on(host)
|
289
|
+
|
290
|
+
roles.each do |role|
|
291
|
+
execute *KAMAL.app(role: role, host: host).maintenance(**maintenance_options) if role.running_proxy?
|
292
|
+
end
|
293
|
+
end
|
253
294
|
end
|
254
295
|
end
|
255
296
|
|
256
297
|
desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true
|
257
298
|
def remove_container(version)
|
258
299
|
with_lock do
|
259
|
-
on(KAMAL.
|
300
|
+
on(KAMAL.app_hosts) do |host|
|
260
301
|
roles = KAMAL.roles_on(host)
|
261
302
|
|
262
303
|
roles.each do |role|
|
@@ -270,7 +311,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
270
311
|
desc "remove_containers", "Remove all app containers from servers", hide: true
|
271
312
|
def remove_containers
|
272
313
|
with_lock do
|
273
|
-
on(KAMAL.
|
314
|
+
on(KAMAL.app_hosts) do |host|
|
274
315
|
roles = KAMAL.roles_on(host)
|
275
316
|
|
276
317
|
roles.each do |role|
|
@@ -284,30 +325,33 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
284
325
|
desc "remove_images", "Remove all app images from servers", hide: true
|
285
326
|
def remove_images
|
286
327
|
with_lock do
|
287
|
-
on(KAMAL.
|
328
|
+
on(KAMAL.app_hosts) do
|
288
329
|
execute *KAMAL.auditor.record("Removed all app images"), verbosity: :debug
|
289
330
|
execute *KAMAL.app.remove_images
|
290
331
|
end
|
291
332
|
end
|
292
333
|
end
|
293
334
|
|
294
|
-
desc "
|
295
|
-
def
|
335
|
+
desc "remove_app_directories", "Remove the app directories from servers", hide: true
|
336
|
+
def remove_app_directories
|
296
337
|
with_lock do
|
297
|
-
on(KAMAL.
|
338
|
+
on(KAMAL.app_hosts) do |host|
|
298
339
|
roles = KAMAL.roles_on(host)
|
299
340
|
|
300
341
|
roles.each do |role|
|
301
|
-
execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory}
|
342
|
+
execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory}", role: role), verbosity: :debug
|
302
343
|
execute *KAMAL.server.remove_app_directory, raise_on_non_zero_exit: false
|
303
344
|
end
|
345
|
+
|
346
|
+
execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory}"), verbosity: :debug
|
347
|
+
execute *KAMAL.app.remove_proxy_app_directory, raise_on_non_zero_exit: false
|
304
348
|
end
|
305
349
|
end
|
306
350
|
end
|
307
351
|
|
308
352
|
desc "version", "Show app version currently running on servers"
|
309
353
|
def version
|
310
|
-
on(KAMAL.
|
354
|
+
on(KAMAL.app_hosts) do |host|
|
311
355
|
role = KAMAL.roles_on(host).first
|
312
356
|
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).current_running_version).strip
|
313
357
|
end
|
@@ -350,6 +394,6 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
350
394
|
end
|
351
395
|
|
352
396
|
def host_boot_groups
|
353
|
-
KAMAL.config.boot.limit ? KAMAL.
|
397
|
+
KAMAL.config.boot.limit ? KAMAL.app_hosts.each_slice(KAMAL.config.boot.limit).to_a : [ KAMAL.app_hosts ]
|
354
398
|
end
|
355
399
|
end
|
data/lib/kamal/cli/base.rb
CHANGED
@@ -133,7 +133,13 @@ module Kamal::Cli
|
|
133
133
|
|
134
134
|
def run_hook(hook, **extra_details)
|
135
135
|
if !options[:skip_hooks] && KAMAL.hook.hook_exists?(hook)
|
136
|
-
details = {
|
136
|
+
details = {
|
137
|
+
hosts: KAMAL.hosts.join(","),
|
138
|
+
roles: KAMAL.specific_roles&.join(","),
|
139
|
+
lock: KAMAL.holding_lock?.to_s,
|
140
|
+
command: command,
|
141
|
+
subcommand: subcommand
|
142
|
+
}.compact
|
137
143
|
|
138
144
|
say "Running the #{hook} hook...", :magenta
|
139
145
|
with_env KAMAL.hook.env(**details, **extra_details) do
|
@@ -147,12 +153,16 @@ module Kamal::Cli
|
|
147
153
|
end
|
148
154
|
|
149
155
|
def on(*args, &block)
|
156
|
+
pre_connect_if_required
|
157
|
+
|
158
|
+
super
|
159
|
+
end
|
160
|
+
|
161
|
+
def pre_connect_if_required
|
150
162
|
if !KAMAL.connected?
|
151
163
|
run_hook "pre-connect"
|
152
164
|
KAMAL.connected = true
|
153
165
|
end
|
154
|
-
|
155
|
-
super
|
156
166
|
end
|
157
167
|
|
158
168
|
def command
|
data/lib/kamal/cli/build.rb
CHANGED
@@ -15,6 +15,8 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
15
15
|
cli = self
|
16
16
|
|
17
17
|
ensure_docker_installed
|
18
|
+
login_to_registry_locally
|
19
|
+
|
18
20
|
run_hook "pre-build"
|
19
21
|
|
20
22
|
uncommitted_changes = Kamal::Git.uncommitted_changes
|
@@ -61,14 +63,16 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
61
63
|
|
62
64
|
desc "pull", "Pull app image from registry onto servers"
|
63
65
|
def pull
|
66
|
+
login_to_registry_remotely
|
67
|
+
|
64
68
|
if (first_hosts = mirror_hosts).any?
|
65
69
|
# Pull on a single host per mirror first to seed them
|
66
70
|
say "Pulling image on #{first_hosts.join(", ")} to seed the #{"mirror".pluralize(first_hosts.count)}...", :magenta
|
67
71
|
pull_on_hosts(first_hosts)
|
68
72
|
say "Pulling image on remaining hosts...", :magenta
|
69
|
-
pull_on_hosts(KAMAL.
|
73
|
+
pull_on_hosts(KAMAL.app_hosts - first_hosts)
|
70
74
|
else
|
71
|
-
pull_on_hosts(KAMAL.
|
75
|
+
pull_on_hosts(KAMAL.app_hosts)
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
@@ -159,9 +163,9 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
159
163
|
end
|
160
164
|
|
161
165
|
def mirror_hosts
|
162
|
-
if KAMAL.
|
166
|
+
if KAMAL.app_hosts.many?
|
163
167
|
mirror_hosts = Concurrent::Hash.new
|
164
|
-
on(KAMAL.
|
168
|
+
on(KAMAL.app_hosts) do |host|
|
165
169
|
first_mirror = capture_with_info(*KAMAL.builder.first_mirror).strip.presence
|
166
170
|
mirror_hosts[first_mirror] ||= host.to_s if first_mirror
|
167
171
|
rescue SSHKit::Command::Failed => e
|
@@ -181,4 +185,16 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
181
185
|
execute *KAMAL.builder.validate_image
|
182
186
|
end
|
183
187
|
end
|
188
|
+
|
189
|
+
def login_to_registry_locally
|
190
|
+
run_locally do
|
191
|
+
execute *KAMAL.registry.login
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def login_to_registry_remotely
|
196
|
+
on(KAMAL.app_hosts) do
|
197
|
+
execute *KAMAL.registry.login
|
198
|
+
end
|
199
|
+
end
|
184
200
|
end
|
data/lib/kamal/cli/main.rb
CHANGED
@@ -20,9 +20,6 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
20
20
|
runtime = print_runtime do
|
21
21
|
invoke_options = deploy_options
|
22
22
|
|
23
|
-
say "Log into image registry...", :magenta
|
24
|
-
invoke "kamal:cli:registry:login", [], invoke_options.merge(skip_local: options[:skip_push])
|
25
|
-
|
26
23
|
if options[:skip_push]
|
27
24
|
say "Pull app image...", :magenta
|
28
25
|
invoke "kamal:cli:build:pull", [], invoke_options
|
@@ -52,7 +49,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
52
49
|
run_hook "post-deploy", secrets: true, runtime: runtime.round.to_s
|
53
50
|
end
|
54
51
|
|
55
|
-
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting kamal-proxy
|
52
|
+
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting kamal-proxy and pruning"
|
56
53
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
57
54
|
def redeploy
|
58
55
|
runtime = print_runtime do
|
@@ -197,10 +194,10 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
197
194
|
confirming "This will replace Traefik with kamal-proxy and restart all accessories" do
|
198
195
|
with_lock do
|
199
196
|
if options[:rolling]
|
200
|
-
|
197
|
+
KAMAL.hosts.each do |host|
|
201
198
|
KAMAL.with_specific_hosts(host) do
|
202
199
|
say "Upgrading #{host}...", :magenta
|
203
|
-
if KAMAL.
|
200
|
+
if KAMAL.app_hosts.include?(host)
|
204
201
|
invoke "kamal:cli:proxy:upgrade", [], options.merge(confirmed: true, rolling: false)
|
205
202
|
reset_invocation(Kamal::Cli::Proxy)
|
206
203
|
end
|
@@ -256,7 +253,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
256
253
|
private
|
257
254
|
def container_available?(version)
|
258
255
|
begin
|
259
|
-
on(KAMAL.
|
256
|
+
on(KAMAL.app_hosts) do
|
260
257
|
KAMAL.roles_on(host).each do |role|
|
261
258
|
container_id = capture_with_info(*KAMAL.app(role: role, host: host).container_id_for_version(version))
|
262
259
|
raise "Container not found" unless container_id.present?
|
data/lib/kamal/cli/proxy.rb
CHANGED
@@ -13,9 +13,10 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
13
13
|
|
14
14
|
version = capture_with_info(*KAMAL.proxy.version).strip.presence
|
15
15
|
|
16
|
-
if version && Kamal::Utils.older_version?(version, Kamal::Configuration::
|
17
|
-
raise "kamal-proxy version #{version} is too old, run `kamal proxy reboot` in order to update to at least #{Kamal::Configuration::
|
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}"
|
18
18
|
end
|
19
|
+
execute *KAMAL.proxy.ensure_apps_config_directory
|
19
20
|
execute *KAMAL.proxy.start_or_run
|
20
21
|
end
|
21
22
|
end
|
@@ -24,30 +25,75 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
24
25
|
desc "boot_config <set|get|reset>", "Manage kamal-proxy boot configuration"
|
25
26
|
option :publish, type: :boolean, default: true, desc: "Publish the proxy ports on the host"
|
26
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"
|
27
|
-
option :http_port, type: :numeric, default: Kamal::Configuration::
|
28
|
-
option :https_port, type: :numeric, default: Kamal::Configuration::
|
29
|
-
option :log_max_size, type: :string, default: Kamal::Configuration::
|
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"
|
31
|
+
option :registry, type: :string, default: nil, desc: "Registry to use for the proxy image"
|
32
|
+
option :repository, type: :string, default: nil, desc: "Repository for the proxy image"
|
33
|
+
option :image_version, type: :string, default: nil, desc: "Version of the proxy to run"
|
34
|
+
option :metrics_port, type: :numeric, default: nil, desc: "Port to report prometheus metrics on"
|
35
|
+
option :debug, type: :boolean, default: false, desc: "Whether to run the proxy in debug mode"
|
30
36
|
option :docker_options, type: :array, default: [], desc: "Docker options to pass to the proxy container", banner: "option=value option2=value2"
|
31
37
|
def boot_config(subcommand)
|
38
|
+
proxy_boot_config = KAMAL.config.proxy_boot
|
39
|
+
|
32
40
|
case subcommand
|
33
41
|
when "set"
|
34
42
|
boot_options = [
|
35
|
-
*(
|
36
|
-
*(
|
43
|
+
*(proxy_boot_config.publish_args(options[:http_port], options[:https_port], options[:publish_host_ip]) if options[:publish]),
|
44
|
+
*(proxy_boot_config.logging_args(options[:log_max_size])),
|
45
|
+
*("--expose=#{options[:metrics_port]}" if options[:metrics_port]),
|
37
46
|
*options[:docker_options].map { |option| "--#{option}" }
|
38
47
|
]
|
39
48
|
|
49
|
+
image = [
|
50
|
+
options[:registry].presence,
|
51
|
+
options[:repository].presence || proxy_boot_config.repository_name,
|
52
|
+
proxy_boot_config.image_name
|
53
|
+
].compact.join("/")
|
54
|
+
|
55
|
+
image_version = options[:image_version]
|
56
|
+
|
57
|
+
run_command_options = { debug: options[:debug] || nil, "metrics-port": options[:metrics_port] }.compact
|
58
|
+
run_command = "kamal-proxy run #{Kamal::Utils.optionize(run_command_options).join(" ")}" if run_command_options.any?
|
59
|
+
|
40
60
|
on(KAMAL.proxy_hosts) do |host|
|
41
61
|
execute(*KAMAL.proxy.ensure_proxy_directory)
|
42
|
-
|
62
|
+
if boot_options != proxy_boot_config.default_boot_options
|
63
|
+
upload! StringIO.new(boot_options.join(" ")), proxy_boot_config.options_file
|
64
|
+
else
|
65
|
+
execute *KAMAL.proxy.reset_boot_options, raise_on_non_zero_exit: false
|
66
|
+
end
|
67
|
+
|
68
|
+
if image != proxy_boot_config.image_default
|
69
|
+
upload! StringIO.new(image), proxy_boot_config.image_file
|
70
|
+
else
|
71
|
+
execute *KAMAL.proxy.reset_image, raise_on_non_zero_exit: false
|
72
|
+
end
|
73
|
+
|
74
|
+
if image_version
|
75
|
+
upload! StringIO.new(image_version), proxy_boot_config.image_version_file
|
76
|
+
else
|
77
|
+
execute *KAMAL.proxy.reset_image_version, raise_on_non_zero_exit: false
|
78
|
+
end
|
79
|
+
|
80
|
+
if run_command
|
81
|
+
upload! StringIO.new(run_command), proxy_boot_config.run_command_file
|
82
|
+
else
|
83
|
+
execute *KAMAL.proxy.reset_run_command, raise_on_non_zero_exit: false
|
84
|
+
end
|
43
85
|
end
|
44
86
|
when "get"
|
87
|
+
|
45
88
|
on(KAMAL.proxy_hosts) do |host|
|
46
|
-
puts "Host #{host}: #{capture_with_info(*KAMAL.proxy.
|
89
|
+
puts "Host #{host}: #{capture_with_info(*KAMAL.proxy.boot_config)}"
|
47
90
|
end
|
48
91
|
when "reset"
|
49
92
|
on(KAMAL.proxy_hosts) do |host|
|
50
|
-
execute *KAMAL.proxy.reset_boot_options
|
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
|
51
97
|
end
|
52
98
|
else
|
53
99
|
raise ArgumentError, "Unknown boot_config subcommand #{subcommand}"
|
@@ -71,6 +117,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
71
117
|
"Stopping and removing kamal-proxy on #{host}, if running..."
|
72
118
|
execute *KAMAL.proxy.stop, raise_on_non_zero_exit: false
|
73
119
|
execute *KAMAL.proxy.remove_container
|
120
|
+
execute *KAMAL.proxy.ensure_apps_config_directory
|
74
121
|
|
75
122
|
execute *KAMAL.proxy.run
|
76
123
|
|
data/lib/kamal/cli/server.rb
CHANGED
@@ -2,8 +2,10 @@ class Kamal::Cli::Server < Kamal::Cli::Base
|
|
2
2
|
desc "exec", "Run a custom command on the server (use --help to show options)"
|
3
3
|
option :interactive, type: :boolean, aliases: "-i", default: false, desc: "Run the command interactively (use for console/bash)"
|
4
4
|
def exec(*cmd)
|
5
|
+
pre_connect_if_required
|
6
|
+
|
5
7
|
cmd = Kamal::Utils.join_commands(cmd)
|
6
|
-
hosts = KAMAL.hosts
|
8
|
+
hosts = KAMAL.hosts
|
7
9
|
|
8
10
|
case
|
9
11
|
when options[:interactive]
|
@@ -27,7 +29,7 @@ class Kamal::Cli::Server < Kamal::Cli::Base
|
|
27
29
|
with_lock do
|
28
30
|
missing = []
|
29
31
|
|
30
|
-
on(KAMAL.hosts
|
32
|
+
on(KAMAL.hosts) do |host|
|
31
33
|
unless execute(*KAMAL.docker.installed?, raise_on_non_zero_exit: false)
|
32
34
|
if execute(*KAMAL.docker.superuser?, raise_on_non_zero_exit: false)
|
33
35
|
info "Missing Docker on #{host}. Installing…"
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# KAMAL_HOSTS
|
14
14
|
# KAMAL_COMMAND
|
15
15
|
# KAMAL_SUBCOMMAND
|
16
|
-
#
|
16
|
+
# KAMAL_ROLES (if set)
|
17
17
|
# KAMAL_DESTINATION (if set)
|
18
18
|
|
19
19
|
# Only check the build status for production deployments
|
@@ -82,11 +82,12 @@ end
|
|
82
82
|
|
83
83
|
$stdout.sync = true
|
84
84
|
|
85
|
-
puts "Checking build status..."
|
86
|
-
attempts = 0
|
87
|
-
checks = GithubStatusChecks.new
|
88
|
-
|
89
85
|
begin
|
86
|
+
puts "Checking build status..."
|
87
|
+
|
88
|
+
attempts = 0
|
89
|
+
checks = GithubStatusChecks.new
|
90
|
+
|
90
91
|
loop do
|
91
92
|
case checks.state
|
92
93
|
when "success"
|