Class: Kamal::Configuration::Role
- Inherits:
-
Object
- Object
- Kamal::Configuration::Role
- Includes:
- Validation
- Defined in:
- lib/kamal/configuration/role.rb
Defined Under Namespace
Classes: Healthcheck
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#healthcheck ⇒ Object
readonly
Returns the value of attribute healthcheck.
-
#name ⇒ Object
(also: #to_s)
readonly
Returns the value of attribute name.
-
#specialized_env ⇒ Object
readonly
Returns the value of attribute specialized_env.
-
#specialized_logging ⇒ Object
readonly
Returns the value of attribute specialized_logging.
-
#specialized_proxy ⇒ Object
readonly
Returns the value of attribute specialized_proxy.
Instance Method Summary collapse
- #asset_extracted_directory(version = config.version) ⇒ Object
- #asset_path ⇒ Object
- #asset_path_options ⇒ Object
- #asset_volume(version = config.version) ⇒ Object
- #asset_volume_args ⇒ Object
- #asset_volume_directory(version = config.version) ⇒ Object
- #assets? ⇒ Boolean
-
#boot ⇒ Object
nil unless the role paces its own hosts.
-
#boot_runner_options(hosts) ⇒ Object
hostsis what on_roles is about to pace —role.hosts & the run's hosts, so --roles/--hosts have already narrowed it. - #cmd ⇒ Object
- #container_name(version = nil) ⇒ Object
- #container_prefix ⇒ Object
- #ensure_one_host_for_ssl ⇒ Object
- #env(host) ⇒ Object
- #env_args(host) ⇒ Object
- #env_directory ⇒ Object
- #env_tags(host) ⇒ Object
-
#healthcheck_args ⇒ Object
Kept out of option_args on purpose: Commands::App::Execution splats those into one-shot
kamal app execcontainers, which must not inherit a service healthcheck. - #hosts ⇒ Object
-
#hosts_with_tag(tag) ⇒ Object
The role's own hosts carrying
tagin deploy.yml. -
#initialize(name, config:) ⇒ Role
constructor
A new instance of Role.
- #label_args ⇒ Object
- #labels ⇒ Object
- #logging ⇒ Object
- #logging_args ⇒ Object
- #option_args ⇒ Object
- #primary? ⇒ Boolean
- #primary_host ⇒ Object
- #proxy ⇒ Object
-
#readiness_delay ⇒ Object
How long a role that has no healthcheck must merely keep running before the deploy accepts it.
-
#readiness_description ⇒ Object
One-line rendering of readiness_source, shared by the deploy banner and
kamal doctorso both name the same gate the same way. -
#readiness_gated? ⇒ Boolean
Whether the operator has made a readiness decision for this role at all — declared a healthcheck, hand-rolled a health-cmd option, or accepted the gap with
healthcheck: false. -
#readiness_source ⇒ Object
Where a deploy of this role actually waits for readiness before stopping the old container.
- #restart_policy ⇒ Object
- #running_proxy? ⇒ Boolean
- #secrets_io(host) ⇒ Object
- #secrets_path ⇒ Object
- #ssl? ⇒ Boolean
- #stop_args ⇒ Object
- #stop_timeout ⇒ Object
Methods included from Validation
Constructor Details
#initialize(name, config:) ⇒ Role
Returns a new instance of Role.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/kamal/configuration/role.rb', line 10 def initialize(name, config:) @name, @config = name.inquiry, config validate! \ role_config, example: validation_yml["servers"]["workers"], context: "servers/#{name}", with: Kamal::Configuration::Validator::Role @specialized_env = Kamal::Configuration::Env.new \ config: specializations.fetch("env", {}), secrets: config.secrets, context: "servers/#{name}/env" @specialized_logging = Kamal::Configuration::Logging.new \ logging_config: specializations.fetch("logging", {}), context: "servers/#{name}/logging" # `healthcheck: false` is an opt-out, not a healthcheck — it leaves @healthcheck nil. if healthcheck_config = specializations["healthcheck"] @healthcheck = Kamal::Configuration::Role::Healthcheck.new \ healthcheck_config: healthcheck_config, context: "servers/#{name}/healthcheck" end initialize_specialized_proxy end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def config @config end |
#healthcheck ⇒ Object (readonly)
Returns the value of attribute healthcheck.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def healthcheck @healthcheck end |
#name ⇒ Object (readonly) Also known as: to_s
Returns the value of attribute name.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def name @name end |
#specialized_env ⇒ Object (readonly)
Returns the value of attribute specialized_env.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def specialized_env @specialized_env end |
#specialized_logging ⇒ Object (readonly)
Returns the value of attribute specialized_logging.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def specialized_logging @specialized_logging end |
#specialized_proxy ⇒ Object (readonly)
Returns the value of attribute specialized_proxy.
6 7 8 |
# File 'lib/kamal/configuration/role.rb', line 6 def specialized_proxy @specialized_proxy end |
Instance Method Details
#asset_extracted_directory(version = config.version) ⇒ Object
247 248 249 |
# File 'lib/kamal/configuration/role.rb', line 247 def asset_extracted_directory(version = config.version) File.join config.assets_directory, "extracted", [ name, version ].join("-") end |
#asset_path ⇒ Object
228 229 230 |
# File 'lib/kamal/configuration/role.rb', line 228 def asset_path asset_path_config&.dig(0) end |
#asset_path_options ⇒ Object
243 244 245 |
# File 'lib/kamal/configuration/role.rb', line 243 def asset_path_config&.dig(1) end |
#asset_volume(version = config.version) ⇒ Object
236 237 238 239 240 241 |
# File 'lib/kamal/configuration/role.rb', line 236 def asset_volume(version = config.version) if assets? Kamal::Configuration::Volume.new \ host_path: asset_volume_directory(version), container_path: asset_path, options: end end |
#asset_volume_args ⇒ Object
209 210 211 |
# File 'lib/kamal/configuration/role.rb', line 209 def asset_volume_args asset_volume&.docker_args end |
#asset_volume_directory(version = config.version) ⇒ Object
251 252 253 |
# File 'lib/kamal/configuration/role.rb', line 251 def asset_volume_directory(version = config.version) File.join config.assets_directory, "volumes", [ name, version ].join("-") end |
#assets? ⇒ Boolean
232 233 234 |
# File 'lib/kamal/configuration/role.rb', line 232 def assets? asset_path.present? && running_proxy? end |
#boot ⇒ Object
nil unless the role paces its own hosts. Deliberately not falling back to the global
boot: that limit is already spent slicing the cross-role host list in
Cli::App#host_boot_groups, and handing it to the per-role runner as well would sleep
boot.wait a second time inside every group.
Built on first read rather than in the initializer — Servers.new constructs every Role before Kamal::Configuration#initialize has finished assigning its own collaborators.
98 99 100 101 102 103 104 105 106 |
# File 'lib/kamal/configuration/role.rb', line 98 def boot return @boot if defined?(@boot) @boot = if (boot_config = specializations["boot"]) Kamal::Configuration::Boot.new \ config: config, boot_config: boot_config, context: "servers/#{name}/boot" end end |
#boot_runner_options(hosts) ⇒ Object
hosts is what on_roles is about to pace — role.hosts & the run's hosts, so
--roles/--hosts have already narrowed it. A percentage limit has to count that, not
the role's configured hosts.
111 112 113 |
# File 'lib/kamal/configuration/role.rb', line 111 def (hosts) boot&.(hosts) || {} end |
#cmd ⇒ Object
57 58 59 |
# File 'lib/kamal/configuration/role.rb', line 57 def cmd specializations["cmd"] end |
#container_name(version = nil) ⇒ Object
219 220 221 |
# File 'lib/kamal/configuration/role.rb', line 219 def container_name(version = nil) [ container_prefix, version || config.version ].compact.join("-") end |
#container_prefix ⇒ Object
223 224 225 |
# File 'lib/kamal/configuration/role.rb', line 223 def container_prefix [ config.service, name, config.destination ].compact.join("-") end |
#ensure_one_host_for_ssl ⇒ Object
255 256 257 258 259 260 |
# File 'lib/kamal/configuration/role.rb', line 255 def ensure_one_host_for_ssl # Skip SSL validation when a loadbalancer is present or custom certificates are provided if running_proxy? && proxy.ssl? && hosts.size > 1 && !proxy.loadbalancer.present? && !proxy.custom_ssl_certificate? raise Kamal::ConfigurationError, "SSL is only supported on a single server unless you provide custom certificates or configure a loadbalancer, found #{hosts.size} servers for role #{name}" end end |
#env(host) ⇒ Object
188 189 190 191 |
# File 'lib/kamal/configuration/role.rb', line 188 def env(host) @envs ||= {} @envs[host] ||= [ config.env, specialized_env, *(host).map(&:env) ].reduce(:merge) end |
#env_args(host) ⇒ Object
193 194 195 |
# File 'lib/kamal/configuration/role.rb', line 193 def env_args(host) [ *env(host).clear_args, *argumentize("--env-file", secrets_path) ] end |
#env_directory ⇒ Object
197 198 199 |
# File 'lib/kamal/configuration/role.rb', line 197 def env_directory File.join(config.env_directory, "roles") end |
#env_tags(host) ⇒ Object
45 46 47 |
# File 'lib/kamal/configuration/role.rb', line 45 def (host) tagged_hosts.fetch(host).collect { |tag| config.env_tag(tag) }.compact end |
#healthcheck_args ⇒ Object
Kept out of option_args on purpose: Commands::App::Execution splats those into
one-shot kamal app exec containers, which must not inherit a service healthcheck.
83 84 85 |
# File 'lib/kamal/configuration/role.rb', line 83 def healthcheck_args healthcheck&.args || [] end |
#hosts ⇒ Object
41 42 43 |
# File 'lib/kamal/configuration/role.rb', line 41 def hosts tagged_hosts.keys end |
#hosts_with_tag(tag) ⇒ Object
The role's own hosts carrying tag in deploy.yml. Accessory tag:/tags: resolution
comes through here rather than re-walking raw_config.servers, so it inherits
extract_hosts_from_config's handling of every legal role shape — bare list, hosts:
mapping, and the top-level servers: array.
53 54 55 |
# File 'lib/kamal/configuration/role.rb', line 53 def hosts_with_tag(tag) tagged_hosts.select { |_host, | .include?(tag) }.keys end |
#label_args ⇒ Object
73 74 75 |
# File 'lib/kamal/configuration/role.rb', line 73 def label_args argumentize "--label", labels end |
#labels ⇒ Object
69 70 71 |
# File 'lib/kamal/configuration/role.rb', line 69 def labels default_labels.merge(custom_labels) end |
#logging ⇒ Object
87 88 89 |
# File 'lib/kamal/configuration/role.rb', line 87 def logging @logging ||= config.logging.merge(specialized_logging) end |
#logging_args ⇒ Object
77 78 79 |
# File 'lib/kamal/configuration/role.rb', line 77 def logging_args logging.args end |
#option_args ⇒ Object
61 62 63 |
# File 'lib/kamal/configuration/role.rb', line 61 def option_args optionize .reject { |key, _| key.to_s == "restart" } end |
#primary? ⇒ Boolean
214 215 216 |
# File 'lib/kamal/configuration/role.rb', line 214 def primary? name == @config.primary_role_name end |
#primary_host ⇒ Object
37 38 39 |
# File 'lib/kamal/configuration/role.rb', line 37 def primary_host hosts.first end |
#proxy ⇒ Object
115 116 117 |
# File 'lib/kamal/configuration/role.rb', line 115 def proxy @proxy ||= specialized_proxy.merge(config.proxy) if running_proxy? end |
#readiness_delay ⇒ Object
How long a role that has no healthcheck must merely keep running before the deploy accepts it. Role-specialized so a role that legitimately opts out can be tuned without slowing every other role down.
184 185 186 |
# File 'lib/kamal/configuration/role.rb', line 184 def readiness_delay specializations["readiness_delay"] || config.readiness_delay end |
#readiness_description ⇒ Object
One-line rendering of readiness_source, shared by the deploy banner and kamal doctor
so both name the same gate the same way.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/kamal/configuration/role.rb', line 148 def readiness_description case readiness_source when :proxy [ "kamal-proxy health check", proxy.healthcheck_path ].compact.join(" ") when :healthcheck healthcheck.port ? "healthcheck #{healthcheck.path}:#{healthcheck.port}" : "healthcheck (custom cmd)" when :healthcheck_exec "healthcheck exec probe (#{healthcheck.exec})" when :docker_options "docker healthcheck (options: health-cmd)" else "NONE (old container stops #{readiness_delay}s after boot)" end end |
#readiness_gated? ⇒ Boolean
Whether the operator has made a readiness decision for this role at all — declared a
healthcheck, hand-rolled a health-cmd option, or accepted the gap with healthcheck: false.
Distinct from readiness_source, which reports what actually gates the deploy.
166 167 168 |
# File 'lib/kamal/configuration/role.rb', line 166 def readiness_gated? healthcheck.present? || health_cmd_option? || healthcheck_disabled? end |
#readiness_source ⇒ Object
Where a deploy of this role actually waits for readiness before stopping the
old container. Without a proxy or a docker healthcheck, Healthcheck::Poller
only sees .State.Status, so staying running for the readiness delay is
the whole gate. :healthcheck_exec is the odd one out: the container declares no
docker healthcheck, the deploy host polls the probe itself.
132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/kamal/configuration/role.rb', line 132 def readiness_source if running_proxy? :proxy elsif healthcheck&.exec? :healthcheck_exec elsif healthcheck :healthcheck elsif health_cmd_option? :docker_options else :none end end |
#restart_policy ⇒ Object
65 66 67 |
# File 'lib/kamal/configuration/role.rb', line 65 def restart_policy restart_policy_option || "unless-stopped" end |
#running_proxy? ⇒ Boolean
119 120 121 |
# File 'lib/kamal/configuration/role.rb', line 119 def running_proxy? @running_proxy end |
#secrets_io(host) ⇒ Object
201 202 203 |
# File 'lib/kamal/configuration/role.rb', line 201 def secrets_io(host) env(host).secrets_io end |
#secrets_path ⇒ Object
205 206 207 |
# File 'lib/kamal/configuration/role.rb', line 205 def secrets_path File.join(config.env_directory, "roles", "#{name}.env") end |
#ssl? ⇒ Boolean
123 124 125 |
# File 'lib/kamal/configuration/role.rb', line 123 def ssl? running_proxy? && proxy.ssl? end |
#stop_args ⇒ Object
170 171 172 173 174 175 |
# File 'lib/kamal/configuration/role.rb', line 170 def stop_args # When deploying with the proxy, kamal-proxy will drain request before returning so we don't need to wait. timeout = stop_timeout || (running_proxy? ? nil : config.drain_timeout) [ *argumentize("-t", timeout) ] end |
#stop_timeout ⇒ Object
177 178 179 |
# File 'lib/kamal/configuration/role.rb', line 177 def stop_timeout specializations["stop_timeout"] || config.stop_timeout end |