kamal 1.8.3 → 2.7.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/README.md +1 -1
- data/lib/kamal/cli/accessory.rb +92 -38
- data/lib/kamal/cli/alias/command.rb +10 -0
- data/lib/kamal/cli/app/{prepare_assets.rb → assets.rb} +1 -1
- data/lib/kamal/cli/app/boot.rb +23 -16
- data/lib/kamal/cli/app/error_pages.rb +33 -0
- data/lib/kamal/cli/app/ssl_certificates.rb +28 -0
- data/lib/kamal/cli/app.rb +132 -30
- data/lib/kamal/cli/base.rb +57 -53
- data/lib/kamal/cli/build.rb +81 -38
- data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
- data/lib/kamal/cli/healthcheck/poller.rb +18 -39
- data/lib/kamal/cli/lock.rb +2 -3
- data/lib/kamal/cli/main.rb +60 -59
- data/lib/kamal/cli/proxy.rb +290 -0
- data/lib/kamal/cli/prune.rb +0 -1
- data/lib/kamal/cli/registry.rb +2 -0
- data/lib/kamal/cli/secrets.rb +49 -0
- data/lib/kamal/cli/server.rb +6 -5
- data/lib/kamal/cli/templates/deploy.yml +53 -53
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +2 -12
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- 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 +19 -6
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/secrets +17 -0
- data/lib/kamal/cli.rb +2 -0
- data/lib/kamal/commander/specifics.rb +19 -6
- data/lib/kamal/commander.rb +39 -32
- data/lib/kamal/commands/accessory/proxy.rb +16 -0
- data/lib/kamal/commands/accessory.rb +19 -19
- data/lib/kamal/commands/app/assets.rb +10 -10
- data/lib/kamal/commands/app/containers.rb +2 -2
- data/lib/kamal/commands/app/error_pages.rb +9 -0
- data/lib/kamal/commands/app/execution.rb +7 -4
- data/lib/kamal/commands/app/images.rb +1 -1
- data/lib/kamal/commands/app/logging.rb +16 -6
- data/lib/kamal/commands/app/proxy.rb +32 -0
- data/lib/kamal/commands/app.rb +25 -24
- data/lib/kamal/commands/auditor.rb +12 -3
- data/lib/kamal/commands/base.rb +54 -8
- data/lib/kamal/commands/builder/base.rb +46 -16
- data/lib/kamal/commands/builder/clone.rb +16 -14
- data/lib/kamal/commands/builder/cloud.rb +22 -0
- data/lib/kamal/commands/builder/hybrid.rb +21 -0
- data/lib/kamal/commands/builder/local.rb +14 -0
- data/lib/kamal/commands/builder/pack.rb +46 -0
- data/lib/kamal/commands/builder/remote.rb +63 -0
- data/lib/kamal/commands/builder.rb +21 -45
- data/lib/kamal/commands/docker.rb +4 -0
- data/lib/kamal/commands/hook.rb +8 -2
- data/lib/kamal/commands/lock.rb +2 -6
- data/lib/kamal/commands/proxy.rb +127 -0
- data/lib/kamal/commands/prune.rb +1 -9
- data/lib/kamal/commands/registry.rb +9 -7
- data/lib/kamal/commands/server.rb +11 -1
- data/lib/kamal/configuration/accessory.rb +89 -12
- data/lib/kamal/configuration/alias.rb +15 -0
- data/lib/kamal/configuration/builder.rb +73 -15
- data/lib/kamal/configuration/docs/accessory.yml +53 -15
- data/lib/kamal/configuration/docs/alias.yml +26 -0
- data/lib/kamal/configuration/docs/boot.yml +3 -3
- data/lib/kamal/configuration/docs/builder.yml +63 -38
- data/lib/kamal/configuration/docs/configuration.yml +62 -46
- data/lib/kamal/configuration/docs/env.yml +61 -17
- data/lib/kamal/configuration/docs/logging.yml +3 -3
- data/lib/kamal/configuration/docs/proxy.yml +168 -0
- data/lib/kamal/configuration/docs/registry.yml +20 -13
- data/lib/kamal/configuration/docs/role.yml +14 -13
- data/lib/kamal/configuration/docs/servers.yml +2 -2
- data/lib/kamal/configuration/docs/ssh.yml +23 -19
- data/lib/kamal/configuration/docs/sshkit.yml +4 -4
- data/lib/kamal/configuration/env/tag.rb +4 -3
- data/lib/kamal/configuration/env.rb +19 -17
- data/lib/kamal/configuration/proxy/boot.rb +129 -0
- data/lib/kamal/configuration/proxy.rb +124 -0
- data/lib/kamal/configuration/registry.rb +7 -6
- data/lib/kamal/configuration/role.rb +69 -98
- data/lib/kamal/configuration/servers.rb +8 -1
- data/lib/kamal/configuration/validator/accessory.rb +6 -2
- data/lib/kamal/configuration/validator/alias.rb +15 -0
- data/lib/kamal/configuration/validator/builder.rb +6 -0
- data/lib/kamal/configuration/validator/proxy.rb +25 -0
- data/lib/kamal/configuration/validator/role.rb +3 -1
- data/lib/kamal/configuration/validator/servers.rb +1 -1
- data/lib/kamal/configuration/validator.rb +62 -24
- data/lib/kamal/configuration.rb +96 -50
- data/lib/kamal/docker.rb +30 -0
- data/lib/kamal/env_file.rb +7 -1
- data/lib/kamal/git.rb +10 -0
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +51 -0
- data/lib/kamal/secrets/adapters/base.rb +33 -0
- data/lib/kamal/secrets/adapters/bitwarden.rb +81 -0
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +66 -0
- data/lib/kamal/secrets/adapters/doppler.rb +57 -0
- data/lib/kamal/secrets/adapters/enpass.rb +71 -0
- data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +40 -0
- data/lib/kamal/secrets/adapters/one_password.rb +104 -0
- data/lib/kamal/secrets/adapters/passbolt.rb +130 -0
- data/lib/kamal/secrets/adapters/test.rb +14 -0
- data/lib/kamal/secrets/adapters.rb +16 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +33 -0
- data/lib/kamal/secrets.rb +42 -0
- data/lib/kamal/sshkit_with_ext.rb +1 -0
- data/lib/kamal/utils.rb +30 -0
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +3 -1
- metadata +63 -36
- data/lib/kamal/cli/env.rb +0 -54
- data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-traefik-reboot.sample +0 -3
- data/lib/kamal/cli/templates/template.env +0 -2
- data/lib/kamal/cli/traefik.rb +0 -122
- data/lib/kamal/commands/app/cord.rb +0 -22
- data/lib/kamal/commands/builder/multiarch/remote.rb +0 -65
- data/lib/kamal/commands/builder/multiarch.rb +0 -41
- data/lib/kamal/commands/builder/native/cached.rb +0 -25
- data/lib/kamal/commands/builder/native/remote.rb +0 -67
- data/lib/kamal/commands/builder/native.rb +0 -20
- data/lib/kamal/commands/traefik.rb +0 -85
- data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
- data/lib/kamal/configuration/docs/traefik.yml +0 -62
- data/lib/kamal/configuration/healthcheck.rb +0 -63
- data/lib/kamal/configuration/traefik.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e1cf57d731a8b129a8ccbb86faddd3e813bc4d17895e6e538fe904f5bb65d27
|
4
|
+
data.tar.gz: 2d7d81b3a34f42fb427bfed18f9cf0ed1955d38e4b4783c1407bc1db6de5cef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3144c40082cfa24c78e2a1ebf2f433e491be3f5966e45cfc5488c3a11f5a3f513f097f7818cbc9e34d20b79986e64212055a87030fd4aa386a1d82bbb7d0efe
|
7
|
+
data.tar.gz: c6b796497a6f7a68815d340664b34fb9943f55ea7121122994aa3fdadaa5b12a18fb4078ff194cffb6060917a74611fdf31017afa75f2515d94ec259e0809251
|
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
|
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
|
|
data/lib/kamal/cli/accessory.rb
CHANGED
@@ -1,18 +1,39 @@
|
|
1
|
+
require "active_support/core_ext/array/conversions"
|
2
|
+
require "concurrent/array"
|
3
|
+
|
1
4
|
class Kamal::Cli::Accessory < Kamal::Cli::Base
|
2
5
|
desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
|
3
|
-
def boot(name,
|
6
|
+
def boot(name, prepare: true)
|
4
7
|
with_lock do
|
5
8
|
if name == "all"
|
6
9
|
KAMAL.accessory_names.each { |accessory_name| boot(accessory_name) }
|
7
10
|
else
|
11
|
+
prepare(name) if prepare
|
12
|
+
|
8
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
|
+
|
9
24
|
directories(name)
|
10
25
|
upload(name)
|
11
26
|
|
12
|
-
on(hosts) do
|
13
|
-
execute *KAMAL.registry.login if login
|
27
|
+
on(hosts) do |host|
|
14
28
|
execute *KAMAL.auditor.record("Booted #{name} accessory"), verbosity: :debug
|
15
|
-
execute *accessory.
|
29
|
+
execute *accessory.ensure_env_directory
|
30
|
+
upload! accessory.secrets_io, accessory.secrets_path, mode: "0600"
|
31
|
+
execute *accessory.run(host: host)
|
32
|
+
|
33
|
+
if accessory.running_proxy?
|
34
|
+
target = capture_with_info(*accessory.container_id_for(container_name: accessory.service_name, only_running: true)).strip
|
35
|
+
execute *accessory.deploy(target: target)
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
18
39
|
end
|
@@ -55,15 +76,10 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
55
76
|
if name == "all"
|
56
77
|
KAMAL.accessory_names.each { |accessory_name| reboot(accessory_name) }
|
57
78
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
stop(name)
|
64
|
-
remove_container(name)
|
65
|
-
boot(name, login: false)
|
66
|
-
end
|
79
|
+
prepare(name)
|
80
|
+
stop(name)
|
81
|
+
remove_container(name)
|
82
|
+
boot(name, prepare: false)
|
67
83
|
end
|
68
84
|
end
|
69
85
|
end
|
@@ -75,6 +91,10 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
75
91
|
on(hosts) do
|
76
92
|
execute *KAMAL.auditor.record("Started #{name} accessory"), verbosity: :debug
|
77
93
|
execute *accessory.start
|
94
|
+
if accessory.running_proxy?
|
95
|
+
target = capture_with_info(*accessory.container_id_for(container_name: accessory.service_name, only_running: true)).strip
|
96
|
+
execute *accessory.deploy(target: target)
|
97
|
+
end
|
78
98
|
end
|
79
99
|
end
|
80
100
|
end
|
@@ -87,6 +107,11 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
87
107
|
on(hosts) do
|
88
108
|
execute *KAMAL.auditor.record("Stopped #{name} accessory"), verbosity: :debug
|
89
109
|
execute *accessory.stop, raise_on_non_zero_exit: false
|
110
|
+
|
111
|
+
if accessory.running_proxy?
|
112
|
+
target = capture_with_info(*accessory.container_id_for(container_name: accessory.service_name, only_running: true)).strip
|
113
|
+
execute *accessory.remove if target
|
114
|
+
end
|
90
115
|
end
|
91
116
|
end
|
92
117
|
end
|
@@ -95,10 +120,8 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
95
120
|
desc "restart [NAME]", "Restart existing accessory container on host"
|
96
121
|
def restart(name)
|
97
122
|
with_lock do
|
98
|
-
|
99
|
-
|
100
|
-
start(name)
|
101
|
-
end
|
123
|
+
stop(name)
|
124
|
+
start(name)
|
102
125
|
end
|
103
126
|
end
|
104
127
|
|
@@ -114,32 +137,37 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
114
137
|
end
|
115
138
|
end
|
116
139
|
|
117
|
-
desc "exec [NAME] [CMD]", "Execute a custom command on servers (use --help to show options)"
|
140
|
+
desc "exec [NAME] [CMD...]", "Execute a custom command on servers within the accessory container (use --help to show options)"
|
118
141
|
option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
|
119
142
|
option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
|
120
|
-
def exec(name, cmd)
|
143
|
+
def exec(name, *cmd)
|
144
|
+
pre_connect_if_required
|
145
|
+
|
146
|
+
cmd = Kamal::Utils.join_commands(cmd)
|
121
147
|
with_accessory(name) do |accessory, hosts|
|
122
148
|
case
|
123
149
|
when options[:interactive] && options[:reuse]
|
124
|
-
say "Launching interactive command
|
150
|
+
say "Launching interactive command via SSH from existing container...", :magenta
|
125
151
|
run_locally { exec accessory.execute_in_existing_container_over_ssh(cmd) }
|
126
152
|
|
127
153
|
when options[:interactive]
|
128
154
|
say "Launching interactive command via SSH from new container...", :magenta
|
155
|
+
on(accessory.hosts.first) { execute *KAMAL.registry.login }
|
129
156
|
run_locally { exec accessory.execute_in_new_container_over_ssh(cmd) }
|
130
157
|
|
131
158
|
when options[:reuse]
|
132
159
|
say "Launching command from existing container...", :magenta
|
133
|
-
on(hosts) do
|
160
|
+
on(hosts) do |host|
|
134
161
|
execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
|
135
|
-
capture_with_info(*accessory.execute_in_existing_container(cmd))
|
162
|
+
puts_by_host host, capture_with_info(*accessory.execute_in_existing_container(cmd))
|
136
163
|
end
|
137
164
|
|
138
165
|
else
|
139
166
|
say "Launching command from new container...", :magenta
|
140
|
-
on(hosts) do
|
167
|
+
on(hosts) do |host|
|
168
|
+
execute *KAMAL.registry.login
|
141
169
|
execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
|
142
|
-
capture_with_info(*accessory.execute_in_new_container(cmd))
|
170
|
+
puts_by_host host, capture_with_info(*accessory.execute_in_new_container(cmd))
|
143
171
|
end
|
144
172
|
end
|
145
173
|
end
|
@@ -149,25 +177,27 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
149
177
|
option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)"
|
150
178
|
option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server"
|
151
179
|
option :grep, aliases: "-g", desc: "Show lines with grep match only (use this to fetch specific requests by id)"
|
152
|
-
option :grep_options,
|
180
|
+
option :grep_options, desc: "Additional options supplied to grep"
|
153
181
|
option :follow, aliases: "-f", desc: "Follow logs on primary server (or specific host set by --hosts)"
|
182
|
+
option :skip_timestamps, type: :boolean, aliases: "-T", desc: "Skip appending timestamps to logging output"
|
154
183
|
def logs(name)
|
155
184
|
with_accessory(name) do |accessory, hosts|
|
156
185
|
grep = options[:grep]
|
157
186
|
grep_options = options[:grep_options]
|
187
|
+
timestamps = !options[:skip_timestamps]
|
158
188
|
|
159
189
|
if options[:follow]
|
160
190
|
run_locally do
|
161
191
|
info "Following logs on #{hosts}..."
|
162
|
-
info accessory.follow_logs(grep: grep, grep_options: grep_options)
|
163
|
-
exec accessory.follow_logs(grep: grep, grep_options: grep_options)
|
192
|
+
info accessory.follow_logs(timestamps: timestamps, grep: grep, grep_options: grep_options)
|
193
|
+
exec accessory.follow_logs(timestamps: timestamps, grep: grep, grep_options: grep_options)
|
164
194
|
end
|
165
195
|
else
|
166
196
|
since = options[:since]
|
167
197
|
lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
|
168
198
|
|
169
199
|
on(hosts) do
|
170
|
-
puts capture_with_info(*accessory.logs(since: since, lines: lines, grep: grep, grep_options: grep_options))
|
200
|
+
puts capture_with_info(*accessory.logs(timestamps: timestamps, since: since, lines: lines, grep: grep, grep_options: grep_options))
|
171
201
|
end
|
172
202
|
end
|
173
203
|
end
|
@@ -222,6 +252,25 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
222
252
|
end
|
223
253
|
end
|
224
254
|
|
255
|
+
desc "upgrade", "Upgrade accessories from Kamal 1.x to 2.0 (restart them in 'kamal' network)"
|
256
|
+
option :rolling, type: :boolean, default: false, desc: "Upgrade one host at a time"
|
257
|
+
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
258
|
+
def upgrade(name)
|
259
|
+
confirming "This will restart all accessories" do
|
260
|
+
with_lock do
|
261
|
+
host_groups = options[:rolling] ? KAMAL.accessory_hosts : [ KAMAL.accessory_hosts ]
|
262
|
+
host_groups.each do |hosts|
|
263
|
+
host_list = Array(hosts).join(",")
|
264
|
+
KAMAL.with_specific_hosts(hosts) do
|
265
|
+
say "Upgrading #{name} accessories on #{host_list}...", :magenta
|
266
|
+
reboot name
|
267
|
+
say "Upgraded #{name} accessories on #{host_list}...", :magenta
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
225
274
|
private
|
226
275
|
def with_accessory(name)
|
227
276
|
if KAMAL.config.accessory(name)
|
@@ -241,19 +290,24 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
241
290
|
end
|
242
291
|
|
243
292
|
def accessory_hosts(accessory)
|
244
|
-
|
245
|
-
KAMAL.specific_hosts & accessory.hosts
|
246
|
-
else
|
247
|
-
accessory.hosts
|
248
|
-
end
|
293
|
+
KAMAL.accessory_hosts & accessory.hosts
|
249
294
|
end
|
250
295
|
|
251
296
|
def remove_accessory(name)
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
297
|
+
stop(name)
|
298
|
+
remove_container(name)
|
299
|
+
remove_image(name)
|
300
|
+
remove_service_directory(name)
|
301
|
+
end
|
302
|
+
|
303
|
+
def prepare(name)
|
304
|
+
with_accessory(name) do |accessory, hosts|
|
305
|
+
on(hosts) do
|
306
|
+
execute *KAMAL.registry.login(registry_config: accessory.registry)
|
307
|
+
execute *KAMAL.docker.create_network
|
308
|
+
rescue SSHKit::Command::Failed => e
|
309
|
+
raise unless e.message.include?("already exists")
|
310
|
+
end
|
257
311
|
end
|
258
312
|
end
|
259
313
|
end
|
data/lib/kamal/cli/app/boot.rb
CHANGED
@@ -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 :
|
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
|
+
hostname = "#{host.to_s[0...51].chomp(".")}-#{SecureRandom.hex(6)}"
|
49
|
+
|
50
|
+
execute *app.ensure_env_directory
|
51
|
+
upload! role.secrets_io(host), role.secrets_path, mode: "0600"
|
48
52
|
|
49
|
-
execute *app.tie_cord(role.cord_host_file) if uses_cord?
|
50
|
-
hostname = "#{host.to_s[0...51].gsub(/\.+$/, '')}-#{SecureRandom.hex(6)}"
|
51
53
|
execute *app.run(hostname: hostname)
|
52
|
-
|
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,17 +68,9 @@ 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?
|
73
|
+
execute *app.clean_up_error_pages if KAMAL.config.error_pages_path
|
71
74
|
end
|
72
75
|
|
73
76
|
def release_barrier
|
@@ -88,8 +91,12 @@ class Kamal::Cli::App::Boot
|
|
88
91
|
def close_barrier
|
89
92
|
if barrier.close
|
90
93
|
info "First #{KAMAL.primary_role} container is unhealthy on #{host}, not booting any other roles"
|
91
|
-
|
92
|
-
|
94
|
+
begin
|
95
|
+
error capture_with_info(*app.logs(container_id: app.container_id_for_version(version)))
|
96
|
+
error capture_with_info(*app.container_health_log(version: version))
|
97
|
+
rescue SSHKit::Command::Failed
|
98
|
+
error "Could not fetch logs for #{version}"
|
99
|
+
end
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
@@ -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
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Kamal::Cli::App::SslCertificates
|
2
|
+
attr_reader :host, :role, :sshkit
|
3
|
+
delegate :execute, :info, :upload!, to: :sshkit
|
4
|
+
|
5
|
+
def initialize(host, role, sshkit)
|
6
|
+
@host = host
|
7
|
+
@role = role
|
8
|
+
@sshkit = sshkit
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
if role.running_proxy? && role.proxy.custom_ssl_certificate?
|
13
|
+
info "Writing SSL certificates for #{role.name} on #{host}"
|
14
|
+
execute *app.create_ssl_directory
|
15
|
+
if cert_content = role.proxy.certificate_pem_content
|
16
|
+
upload!(StringIO.new(cert_content), role.proxy.host_tls_cert, mode: "0644")
|
17
|
+
end
|
18
|
+
if key_content = role.proxy.private_key_pem_content
|
19
|
+
upload!(StringIO.new(key_content), role.proxy.host_tls_key, mode: "0644")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def app
|
26
|
+
@app ||= KAMAL.app(role: role, host: host)
|
27
|
+
end
|
28
|
+
end
|