dash 2.12.0 → 3.0.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/app/boot.rb +47 -11
- data/lib/kamal/cli/app/rollout_boot.rb +59 -0
- data/lib/kamal/cli/app/ssl_certificates.rb +12 -3
- data/lib/kamal/cli/app.rb +74 -7
- data/lib/kamal/cli/base.rb +41 -32
- data/lib/kamal/cli/doctor/config_checks.rb +28 -0
- data/lib/kamal/cli/doctor/endpoint_checks.rb +114 -0
- data/lib/kamal/cli/doctor/host_checks.rb +178 -0
- data/lib/kamal/cli/doctor.rb +112 -0
- data/lib/kamal/cli/healthcheck/drift_error.rb +7 -0
- data/lib/kamal/cli/healthcheck/poller.rb +60 -10
- data/lib/kamal/cli/main.rb +63 -0
- data/lib/kamal/cli/proxy/drift.rb +39 -0
- data/lib/kamal/cli/proxy/loadbalancer_claim.rb +70 -0
- data/lib/kamal/cli/proxy/loadbalancer_reboot.rb +41 -0
- data/lib/kamal/cli/proxy/reboot.rb +172 -0
- data/lib/kamal/cli/proxy.rb +200 -26
- data/lib/kamal/cli/prune.rb +7 -4
- data/lib/kamal/cli/templates/sample_hooks/post-app-stop.sample +9 -0
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-deploy.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-stop.sample +12 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-deploy.sample +3 -0
- data/lib/kamal/cli.rb +1 -0
- data/lib/kamal/commands/app/proxy.rb +12 -0
- data/lib/kamal/commands/app.rb +8 -0
- data/lib/kamal/commands/base.rb +11 -1
- data/lib/kamal/commands/docker.rb +5 -0
- data/lib/kamal/commands/loadbalancer.rb +76 -34
- data/lib/kamal/commands/proxy.rb +105 -11
- data/lib/kamal/commands/prune.rb +16 -2
- data/lib/kamal/commands/server.rb +5 -0
- data/lib/kamal/configuration/accessory.rb +9 -8
- data/lib/kamal/configuration/boot.rb +38 -7
- data/lib/kamal/configuration/docs/accessory.yml +28 -1
- data/lib/kamal/configuration/docs/boot.yml +17 -2
- data/lib/kamal/configuration/docs/configuration.yml +2 -1
- data/lib/kamal/configuration/docs/proxy.yml +844 -24
- data/lib/kamal/configuration/docs/role.yml +86 -0
- data/lib/kamal/configuration/loadbalancer.rb +70 -7
- data/lib/kamal/configuration/proxy/acme.rb +69 -0
- data/lib/kamal/configuration/proxy/run.rb +194 -5
- data/lib/kamal/configuration/proxy.rb +495 -18
- data/lib/kamal/configuration/role/healthcheck.rb +95 -0
- data/lib/kamal/configuration/role.rb +104 -1
- data/lib/kamal/configuration/validator/proxy.rb +623 -10
- data/lib/kamal/configuration/validator/role.rb +26 -0
- data/lib/kamal/configuration/validator.rb +26 -3
- data/lib/kamal/configuration.rb +197 -0
- data/lib/kamal/sshkit_with_ext.rb +27 -2
- data/lib/kamal/utils.rb +22 -2
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +11 -0
- metadata +18 -2
|
@@ -3,7 +3,7 @@ class Kamal::Configuration::Role
|
|
|
3
3
|
|
|
4
4
|
delegate :argumentize, :optionize, to: Kamal::Utils
|
|
5
5
|
|
|
6
|
-
attr_reader :name, :config, :specialized_env, :specialized_logging, :specialized_proxy
|
|
6
|
+
attr_reader :name, :config, :specialized_env, :specialized_logging, :specialized_proxy, :healthcheck
|
|
7
7
|
|
|
8
8
|
alias to_s name
|
|
9
9
|
|
|
@@ -24,6 +24,13 @@ class Kamal::Configuration::Role
|
|
|
24
24
|
logging_config: specializations.fetch("logging", {}),
|
|
25
25
|
context: "servers/#{name}/logging"
|
|
26
26
|
|
|
27
|
+
# `healthcheck: false` is an opt-out, not a healthcheck — it leaves @healthcheck nil.
|
|
28
|
+
if healthcheck_config = specializations["healthcheck"]
|
|
29
|
+
@healthcheck = Kamal::Configuration::Role::Healthcheck.new \
|
|
30
|
+
healthcheck_config: healthcheck_config,
|
|
31
|
+
context: "servers/#{name}/healthcheck"
|
|
32
|
+
end
|
|
33
|
+
|
|
27
34
|
initialize_specialized_proxy
|
|
28
35
|
end
|
|
29
36
|
|
|
@@ -39,6 +46,14 @@ class Kamal::Configuration::Role
|
|
|
39
46
|
tagged_hosts.fetch(host).collect { |tag| config.env_tag(tag) }.compact
|
|
40
47
|
end
|
|
41
48
|
|
|
49
|
+
# The role's own hosts carrying `tag` in deploy.yml. Accessory `tag:`/`tags:` resolution
|
|
50
|
+
# comes through here rather than re-walking raw_config.servers, so it inherits
|
|
51
|
+
# extract_hosts_from_config's handling of every legal role shape — bare list, `hosts:`
|
|
52
|
+
# mapping, and the top-level `servers:` array.
|
|
53
|
+
def hosts_with_tag(tag)
|
|
54
|
+
tagged_hosts.select { |_host, tags| tags.include?(tag) }.keys
|
|
55
|
+
end
|
|
56
|
+
|
|
42
57
|
def cmd
|
|
43
58
|
specializations["cmd"]
|
|
44
59
|
end
|
|
@@ -63,10 +78,40 @@ class Kamal::Configuration::Role
|
|
|
63
78
|
logging.args
|
|
64
79
|
end
|
|
65
80
|
|
|
81
|
+
# Kept out of option_args on purpose: Commands::App::Execution splats those into
|
|
82
|
+
# one-shot `kamal app exec` containers, which must not inherit a service healthcheck.
|
|
83
|
+
def healthcheck_args
|
|
84
|
+
healthcheck&.args || []
|
|
85
|
+
end
|
|
86
|
+
|
|
66
87
|
def logging
|
|
67
88
|
@logging ||= config.logging.merge(specialized_logging)
|
|
68
89
|
end
|
|
69
90
|
|
|
91
|
+
# nil unless the role paces its own hosts. Deliberately not falling back to the global
|
|
92
|
+
# boot: that limit is already spent slicing the cross-role host list in
|
|
93
|
+
# Cli::App#host_boot_groups, and handing it to the per-role runner as well would sleep
|
|
94
|
+
# `boot.wait` a second time inside every group.
|
|
95
|
+
#
|
|
96
|
+
# Built on first read rather than in the initializer — Servers.new constructs every Role
|
|
97
|
+
# before Kamal::Configuration#initialize has finished assigning its own collaborators.
|
|
98
|
+
def boot
|
|
99
|
+
return @boot if defined?(@boot)
|
|
100
|
+
|
|
101
|
+
@boot =
|
|
102
|
+
if (boot_config = specializations["boot"])
|
|
103
|
+
Kamal::Configuration::Boot.new \
|
|
104
|
+
config: config, boot_config: boot_config, context: "servers/#{name}/boot"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# `hosts` is what on_roles is about to pace — `role.hosts & the run's hosts`, so
|
|
109
|
+
# --roles/--hosts have already narrowed it. A percentage limit has to count that, not
|
|
110
|
+
# the role's configured hosts.
|
|
111
|
+
def boot_runner_options(hosts)
|
|
112
|
+
boot&.runner_options_for(hosts) || {}
|
|
113
|
+
end
|
|
114
|
+
|
|
70
115
|
def proxy
|
|
71
116
|
@proxy ||= specialized_proxy.merge(config.proxy) if running_proxy?
|
|
72
117
|
end
|
|
@@ -79,6 +124,49 @@ class Kamal::Configuration::Role
|
|
|
79
124
|
running_proxy? && proxy.ssl?
|
|
80
125
|
end
|
|
81
126
|
|
|
127
|
+
# Where a deploy of this role actually waits for readiness before stopping the
|
|
128
|
+
# old container. Without a proxy or a docker healthcheck, Healthcheck::Poller
|
|
129
|
+
# only sees `.State.Status`, so staying `running` for the readiness delay is
|
|
130
|
+
# the whole gate. `:healthcheck_exec` is the odd one out: the container declares no
|
|
131
|
+
# docker healthcheck, the deploy host polls the probe itself.
|
|
132
|
+
def readiness_source
|
|
133
|
+
if running_proxy?
|
|
134
|
+
:proxy
|
|
135
|
+
elsif healthcheck&.exec?
|
|
136
|
+
:healthcheck_exec
|
|
137
|
+
elsif healthcheck
|
|
138
|
+
:healthcheck
|
|
139
|
+
elsif health_cmd_option?
|
|
140
|
+
:docker_options
|
|
141
|
+
else
|
|
142
|
+
:none
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# One-line rendering of readiness_source, shared by the deploy banner and `kamal doctor`
|
|
147
|
+
# so both name the same gate the same way.
|
|
148
|
+
def readiness_description
|
|
149
|
+
case readiness_source
|
|
150
|
+
when :proxy
|
|
151
|
+
[ "kamal-proxy health check", proxy.healthcheck_path ].compact.join(" ")
|
|
152
|
+
when :healthcheck
|
|
153
|
+
healthcheck.port ? "healthcheck #{healthcheck.path}:#{healthcheck.port}" : "healthcheck (custom cmd)"
|
|
154
|
+
when :healthcheck_exec
|
|
155
|
+
"healthcheck exec probe (#{healthcheck.exec})"
|
|
156
|
+
when :docker_options
|
|
157
|
+
"docker healthcheck (options: health-cmd)"
|
|
158
|
+
else
|
|
159
|
+
"NONE (old container stops #{readiness_delay}s after boot)"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Whether the operator has made a readiness decision for this role at all — declared a
|
|
164
|
+
# healthcheck, hand-rolled a health-cmd option, or accepted the gap with `healthcheck: false`.
|
|
165
|
+
# Distinct from readiness_source, which reports what actually gates the deploy.
|
|
166
|
+
def readiness_gated?
|
|
167
|
+
healthcheck.present? || health_cmd_option? || healthcheck_disabled?
|
|
168
|
+
end
|
|
169
|
+
|
|
82
170
|
def stop_args
|
|
83
171
|
# When deploying with the proxy, kamal-proxy will drain request before returning so we don't need to wait.
|
|
84
172
|
timeout = stop_timeout || (running_proxy? ? nil : config.drain_timeout)
|
|
@@ -90,6 +178,13 @@ class Kamal::Configuration::Role
|
|
|
90
178
|
specializations["stop_timeout"] || config.stop_timeout
|
|
91
179
|
end
|
|
92
180
|
|
|
181
|
+
# How long a role that has no healthcheck must merely keep running before the deploy
|
|
182
|
+
# accepts it. Role-specialized so a role that legitimately opts out can be tuned
|
|
183
|
+
# without slowing every other role down.
|
|
184
|
+
def readiness_delay
|
|
185
|
+
specializations["readiness_delay"] || config.readiness_delay
|
|
186
|
+
end
|
|
187
|
+
|
|
93
188
|
def env(host)
|
|
94
189
|
@envs ||= {}
|
|
95
190
|
@envs[host] ||= [ config.env, specialized_env, *env_tags(host).map(&:env) ].reduce(:merge)
|
|
@@ -230,6 +325,14 @@ class Kamal::Configuration::Role
|
|
|
230
325
|
docker_options.find { |key, _| key.to_s == "restart" }&.last
|
|
231
326
|
end
|
|
232
327
|
|
|
328
|
+
def health_cmd_option?
|
|
329
|
+
docker_options.any? { |key, _| key.to_s == "health-cmd" }
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def healthcheck_disabled?
|
|
333
|
+
specializations["healthcheck"] == false
|
|
334
|
+
end
|
|
335
|
+
|
|
233
336
|
def custom_labels
|
|
234
337
|
Hash.new.tap do |labels|
|
|
235
338
|
labels.merge!(config.labels) if config.labels.present?
|