dash 3.2.0 → 4.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/README.md +1 -1
- data/bin/dash +2 -2
- data/lib/{kamal → dash}/cli/accessory.rb +24 -24
- data/lib/dash/cli/alias/command.rb +10 -0
- data/lib/{kamal → dash}/cli/app/assets.rb +2 -2
- data/lib/{kamal → dash}/cli/app/boot.rb +16 -16
- data/lib/{kamal → dash}/cli/app/error_pages.rb +6 -6
- data/lib/{kamal → dash}/cli/app/rollout_boot.rb +6 -6
- data/lib/{kamal → dash}/cli/app/ssl_certificates.rb +3 -3
- data/lib/{kamal → dash}/cli/app.rb +87 -87
- data/lib/{kamal → dash}/cli/base.rb +72 -48
- data/lib/dash/cli/build/clone.rb +59 -0
- data/lib/{kamal → dash}/cli/build/port_forwarding.rb +1 -1
- data/lib/{kamal → dash}/cli/build.rb +45 -45
- data/lib/{kamal → dash}/cli/doctor/config_checks.rb +3 -3
- data/lib/{kamal → dash}/cli/doctor/endpoint_checks.rb +26 -8
- data/lib/{kamal → dash}/cli/doctor/host_checks.rb +22 -22
- data/lib/{kamal → dash}/cli/doctor.rb +9 -9
- data/lib/{kamal → dash}/cli/healthcheck/barrier.rb +2 -2
- data/lib/{kamal → dash}/cli/healthcheck/drift_error.rb +2 -2
- data/lib/dash/cli/healthcheck/error.rb +2 -0
- data/lib/{kamal → dash}/cli/healthcheck/poller.rb +7 -7
- data/lib/{kamal → dash}/cli/lock.rb +1 -1
- data/lib/dash/cli/main/migrate.rb +77 -0
- data/lib/{kamal → dash}/cli/main.rb +82 -71
- data/lib/{kamal → dash}/cli/proxy/drift.rb +3 -3
- data/lib/dash/cli/proxy/legacy_rename.rb +58 -0
- data/lib/{kamal → dash}/cli/proxy/loadbalancer_claim.rb +3 -3
- data/lib/{kamal → dash}/cli/proxy/loadbalancer_reboot.rb +23 -23
- data/lib/{kamal → dash}/cli/proxy/reboot.rb +21 -21
- data/lib/{kamal → dash}/cli/proxy.rb +178 -162
- data/lib/{kamal → dash}/cli/prune.rb +10 -10
- data/lib/{kamal → dash}/cli/registry.rb +11 -11
- data/lib/{kamal → dash}/cli/secrets.rb +3 -3
- data/lib/{kamal → dash}/cli/server.rb +14 -14
- data/lib/{kamal → dash}/cli/templates/deploy.yml +4 -4
- data/lib/dash/cli/templates/sample_hooks/docker-setup.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/post-app-stop.sample +9 -0
- data/lib/dash/cli/templates/sample_hooks/post-deploy.sample +14 -0
- data/lib/dash/cli/templates/sample_hooks/post-proxy-deploy.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-app-stop.sample +2 -2
- data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-build.sample +8 -8
- data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-connect.sample +8 -8
- data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-deploy.sample +9 -9
- data/lib/dash/cli/templates/sample_hooks/pre-proxy-deploy.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
- data/lib/{kamal → dash}/cli/templates/secrets +6 -6
- data/lib/{kamal → dash}/cli.rb +2 -2
- data/lib/{kamal → dash}/commander/specifics.rb +2 -2
- data/lib/{kamal → dash}/commander.rb +32 -24
- data/lib/{kamal → dash}/commands/accessory/proxy.rb +2 -2
- data/lib/{kamal → dash}/commands/accessory.rb +2 -2
- data/lib/{kamal → dash}/commands/app/assets.rb +1 -1
- data/lib/{kamal → dash}/commands/app/containers.rb +1 -1
- data/lib/{kamal → dash}/commands/app/error_pages.rb +2 -2
- data/lib/{kamal → dash}/commands/app/execution.rb +2 -2
- data/lib/{kamal → dash}/commands/app/images.rb +1 -1
- data/lib/{kamal → dash}/commands/app/logging.rb +1 -1
- data/lib/{kamal → dash}/commands/app/proxy.rb +2 -2
- data/lib/{kamal → dash}/commands/app.rb +2 -2
- data/lib/{kamal → dash}/commands/auditor.rb +3 -7
- data/lib/{kamal → dash}/commands/base.rb +39 -3
- data/lib/{kamal → dash}/commands/builder/base.rb +2 -2
- data/lib/{kamal → dash}/commands/builder/clone.rb +3 -3
- data/lib/{kamal → dash}/commands/builder/cloud.rb +1 -1
- data/lib/{kamal → dash}/commands/builder/hybrid.rb +1 -1
- data/lib/{kamal → dash}/commands/builder/local.rb +1 -1
- data/lib/{kamal → dash}/commands/builder/pack.rb +1 -1
- data/lib/{kamal → dash}/commands/builder/remote.rb +1 -1
- data/lib/{kamal → dash}/commands/builder.rb +7 -7
- data/lib/dash/commands/docker.rb +89 -0
- data/lib/{kamal → dash}/commands/hook.rb +1 -1
- data/lib/{kamal → dash}/commands/loadbalancer.rb +55 -24
- data/lib/{kamal → dash}/commands/lock.rb +3 -3
- data/lib/{kamal → dash}/commands/proxy/cert_transfer.rb +6 -6
- data/lib/dash/commands/proxy.rb +375 -0
- data/lib/{kamal → dash}/commands/prune.rb +2 -2
- data/lib/dash/commands/registry.rb +44 -0
- data/lib/{kamal → dash}/commands/server.rb +1 -5
- data/lib/dash/commands.rb +2 -0
- data/lib/{kamal → dash}/configuration/accessory.rb +13 -13
- data/lib/{kamal → dash}/configuration/alias.rb +3 -3
- data/lib/{kamal → dash}/configuration/boot.rb +2 -2
- data/lib/{kamal → dash}/configuration/builder.rb +7 -7
- data/lib/{kamal → dash}/configuration/docs/accessory.yml +3 -3
- data/lib/{kamal → dash}/configuration/docs/builder.yml +3 -3
- data/lib/{kamal → dash}/configuration/docs/configuration.yml +13 -6
- data/lib/{kamal → dash}/configuration/docs/env.yml +10 -10
- data/lib/{kamal → dash}/configuration/docs/proxy.yml +68 -45
- data/lib/{kamal → dash}/configuration/docs/registry.yml +5 -5
- data/lib/{kamal → dash}/configuration/env/tag.rb +2 -2
- data/lib/{kamal → dash}/configuration/env.rb +5 -5
- data/lib/{kamal → dash}/configuration/loadbalancer.rb +5 -5
- data/lib/{kamal → dash}/configuration/logging.rb +3 -3
- data/lib/{kamal → dash}/configuration/output.rb +4 -4
- data/lib/{kamal → dash}/configuration/proxy/acme.rb +9 -8
- data/lib/{kamal → dash}/configuration/proxy/boot.rb +9 -11
- data/lib/{kamal → dash}/configuration/proxy/run.rb +20 -20
- data/lib/{kamal → dash}/configuration/proxy.rb +51 -29
- data/lib/{kamal → dash}/configuration/registry.rb +3 -3
- data/lib/{kamal → dash}/configuration/role/healthcheck.rb +3 -3
- data/lib/{kamal → dash}/configuration/role.rb +14 -14
- data/lib/{kamal → dash}/configuration/servers.rb +4 -4
- data/lib/{kamal → dash}/configuration/ssh.rb +2 -2
- data/lib/{kamal → dash}/configuration/sshkit.rb +2 -2
- data/lib/{kamal → dash}/configuration/validation.rb +2 -2
- data/lib/{kamal → dash}/configuration/validator/accessory.rb +1 -1
- data/lib/{kamal → dash}/configuration/validator/alias.rb +2 -2
- data/lib/{kamal → dash}/configuration/validator/builder.rb +1 -1
- data/lib/dash/configuration/validator/configuration.rb +6 -0
- data/lib/{kamal → dash}/configuration/validator/env.rb +2 -2
- data/lib/{kamal → dash}/configuration/validator/proxy.rb +31 -31
- data/lib/{kamal → dash}/configuration/validator/registry.rb +1 -1
- data/lib/{kamal → dash}/configuration/validator/role.rb +1 -1
- data/lib/{kamal → dash}/configuration/validator/servers.rb +1 -1
- data/lib/{kamal → dash}/configuration/validator.rb +4 -4
- data/lib/{kamal → dash}/configuration/volume.rb +2 -2
- data/lib/{kamal → dash}/configuration.rb +47 -37
- data/lib/{kamal → dash}/docker.rb +1 -1
- data/lib/{kamal → dash}/env_file.rb +1 -1
- data/lib/{kamal → dash}/git.rb +1 -1
- data/lib/{kamal → dash}/otel_shipper.rb +3 -3
- data/lib/{kamal → dash}/output/base_logger.rb +1 -1
- data/lib/{kamal → dash}/output/file_logger.rb +1 -1
- data/lib/{kamal → dash}/output/formatter.rb +1 -1
- data/lib/{kamal → dash}/output/otel_logger.rb +3 -3
- data/lib/dash/project_directory.rb +28 -0
- data/lib/{kamal → dash}/secrets/adapters/aws_secrets_manager.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/base.rb +2 -2
- data/lib/{kamal → dash}/secrets/adapters/bitwarden.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/bitwarden_secrets_manager.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/doppler.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/enpass.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/gcp_secret_manager.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/last_pass.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/one_password.rb +2 -2
- data/lib/{kamal → dash}/secrets/adapters/passbolt.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters/test.rb +1 -1
- data/lib/{kamal → dash}/secrets/adapters.rb +2 -2
- data/lib/{kamal → dash}/secrets/dotenv/inline_command_substitution.rb +2 -2
- data/lib/{kamal → dash}/secrets.rb +6 -6
- data/lib/{kamal → dash}/tags.rb +8 -3
- data/lib/{kamal → dash}/utils/sensitive.rb +1 -1
- data/lib/{kamal → dash}/utils.rb +16 -6
- data/lib/dash/version.rb +3 -0
- data/lib/{kamal.rb → dash.rb} +4 -4
- metadata +157 -154
- data/lib/kamal/cli/alias/command.rb +0 -10
- data/lib/kamal/cli/build/clone.rb +0 -59
- data/lib/kamal/cli/healthcheck/error.rb +0 -2
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/post-app-stop.sample +0 -9
- data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +0 -14
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-deploy.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-deploy.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +0 -3
- data/lib/kamal/commands/docker.rb +0 -55
- data/lib/kamal/commands/proxy.rb +0 -266
- data/lib/kamal/commands/registry.rb +0 -38
- data/lib/kamal/commands.rb +0 -2
- data/lib/kamal/configuration/validator/configuration.rb +0 -6
- data/lib/kamal/version.rb +0 -3
- /data/lib/{kamal → dash}/configuration/docs/alias.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/boot.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/logging.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/output.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/role.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/servers.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/ssh.yml +0 -0
- /data/lib/{kamal → dash}/configuration/docs/sshkit.yml +0 -0
- /data/lib/{kamal → dash}/sshkit_with_ext.rb +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Dash::Configuration::Validator::Env < Dash::Configuration::Validator
|
|
2
2
|
SPECIAL_KEYS = [ "clear", "secret", "tags" ]
|
|
3
3
|
|
|
4
4
|
def validate!
|
|
@@ -39,7 +39,7 @@ class Kamal::Configuration::Validator::Env < Kamal::Configuration::Validator
|
|
|
39
39
|
with_context(tag) do
|
|
40
40
|
validate_type! value, Hash
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Dash::Configuration::Validator::Env.new(
|
|
43
43
|
value,
|
|
44
44
|
example: example["tags"].values[1],
|
|
45
45
|
context: context
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Dash::Configuration::Validator::Proxy < Dash::Configuration::Validator
|
|
2
2
|
def validate!
|
|
3
3
|
unless config.nil?
|
|
4
4
|
super
|
|
@@ -8,7 +8,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
8
8
|
# provides the hostnames at runtime.
|
|
9
9
|
# On-demand TLS joins loadbalancer and ssl_domains as a source of hostnames
|
|
10
10
|
# that only exist at handshake time - demanding a static host here would
|
|
11
|
-
# reject the one shape
|
|
11
|
+
# reject the one shape dash-proxy requires for it.
|
|
12
12
|
if config["host"].blank? && config["hosts"].blank? && config["ssl"] && config["loadbalancer"].blank? &&
|
|
13
13
|
config.dig("ssl_domains", "source").blank? && ssl_config["on_demand_url"].blank?
|
|
14
14
|
error "Must set a host to enable automatic SSL"
|
|
@@ -113,7 +113,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
-
# Same source shape as ssl_domains. The interval minimum is
|
|
116
|
+
# Same source shape as ssl_domains. The interval minimum is dash-proxy's
|
|
117
117
|
# own (MinRedirectsInterval, 10s) - it rejects a smaller one after the SSH
|
|
118
118
|
# round trip, so catch it here at config time.
|
|
119
119
|
def validate_redirects_source!(redirects_source)
|
|
@@ -132,7 +132,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
132
132
|
end
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
-
#
|
|
135
|
+
# dash-proxy only logs a warning for a DNS provider it does not recognise
|
|
136
136
|
# and then carries on with no provider at all, so the symptom is a
|
|
137
137
|
# certificate that never issues rather than a failed boot. Catch it here,
|
|
138
138
|
# before any host is contacted.
|
|
@@ -149,7 +149,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
149
149
|
validate_dns_provider_zones! provider
|
|
150
150
|
elsif provider.present? && !supported_dns_provider?(provider)
|
|
151
151
|
error "unsupported dns_provider '#{provider}'. " \
|
|
152
|
-
"Supported providers: #{
|
|
152
|
+
"Supported providers: #{Dash::Configuration::Proxy::Acme::DNS_PROVIDERS.join(", ")}"
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
end
|
|
@@ -175,17 +175,17 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
175
175
|
|
|
176
176
|
unless zone_provider.is_a?(String) && supported_dns_provider?(zone_provider)
|
|
177
177
|
error "unsupported dns_provider '#{zone_provider}' for '#{zone}'. " \
|
|
178
|
-
"Supported providers: #{
|
|
178
|
+
"Supported providers: #{Dash::Configuration::Proxy::Acme::DNS_PROVIDERS.join(", ")}"
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
def supported_dns_provider?(provider)
|
|
184
|
-
|
|
184
|
+
Dash::Configuration::Proxy::Acme::SUPPORTED_DNS_PROVIDERS.include?(provider.to_s.downcase)
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
# The whole TLS surface lives in the one `ssl` hash: certificate material,
|
|
188
|
-
# on-demand issuance and the mTLS client CA.
|
|
188
|
+
# on-demand issuance and the mTLS client CA. dash-proxy rejects the
|
|
189
189
|
# on-demand combinations outright rather than picking a winner
|
|
190
190
|
# (ServiceOptions.Validate), so there is no precedence to document - only
|
|
191
191
|
# a deploy that would fail after the SSH round-trip. Fail here.
|
|
@@ -231,13 +231,13 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
231
231
|
|
|
232
232
|
# An RFC 9110 token, which is both a valid header field name and a valid
|
|
233
233
|
# cookie name. For a header, a space or a colon would also break the
|
|
234
|
-
# '<name>: <value>' encoding
|
|
234
|
+
# '<name>: <value>' encoding dash-proxy cuts at the first colon.
|
|
235
235
|
TOKEN = /\A[!#$%&'*+\-.^_`|~0-9A-Za-z]+\z/
|
|
236
236
|
|
|
237
237
|
POOL_KEYS = %w[ max_conns max_idle_conns idle_conn_timeout dial_timeout try_duration try_interval ].freeze
|
|
238
238
|
|
|
239
239
|
# A zero is meaningful for most of these, so only negatives are refused.
|
|
240
|
-
#
|
|
240
|
+
# dash-proxy clamps them rather than failing when it reads saved state, and
|
|
241
241
|
# rejects them from a client — this is the client.
|
|
242
242
|
def validate_tuning!
|
|
243
243
|
target = config["target"] || {}
|
|
@@ -258,13 +258,13 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
258
258
|
with_context("request_timeout") { error "cannot be negative" }
|
|
259
259
|
end
|
|
260
260
|
|
|
261
|
-
# Sibling consistency:
|
|
261
|
+
# Sibling consistency: dash-proxy clamps a negative --target-timeout as
|
|
262
262
|
# silently as a negative --request-timeout.
|
|
263
263
|
if config["response_timeout"].to_f.negative?
|
|
264
264
|
with_context("response_timeout") { error "cannot be negative" }
|
|
265
265
|
end
|
|
266
266
|
|
|
267
|
-
# Both maps reach
|
|
267
|
+
# Both maps reach dash-proxy's one parsePathTimeouts, which refuses a
|
|
268
268
|
# negative duration.
|
|
269
269
|
%w[ path_response_timeouts path_request_timeouts ].each do |key|
|
|
270
270
|
with_context(key) do
|
|
@@ -278,7 +278,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
278
278
|
# Session affinity and scale-to-zero. The one rule NOT here is that sleep
|
|
279
279
|
# needs proxy/run/docker_socket: a role can carry `sleep` while the root
|
|
280
280
|
# carries the socket, and this validator runs against the role's own proxy
|
|
281
|
-
# block before it is merged.
|
|
281
|
+
# block before it is merged. Dash::Configuration checks that pairing on the
|
|
282
282
|
# merged config instead.
|
|
283
283
|
def validate_lifecycle!
|
|
284
284
|
affinity = config["session_affinity"] || {}
|
|
@@ -312,7 +312,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
312
312
|
end
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
-
#
|
|
315
|
+
# dash-proxy rejects canonical_host + on-demand TLS after the SSH round
|
|
316
316
|
# trip (canonical redirection needs a fixed host, on-demand TLS has none),
|
|
317
317
|
# and a canonical host outside the host list redirects every request to a
|
|
318
318
|
# hostname this service does not serve.
|
|
@@ -393,7 +393,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
393
393
|
end
|
|
394
394
|
|
|
395
395
|
# Go carries the request host in Request.Host rather than the header map,
|
|
396
|
-
# so
|
|
396
|
+
# so dash-proxy refuses the rule instead of silently doing nothing.
|
|
397
397
|
if direction == "request" && name.to_s.downcase == "host"
|
|
398
398
|
return error "cannot rewrite the Host header"
|
|
399
399
|
end
|
|
@@ -408,7 +408,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
408
408
|
|
|
409
409
|
# The pattern is deliberately not compiled: Go's RE2 and Ruby's Onigmo differ
|
|
410
410
|
# at the edges (Ruby rejects Go's `(?P<name>...)`), and refusing a pattern
|
|
411
|
-
#
|
|
411
|
+
# dash-proxy would have accepted is worse than finding out at deploy time.
|
|
412
412
|
def validate_path_rules!(key, redirect:)
|
|
413
413
|
Array(config[key]).each_with_index do |rule, index|
|
|
414
414
|
with_context(key) do
|
|
@@ -419,7 +419,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
419
419
|
next error "needs both from and to"
|
|
420
420
|
end
|
|
421
421
|
|
|
422
|
-
# The wire format is '<from>=<to>' and
|
|
422
|
+
# The wire format is '<from>=<to>' and dash-proxy cuts at the
|
|
423
423
|
# FIRST '=', so an '=' inside the pattern silently builds a rule
|
|
424
424
|
# for a different path.
|
|
425
425
|
if rule["from"].to_s.include?("=")
|
|
@@ -443,7 +443,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
443
443
|
end
|
|
444
444
|
end
|
|
445
445
|
|
|
446
|
-
#
|
|
446
|
+
# dash-proxy's --rate-limit is a Float64, so half a request per second is a
|
|
447
447
|
# legal rate. The docs example can only demonstrate one numeric type, and an
|
|
448
448
|
# Integer there would reject 0.5 — so the shape is checked by hand instead.
|
|
449
449
|
def validate_key_override!(key, value)
|
|
@@ -488,7 +488,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
488
488
|
end
|
|
489
489
|
|
|
490
490
|
# Rate limiting and the IP allow list are only as correct as the address they
|
|
491
|
-
# key on, so
|
|
491
|
+
# key on, so dash-proxy ties the three settings together with rules that
|
|
492
492
|
# otherwise surface only once the deploy has reached a host.
|
|
493
493
|
def validate_access_control!
|
|
494
494
|
allow_ips = Array(config["allow_ips"])
|
|
@@ -531,7 +531,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
531
531
|
error "trusted_proxies has no effect without allow_ips, deny_ips or rate_limit"
|
|
532
532
|
end
|
|
533
533
|
|
|
534
|
-
# Unconditional: even without allow_ips/rate_limit,
|
|
534
|
+
# Unconditional: even without allow_ips/rate_limit, dash-proxy rewrites
|
|
535
535
|
# the client address (and X-Forwarded-For) from this header, so honoring
|
|
536
536
|
# it from untrusted peers is a client-spoofable identity.
|
|
537
537
|
if client_ip["header"].present? && trusted_proxies.empty?
|
|
@@ -549,7 +549,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
549
549
|
end
|
|
550
550
|
end
|
|
551
551
|
|
|
552
|
-
#
|
|
552
|
+
# dash-proxy serves the health check path without an address check and
|
|
553
553
|
# without a rate limit so deploys keep working, which makes '/' a hole
|
|
554
554
|
# straight through all three features.
|
|
555
555
|
if (allow_ips.any? || deny_ips.any? || rate_limited) && config.dig("healthcheck", "path") == "/"
|
|
@@ -604,11 +604,11 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
604
604
|
end
|
|
605
605
|
|
|
606
606
|
encodings.each do |encoding|
|
|
607
|
-
canonical =
|
|
607
|
+
canonical = Dash::Configuration::Proxy::COMPRESSION_ENCODING_ALIASES.fetch(encoding.to_s, encoding.to_s)
|
|
608
608
|
|
|
609
|
-
unless
|
|
609
|
+
unless Dash::Configuration::Proxy::SUPPORTED_COMPRESSION_ENCODINGS.include?(canonical)
|
|
610
610
|
error "unsupported encoding '#{encoding}'. " \
|
|
611
|
-
"Supported encodings: #{
|
|
611
|
+
"Supported encodings: #{Dash::Configuration::Proxy::SUPPORTED_COMPRESSION_ENCODINGS.join(", ")}"
|
|
612
612
|
end
|
|
613
613
|
end
|
|
614
614
|
|
|
@@ -618,7 +618,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
618
618
|
|
|
619
619
|
Array(compress["content_types"]).each do |content_type|
|
|
620
620
|
# A main-type wildcard would match everything the proxy cannot see
|
|
621
|
-
# inside, so
|
|
621
|
+
# inside, so dash-proxy allows a wildcard only in the subtype.
|
|
622
622
|
unless content_type.to_s.match?(%r{\A[^/*\s]+/[^/\s]+\z})
|
|
623
623
|
error "content_types entry '#{content_type}' must be a media type such as text/html or text/*"
|
|
624
624
|
end
|
|
@@ -632,7 +632,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
632
632
|
REFUSED_TLS_VERSIONS = %w[ 1.0 1.1 ].freeze
|
|
633
633
|
RUN_TIMEOUTS = %w[ read_header_timeout read_timeout write_timeout idle_timeout shutdown_timeout ].freeze
|
|
634
634
|
|
|
635
|
-
#
|
|
635
|
+
# dash-proxy validates these three in preRun, so a typo does not fail the
|
|
636
636
|
# deploy - it stops the proxy container from booting at all.
|
|
637
637
|
def validate_run_server_options!(run_config)
|
|
638
638
|
with_context("run") do
|
|
@@ -656,7 +656,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
656
656
|
end
|
|
657
657
|
end
|
|
658
658
|
|
|
659
|
-
# Accepts the spellings
|
|
659
|
+
# Accepts the spellings dash-proxy's normalizeTLSVersion reduces - a `tls`
|
|
660
660
|
# or `tlsv` prefix, and `_` for `.` - so a config written for upstream is not
|
|
661
661
|
# rejected here and accepted there.
|
|
662
662
|
def validate_min_tls!(value)
|
|
@@ -673,7 +673,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
673
673
|
end
|
|
674
674
|
end
|
|
675
675
|
|
|
676
|
-
#
|
|
676
|
+
# dash-proxy reads the cache policy only when --cache is set and ignores it
|
|
677
677
|
# otherwise, so a tuned block with no `enabled` is a cache that silently
|
|
678
678
|
# never caches - this issue's own predicted first support question.
|
|
679
679
|
def validate_cache!(cache)
|
|
@@ -682,12 +682,12 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
682
682
|
with_context("cache") do
|
|
683
683
|
if (orphaned = cache.keys - [ "enabled" ]).any?
|
|
684
684
|
error "#{orphaned.first} has no effect without enabled: true - " \
|
|
685
|
-
"
|
|
685
|
+
"dash-proxy ignores the cache policy entirely when --cache is absent"
|
|
686
686
|
end
|
|
687
687
|
end
|
|
688
688
|
end
|
|
689
689
|
|
|
690
|
-
# An unsupported store is rejected in
|
|
690
|
+
# An unsupported store is rejected in dash-proxy's preRun, which means the
|
|
691
691
|
# proxy container exits at boot rather than a deploy failing. Catch it before
|
|
692
692
|
# the fleet loses its proxy.
|
|
693
693
|
def validate_cache_store!(cache)
|
|
@@ -708,7 +708,7 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
|
|
|
708
708
|
if basic_auth["username"].blank?
|
|
709
709
|
error "Missing username setting (required when basic_auth is set)"
|
|
710
710
|
elsif basic_auth["username"].to_s.include?(":")
|
|
711
|
-
#
|
|
711
|
+
# dash-proxy cuts <username>:<password> at the first colon, so a
|
|
712
712
|
# colon in the username would silently truncate it.
|
|
713
713
|
error "Invalid username: cannot contain a colon"
|
|
714
714
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Dash::Configuration::Validator
|
|
2
2
|
attr_reader :config, :example, :context
|
|
3
3
|
|
|
4
4
|
def initialize(config, example:, context:)
|
|
@@ -91,7 +91,7 @@ class Kamal::Configuration::Validator
|
|
|
91
91
|
else
|
|
92
92
|
validate_type! value, type
|
|
93
93
|
end
|
|
94
|
-
rescue
|
|
94
|
+
rescue Dash::ConfigurationError
|
|
95
95
|
type_error(Array, type)
|
|
96
96
|
end
|
|
97
97
|
|
|
@@ -187,7 +187,7 @@ class Kamal::Configuration::Validator
|
|
|
187
187
|
end
|
|
188
188
|
|
|
189
189
|
def error(message)
|
|
190
|
-
raise
|
|
190
|
+
raise Dash::ConfigurationError, "#{error_context}#{message}"
|
|
191
191
|
end
|
|
192
192
|
|
|
193
193
|
def type_error(*expected_types)
|
|
@@ -245,7 +245,7 @@ class Kamal::Configuration::Validator
|
|
|
245
245
|
validate_health_option_expansion!(options)
|
|
246
246
|
end
|
|
247
247
|
|
|
248
|
-
#
|
|
248
|
+
# Dash::Utils::DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX escapes a bare `$` but exempts
|
|
249
249
|
# `${...}`, leaving it for the deploy host's shell to expand at docker run time. Role env
|
|
250
250
|
# never reaches that shell, so `${SOME_ENV}` in a health command silently becomes empty and
|
|
251
251
|
# the container sits `starting` until deploy_timeout. Reject it where it is most likely written.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Dash::Configuration::Volume
|
|
2
2
|
attr_reader :host_path, :container_path, :options
|
|
3
|
-
delegate :argumentize, to:
|
|
3
|
+
delegate :argumentize, to: Dash::Utils
|
|
4
4
|
|
|
5
5
|
def initialize(host_path:, container_path:, options: nil)
|
|
6
6
|
@host_path = host_path
|
|
@@ -5,11 +5,15 @@ require "active_support/core_ext/hash/keys"
|
|
|
5
5
|
require "erb"
|
|
6
6
|
require "net/ssh/proxy/jump"
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class Dash::Configuration
|
|
9
9
|
HOOKS_OUTPUT_LEVELS = [ :quiet, :verbose ].freeze
|
|
10
10
|
|
|
11
|
+
# The pre-3b name of #run_directory. Referenced only by the one-shot host
|
|
12
|
+
# migration in Dash::Commands::Base; nothing reads paths under it.
|
|
13
|
+
LEGACY_RUN_DIRECTORY = ".kamal"
|
|
14
|
+
|
|
11
15
|
delegate :service, :labels, :hooks_path, to: :raw_config, allow_nil: true
|
|
12
|
-
delegate :argumentize, :optionize, to:
|
|
16
|
+
delegate :argumentize, :optionize, to: Dash::Utils
|
|
13
17
|
|
|
14
18
|
attr_reader :destination, :raw_config, :secrets
|
|
15
19
|
attr_reader :accessories, :aliases, :boot, :builder, :env, :logging, :output, :proxy, :proxy_boot, :servers, :ssh, :sshkit, :registry
|
|
@@ -18,7 +22,7 @@ class Kamal::Configuration
|
|
|
18
22
|
|
|
19
23
|
class << self
|
|
20
24
|
def create_from(config_file:, destination: nil, version: nil)
|
|
21
|
-
ENV["KAMAL_DESTINATION"] = destination
|
|
25
|
+
ENV["DASH_DESTINATION"] = ENV["KAMAL_DESTINATION"] = destination
|
|
22
26
|
|
|
23
27
|
raw_config = load_raw_config(config_file: config_file, destination: destination)
|
|
24
28
|
|
|
@@ -56,9 +60,9 @@ class Kamal::Configuration
|
|
|
56
60
|
@destination = destination
|
|
57
61
|
@declared_version = version
|
|
58
62
|
|
|
59
|
-
validate! raw_config, example: validation_yml.symbolize_keys, context: "", with:
|
|
63
|
+
validate! raw_config, example: validation_yml.symbolize_keys, context: "", with: Dash::Configuration::Validator::Configuration
|
|
60
64
|
|
|
61
|
-
@secrets =
|
|
65
|
+
@secrets = Dash::Secrets.new(destination: destination, secrets_path: secrets_path)
|
|
62
66
|
|
|
63
67
|
# Eager load config to validate it, these are first as they have dependencies later on
|
|
64
68
|
@servers = Servers.new(config: self)
|
|
@@ -292,8 +296,14 @@ class Kamal::Configuration
|
|
|
292
296
|
raw_config.stop_timeout
|
|
293
297
|
end
|
|
294
298
|
|
|
299
|
+
# Where dash keeps its per-host state - app env and assets, the proxy's
|
|
300
|
+
# options/image/run_command files and apps-config bind mount, loadbalancer
|
|
301
|
+
# service claims, deploy locks and the audit log - under the SSH user's home.
|
|
302
|
+
# Renamed from `.kamal` in stage 3b of the server artifact rename
|
|
303
|
+
# (zoolutions/dash#118); hosts still on the old name are migrated in place by
|
|
304
|
+
# Dash::Commands::Base#ensure_run_directory.
|
|
295
305
|
def run_directory
|
|
296
|
-
".
|
|
306
|
+
".dash"
|
|
297
307
|
end
|
|
298
308
|
|
|
299
309
|
def apps_directory
|
|
@@ -313,11 +323,11 @@ class Kamal::Configuration
|
|
|
313
323
|
end
|
|
314
324
|
|
|
315
325
|
def hooks_path
|
|
316
|
-
raw_config.hooks_path || "
|
|
326
|
+
raw_config.hooks_path || Dash::ProjectDirectory.join("hooks")
|
|
317
327
|
end
|
|
318
328
|
|
|
319
329
|
def secrets_path
|
|
320
|
-
raw_config.secrets_path || "
|
|
330
|
+
raw_config.secrets_path || Dash::ProjectDirectory.join("secrets")
|
|
321
331
|
end
|
|
322
332
|
|
|
323
333
|
def asset_path
|
|
@@ -379,26 +389,26 @@ class Kamal::Configuration
|
|
|
379
389
|
|
|
380
390
|
def ensure_required_keys_present
|
|
381
391
|
%i[ service registry ].each do |key|
|
|
382
|
-
raise
|
|
392
|
+
raise Dash::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
|
|
383
393
|
end
|
|
384
394
|
|
|
385
|
-
raise
|
|
395
|
+
raise Dash::ConfigurationError, "Missing required configuration for image" if image.blank?
|
|
386
396
|
|
|
387
397
|
if raw_config.servers.nil?
|
|
388
|
-
raise
|
|
398
|
+
raise Dash::ConfigurationError, "No servers or accessories specified" unless raw_config.accessories.present?
|
|
389
399
|
else
|
|
390
400
|
unless role(primary_role_name).present?
|
|
391
|
-
raise
|
|
401
|
+
raise Dash::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
|
|
392
402
|
end
|
|
393
403
|
|
|
394
404
|
if primary_role.hosts.empty?
|
|
395
|
-
raise
|
|
405
|
+
raise Dash::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
|
|
396
406
|
end
|
|
397
407
|
|
|
398
408
|
unless allow_empty_roles?
|
|
399
409
|
roles.each do |role|
|
|
400
410
|
if role.hosts.empty?
|
|
401
|
-
raise
|
|
411
|
+
raise Dash::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
|
|
402
412
|
end
|
|
403
413
|
end
|
|
404
414
|
end
|
|
@@ -408,21 +418,21 @@ class Kamal::Configuration
|
|
|
408
418
|
end
|
|
409
419
|
|
|
410
420
|
def ensure_valid_service_name
|
|
411
|
-
raise
|
|
421
|
+
raise Dash::ConfigurationError, "Service name can only include alphanumeric characters, hyphens, and underscores" unless raw_config[:service] =~ /^[a-z0-9_-]+$/i
|
|
412
422
|
|
|
413
423
|
true
|
|
414
424
|
end
|
|
415
425
|
|
|
416
426
|
def ensure_valid_kamal_version
|
|
417
|
-
if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(
|
|
418
|
-
raise
|
|
427
|
+
if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Dash::VERSION)
|
|
428
|
+
raise Dash::ConfigurationError, "Current version is #{Dash::VERSION}, minimum required is #{minimum_version}"
|
|
419
429
|
end
|
|
420
430
|
|
|
421
431
|
true
|
|
422
432
|
end
|
|
423
433
|
|
|
424
434
|
def ensure_retain_containers_valid
|
|
425
|
-
raise
|
|
435
|
+
raise Dash::ConfigurationError, "Must retain at least 1 container" if retain_containers < 1
|
|
426
436
|
|
|
427
437
|
true
|
|
428
438
|
end
|
|
@@ -431,7 +441,7 @@ class Kamal::Configuration
|
|
|
431
441
|
hooks = %w[ pre-traefik-reboot post-traefik-reboot ].select { |hook_file| File.exist?(File.join(hooks_path, hook_file)) }
|
|
432
442
|
|
|
433
443
|
if hooks.any?
|
|
434
|
-
raise
|
|
444
|
+
raise Dash::ConfigurationError, "Found #{hooks.join(", ")}, these should be renamed to (pre|post)-proxy-reboot"
|
|
435
445
|
end
|
|
436
446
|
|
|
437
447
|
true
|
|
@@ -468,7 +478,7 @@ class Kamal::Configuration
|
|
|
468
478
|
return true if offenders.empty?
|
|
469
479
|
|
|
470
480
|
warn "Host(s) #{offenders.sort.join(", ")}: proxy_protocol is enabled without proxy_protocol_allow_ips, " \
|
|
471
|
-
"so
|
|
481
|
+
"so dash-proxy honours a PROXY header from any peer that can reach the port. That header sets the client " \
|
|
472
482
|
"address `allow_ips`, `rate_limit` and the access log all use. Name the load balancers you actually run."
|
|
473
483
|
|
|
474
484
|
true
|
|
@@ -492,12 +502,12 @@ class Kamal::Configuration
|
|
|
492
502
|
|
|
493
503
|
return true if offenders.empty?
|
|
494
504
|
|
|
495
|
-
raise
|
|
496
|
-
"proxy/sleep requires proxy/run/docker_socket -
|
|
505
|
+
raise Dash::ConfigurationError, "Role(s) #{offenders.map(&:name).join(", ")}: " \
|
|
506
|
+
"proxy/sleep requires proxy/run/docker_socket - dash-proxy can only stop and start containers " \
|
|
497
507
|
"through the container runtime socket, and it is not mounted into the proxy without it"
|
|
498
508
|
end
|
|
499
509
|
|
|
500
|
-
#
|
|
510
|
+
# dash-proxy resolves a zero max_idle_conns to its default of 100
|
|
501
511
|
# (target_pool.go resolves defaults from zeros), so the one value an
|
|
502
512
|
# operator writes to mean "keep none" is the one value that cannot mean it.
|
|
503
513
|
# Legal, so warn rather than raise.
|
|
@@ -508,14 +518,14 @@ class Kamal::Configuration
|
|
|
508
518
|
return true if offenders.empty?
|
|
509
519
|
|
|
510
520
|
warn "Role(s) #{offenders.map(&:name).join(", ")}: target/max_idle_conns: 0 means the proxy default of 100, " \
|
|
511
|
-
"not \"keep none\" -
|
|
521
|
+
"not \"keep none\" - dash-proxy resolves its defaults from zeros. Leave it unset for the default, " \
|
|
512
522
|
"or set 1 for the practical minimum."
|
|
513
523
|
|
|
514
524
|
true
|
|
515
525
|
end
|
|
516
526
|
|
|
517
527
|
# `intercept_errors` discards the app's error body and renders the proxy's own
|
|
518
|
-
# page instead. With no pages to render,
|
|
528
|
+
# page instead. With no pages to render, dash-proxy falls back to a bare
|
|
519
529
|
# plaintext status line — so the app's error page is thrown away and replaced
|
|
520
530
|
# by the words "Bad Gateway". Legal, and almost never the intent.
|
|
521
531
|
def ensure_intercepted_errors_have_pages
|
|
@@ -525,7 +535,7 @@ class Kamal::Configuration
|
|
|
525
535
|
return true if offenders.empty?
|
|
526
536
|
|
|
527
537
|
warn "Role(s) #{offenders.map(&:name).join(", ")}: intercept_errors is set but no error_pages_path is " \
|
|
528
|
-
"configured, so
|
|
538
|
+
"configured, so dash-proxy replaces the app's error page with a bare plaintext status line. " \
|
|
529
539
|
"Set `error_pages_path:` to serve your own pages, or remove `intercept_errors` to let the app's through."
|
|
530
540
|
|
|
531
541
|
true
|
|
@@ -533,7 +543,7 @@ class Kamal::Configuration
|
|
|
533
543
|
|
|
534
544
|
# Rate limiting and IP deny rules are only as correct as the address they key
|
|
535
545
|
# on. `forward_headers: true` says something sits in front of the proxy, and
|
|
536
|
-
# without `trusted_proxies`
|
|
546
|
+
# without `trusted_proxies` dash-proxy keys on that something's address
|
|
537
547
|
# rather than the client's — so the limiter throttles the whole world as one
|
|
538
548
|
# client (or nobody), and a deny list denies nobody it was written for. Warn
|
|
539
549
|
# rather than raise: the config is legal, just almost certainly not what was
|
|
@@ -558,7 +568,7 @@ class Kamal::Configuration
|
|
|
558
568
|
|
|
559
569
|
offenders.each do |role_name, features|
|
|
560
570
|
warn "Role #{role_name}: #{features.join(" and ")} is set with forward_headers, " \
|
|
561
|
-
"but no proxy/client_ip/trusted_proxies.
|
|
571
|
+
"but no proxy/client_ip/trusted_proxies. dash-proxy will key on the address of " \
|
|
562
572
|
"whatever sits in front of it, not on the client's — so the rules apply to every " \
|
|
563
573
|
"visitor as one client, or to none of them. Declare the proxies in front with " \
|
|
564
574
|
"`client_ip: trusted_proxies:`."
|
|
@@ -577,7 +587,7 @@ class Kamal::Configuration
|
|
|
577
587
|
paced = roles.select(&:boot)
|
|
578
588
|
return true if paced.empty? || boot.parallel_roles != false
|
|
579
589
|
|
|
580
|
-
raise
|
|
590
|
+
raise Dash::ConfigurationError, "servers/#{paced.first.name}/boot cannot be combined with boot/parallel_roles: false, " \
|
|
581
591
|
"which boots each host's roles in turn and so cannot pace one role's hosts. Remove one of them"
|
|
582
592
|
end
|
|
583
593
|
|
|
@@ -602,7 +612,7 @@ class Kamal::Configuration
|
|
|
602
612
|
hosts = roles.select(&:ssl?).flat_map { |role| role.proxy.hosts }
|
|
603
613
|
duplicates = hosts.tally.filter_map { |host, count| host if count > 1 }
|
|
604
614
|
|
|
605
|
-
raise
|
|
615
|
+
raise Dash::ConfigurationError, "Different roles can't share the same host for SSL: #{duplicates.join(", ")}" if duplicates.any?
|
|
606
616
|
|
|
607
617
|
true
|
|
608
618
|
end
|
|
@@ -610,7 +620,7 @@ class Kamal::Configuration
|
|
|
610
620
|
def ensure_local_registry_remote_builder_has_ssh_url
|
|
611
621
|
if registry.local? && builder.remote?
|
|
612
622
|
unless URI(builder.remote).scheme == "ssh"
|
|
613
|
-
raise
|
|
623
|
+
raise Dash::ConfigurationError, "Local registry with remote builder requires an SSH URL (e.g., ssh://user@host)"
|
|
614
624
|
end
|
|
615
625
|
end
|
|
616
626
|
|
|
@@ -621,7 +631,7 @@ class Kamal::Configuration
|
|
|
621
631
|
all_hosts.each do |host|
|
|
622
632
|
run_configs = proxy_runs(host)
|
|
623
633
|
if run_configs.uniq.size > 1
|
|
624
|
-
raise
|
|
634
|
+
raise Dash::ConfigurationError, "Conflicting proxy run configurations for host #{host}"
|
|
625
635
|
end
|
|
626
636
|
end
|
|
627
637
|
end
|
|
@@ -634,7 +644,7 @@ class Kamal::Configuration
|
|
|
634
644
|
# accessories-only configuration has nothing to run it on.
|
|
635
645
|
def ensure_valid_loadbalancer
|
|
636
646
|
if proxy.loadbalancer == true && primary_role.nil?
|
|
637
|
-
raise
|
|
647
|
+
raise Dash::ConfigurationError, "proxy/loadbalancer: can't be enabled without servers"
|
|
638
648
|
end
|
|
639
649
|
|
|
640
650
|
true
|
|
@@ -656,16 +666,16 @@ class Kamal::Configuration
|
|
|
656
666
|
def validate_hooks_output_level!(level, hook = nil)
|
|
657
667
|
return if HOOKS_OUTPUT_LEVELS.include?(level)
|
|
658
668
|
context = hook ? " for hook '#{hook}'" : ""
|
|
659
|
-
raise
|
|
669
|
+
raise Dash::ConfigurationError, "Invalid hooks_output '#{level}'#{context}, must be one of: #{HOOKS_OUTPUT_LEVELS.join(', ')}"
|
|
660
670
|
end
|
|
661
671
|
|
|
662
672
|
def git_version
|
|
663
673
|
@git_version ||=
|
|
664
|
-
if
|
|
665
|
-
if
|
|
674
|
+
if Dash::Git.used?
|
|
675
|
+
if Dash::Git.uncommitted_changes.present? && !builder.git_clone?
|
|
666
676
|
uncommitted_suffix = "_uncommitted_#{SecureRandom.hex(8)}"
|
|
667
677
|
end
|
|
668
|
-
[
|
|
678
|
+
[ Dash::Git.revision, uncommitted_suffix ].compact.join
|
|
669
679
|
else
|
|
670
680
|
raise "Can't use commit hash as version, no git repository found in #{Dir.pwd}"
|
|
671
681
|
end
|
data/lib/{kamal → dash}/git.rb
RENAMED
|
@@ -4,7 +4,7 @@ require "json"
|
|
|
4
4
|
require "securerandom"
|
|
5
5
|
require "uri"
|
|
6
6
|
|
|
7
|
-
class
|
|
7
|
+
class Dash::OtelShipper
|
|
8
8
|
BATCH_SIZE = 100
|
|
9
9
|
FLUSH_INTERVAL = 5.seconds
|
|
10
10
|
|
|
@@ -38,7 +38,7 @@ class Kamal::OtelShipper
|
|
|
38
38
|
@run_id = SecureRandom.uuid
|
|
39
39
|
@resource_attributes = [
|
|
40
40
|
{ key: "service.name", value: { stringValue: "kamal" } },
|
|
41
|
-
{ key: "service.version", value: { stringValue:
|
|
41
|
+
{ key: "service.version", value: { stringValue: Dash::VERSION } },
|
|
42
42
|
{ key: "kamal.run_id", value: { stringValue: @run_id } },
|
|
43
43
|
*tags.tags.map do |key, value|
|
|
44
44
|
otel_key = OTEL_ATTRIBUTE_KEYS.fetch(key, "kamal.#{key}")
|
|
@@ -156,7 +156,7 @@ class Kamal::OtelShipper
|
|
|
156
156
|
payload = {
|
|
157
157
|
resourceLogs: [ {
|
|
158
158
|
resource: { attributes: @resource_attributes },
|
|
159
|
-
scopeLogs: [ { scope: { name: "kamal", version:
|
|
159
|
+
scopeLogs: [ { scope: { name: "kamal", version: Dash::VERSION }, logRecords: records } ]
|
|
160
160
|
} ]
|
|
161
161
|
}
|
|
162
162
|
|