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.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/dash +2 -2
  4. data/lib/{kamal → dash}/cli/accessory.rb +24 -24
  5. data/lib/dash/cli/alias/command.rb +10 -0
  6. data/lib/{kamal → dash}/cli/app/assets.rb +2 -2
  7. data/lib/{kamal → dash}/cli/app/boot.rb +16 -16
  8. data/lib/{kamal → dash}/cli/app/error_pages.rb +6 -6
  9. data/lib/{kamal → dash}/cli/app/rollout_boot.rb +6 -6
  10. data/lib/{kamal → dash}/cli/app/ssl_certificates.rb +3 -3
  11. data/lib/{kamal → dash}/cli/app.rb +87 -87
  12. data/lib/{kamal → dash}/cli/base.rb +72 -48
  13. data/lib/dash/cli/build/clone.rb +59 -0
  14. data/lib/{kamal → dash}/cli/build/port_forwarding.rb +1 -1
  15. data/lib/{kamal → dash}/cli/build.rb +45 -45
  16. data/lib/{kamal → dash}/cli/doctor/config_checks.rb +3 -3
  17. data/lib/{kamal → dash}/cli/doctor/endpoint_checks.rb +26 -8
  18. data/lib/{kamal → dash}/cli/doctor/host_checks.rb +22 -22
  19. data/lib/{kamal → dash}/cli/doctor.rb +9 -9
  20. data/lib/{kamal → dash}/cli/healthcheck/barrier.rb +2 -2
  21. data/lib/{kamal → dash}/cli/healthcheck/drift_error.rb +2 -2
  22. data/lib/dash/cli/healthcheck/error.rb +2 -0
  23. data/lib/{kamal → dash}/cli/healthcheck/poller.rb +7 -7
  24. data/lib/{kamal → dash}/cli/lock.rb +1 -1
  25. data/lib/dash/cli/main/migrate.rb +77 -0
  26. data/lib/{kamal → dash}/cli/main.rb +82 -71
  27. data/lib/{kamal → dash}/cli/proxy/drift.rb +3 -3
  28. data/lib/dash/cli/proxy/legacy_rename.rb +58 -0
  29. data/lib/{kamal → dash}/cli/proxy/loadbalancer_claim.rb +3 -3
  30. data/lib/{kamal → dash}/cli/proxy/loadbalancer_reboot.rb +23 -23
  31. data/lib/{kamal → dash}/cli/proxy/reboot.rb +21 -21
  32. data/lib/{kamal → dash}/cli/proxy.rb +178 -162
  33. data/lib/{kamal → dash}/cli/prune.rb +10 -10
  34. data/lib/{kamal → dash}/cli/registry.rb +11 -11
  35. data/lib/{kamal → dash}/cli/secrets.rb +3 -3
  36. data/lib/{kamal → dash}/cli/server.rb +14 -14
  37. data/lib/{kamal → dash}/cli/templates/deploy.yml +4 -4
  38. data/lib/dash/cli/templates/sample_hooks/docker-setup.sample +3 -0
  39. data/lib/dash/cli/templates/sample_hooks/post-app-boot.sample +3 -0
  40. data/lib/dash/cli/templates/sample_hooks/post-app-stop.sample +9 -0
  41. data/lib/dash/cli/templates/sample_hooks/post-deploy.sample +14 -0
  42. data/lib/dash/cli/templates/sample_hooks/post-proxy-deploy.sample +3 -0
  43. data/lib/dash/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  44. data/lib/dash/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
  45. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-app-stop.sample +2 -2
  46. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-build.sample +8 -8
  47. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-connect.sample +8 -8
  48. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-deploy.sample +9 -9
  49. data/lib/dash/cli/templates/sample_hooks/pre-proxy-deploy.sample +3 -0
  50. data/lib/dash/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
  51. data/lib/{kamal → dash}/cli/templates/secrets +6 -6
  52. data/lib/{kamal → dash}/cli.rb +2 -2
  53. data/lib/{kamal → dash}/commander/specifics.rb +2 -2
  54. data/lib/{kamal → dash}/commander.rb +32 -24
  55. data/lib/{kamal → dash}/commands/accessory/proxy.rb +2 -2
  56. data/lib/{kamal → dash}/commands/accessory.rb +2 -2
  57. data/lib/{kamal → dash}/commands/app/assets.rb +1 -1
  58. data/lib/{kamal → dash}/commands/app/containers.rb +1 -1
  59. data/lib/{kamal → dash}/commands/app/error_pages.rb +2 -2
  60. data/lib/{kamal → dash}/commands/app/execution.rb +2 -2
  61. data/lib/{kamal → dash}/commands/app/images.rb +1 -1
  62. data/lib/{kamal → dash}/commands/app/logging.rb +1 -1
  63. data/lib/{kamal → dash}/commands/app/proxy.rb +2 -2
  64. data/lib/{kamal → dash}/commands/app.rb +2 -2
  65. data/lib/{kamal → dash}/commands/auditor.rb +3 -7
  66. data/lib/{kamal → dash}/commands/base.rb +39 -3
  67. data/lib/{kamal → dash}/commands/builder/base.rb +2 -2
  68. data/lib/{kamal → dash}/commands/builder/clone.rb +3 -3
  69. data/lib/{kamal → dash}/commands/builder/cloud.rb +1 -1
  70. data/lib/{kamal → dash}/commands/builder/hybrid.rb +1 -1
  71. data/lib/{kamal → dash}/commands/builder/local.rb +1 -1
  72. data/lib/{kamal → dash}/commands/builder/pack.rb +1 -1
  73. data/lib/{kamal → dash}/commands/builder/remote.rb +1 -1
  74. data/lib/{kamal → dash}/commands/builder.rb +7 -7
  75. data/lib/dash/commands/docker.rb +89 -0
  76. data/lib/{kamal → dash}/commands/hook.rb +1 -1
  77. data/lib/{kamal → dash}/commands/loadbalancer.rb +55 -24
  78. data/lib/{kamal → dash}/commands/lock.rb +3 -3
  79. data/lib/{kamal → dash}/commands/proxy/cert_transfer.rb +6 -6
  80. data/lib/dash/commands/proxy.rb +375 -0
  81. data/lib/{kamal → dash}/commands/prune.rb +2 -2
  82. data/lib/dash/commands/registry.rb +44 -0
  83. data/lib/{kamal → dash}/commands/server.rb +1 -5
  84. data/lib/dash/commands.rb +2 -0
  85. data/lib/{kamal → dash}/configuration/accessory.rb +13 -13
  86. data/lib/{kamal → dash}/configuration/alias.rb +3 -3
  87. data/lib/{kamal → dash}/configuration/boot.rb +2 -2
  88. data/lib/{kamal → dash}/configuration/builder.rb +7 -7
  89. data/lib/{kamal → dash}/configuration/docs/accessory.yml +3 -3
  90. data/lib/{kamal → dash}/configuration/docs/builder.yml +3 -3
  91. data/lib/{kamal → dash}/configuration/docs/configuration.yml +13 -6
  92. data/lib/{kamal → dash}/configuration/docs/env.yml +10 -10
  93. data/lib/{kamal → dash}/configuration/docs/proxy.yml +68 -45
  94. data/lib/{kamal → dash}/configuration/docs/registry.yml +5 -5
  95. data/lib/{kamal → dash}/configuration/env/tag.rb +2 -2
  96. data/lib/{kamal → dash}/configuration/env.rb +5 -5
  97. data/lib/{kamal → dash}/configuration/loadbalancer.rb +5 -5
  98. data/lib/{kamal → dash}/configuration/logging.rb +3 -3
  99. data/lib/{kamal → dash}/configuration/output.rb +4 -4
  100. data/lib/{kamal → dash}/configuration/proxy/acme.rb +9 -8
  101. data/lib/{kamal → dash}/configuration/proxy/boot.rb +9 -11
  102. data/lib/{kamal → dash}/configuration/proxy/run.rb +20 -20
  103. data/lib/{kamal → dash}/configuration/proxy.rb +51 -29
  104. data/lib/{kamal → dash}/configuration/registry.rb +3 -3
  105. data/lib/{kamal → dash}/configuration/role/healthcheck.rb +3 -3
  106. data/lib/{kamal → dash}/configuration/role.rb +14 -14
  107. data/lib/{kamal → dash}/configuration/servers.rb +4 -4
  108. data/lib/{kamal → dash}/configuration/ssh.rb +2 -2
  109. data/lib/{kamal → dash}/configuration/sshkit.rb +2 -2
  110. data/lib/{kamal → dash}/configuration/validation.rb +2 -2
  111. data/lib/{kamal → dash}/configuration/validator/accessory.rb +1 -1
  112. data/lib/{kamal → dash}/configuration/validator/alias.rb +2 -2
  113. data/lib/{kamal → dash}/configuration/validator/builder.rb +1 -1
  114. data/lib/dash/configuration/validator/configuration.rb +6 -0
  115. data/lib/{kamal → dash}/configuration/validator/env.rb +2 -2
  116. data/lib/{kamal → dash}/configuration/validator/proxy.rb +31 -31
  117. data/lib/{kamal → dash}/configuration/validator/registry.rb +1 -1
  118. data/lib/{kamal → dash}/configuration/validator/role.rb +1 -1
  119. data/lib/{kamal → dash}/configuration/validator/servers.rb +1 -1
  120. data/lib/{kamal → dash}/configuration/validator.rb +4 -4
  121. data/lib/{kamal → dash}/configuration/volume.rb +2 -2
  122. data/lib/{kamal → dash}/configuration.rb +47 -37
  123. data/lib/{kamal → dash}/docker.rb +1 -1
  124. data/lib/{kamal → dash}/env_file.rb +1 -1
  125. data/lib/{kamal → dash}/git.rb +1 -1
  126. data/lib/{kamal → dash}/otel_shipper.rb +3 -3
  127. data/lib/{kamal → dash}/output/base_logger.rb +1 -1
  128. data/lib/{kamal → dash}/output/file_logger.rb +1 -1
  129. data/lib/{kamal → dash}/output/formatter.rb +1 -1
  130. data/lib/{kamal → dash}/output/otel_logger.rb +3 -3
  131. data/lib/dash/project_directory.rb +28 -0
  132. data/lib/{kamal → dash}/secrets/adapters/aws_secrets_manager.rb +1 -1
  133. data/lib/{kamal → dash}/secrets/adapters/base.rb +2 -2
  134. data/lib/{kamal → dash}/secrets/adapters/bitwarden.rb +1 -1
  135. data/lib/{kamal → dash}/secrets/adapters/bitwarden_secrets_manager.rb +1 -1
  136. data/lib/{kamal → dash}/secrets/adapters/doppler.rb +1 -1
  137. data/lib/{kamal → dash}/secrets/adapters/enpass.rb +1 -1
  138. data/lib/{kamal → dash}/secrets/adapters/gcp_secret_manager.rb +1 -1
  139. data/lib/{kamal → dash}/secrets/adapters/last_pass.rb +1 -1
  140. data/lib/{kamal → dash}/secrets/adapters/one_password.rb +2 -2
  141. data/lib/{kamal → dash}/secrets/adapters/passbolt.rb +1 -1
  142. data/lib/{kamal → dash}/secrets/adapters/test.rb +1 -1
  143. data/lib/{kamal → dash}/secrets/adapters.rb +2 -2
  144. data/lib/{kamal → dash}/secrets/dotenv/inline_command_substitution.rb +2 -2
  145. data/lib/{kamal → dash}/secrets.rb +6 -6
  146. data/lib/{kamal → dash}/tags.rb +8 -3
  147. data/lib/{kamal → dash}/utils/sensitive.rb +1 -1
  148. data/lib/{kamal → dash}/utils.rb +16 -6
  149. data/lib/dash/version.rb +3 -0
  150. data/lib/{kamal.rb → dash.rb} +4 -4
  151. metadata +157 -154
  152. data/lib/kamal/cli/alias/command.rb +0 -10
  153. data/lib/kamal/cli/build/clone.rb +0 -59
  154. data/lib/kamal/cli/healthcheck/error.rb +0 -2
  155. data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +0 -3
  156. data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +0 -3
  157. data/lib/kamal/cli/templates/sample_hooks/post-app-stop.sample +0 -9
  158. data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +0 -14
  159. data/lib/kamal/cli/templates/sample_hooks/post-proxy-deploy.sample +0 -3
  160. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +0 -3
  161. data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +0 -3
  162. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-deploy.sample +0 -3
  163. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +0 -3
  164. data/lib/kamal/commands/docker.rb +0 -55
  165. data/lib/kamal/commands/proxy.rb +0 -266
  166. data/lib/kamal/commands/registry.rb +0 -38
  167. data/lib/kamal/commands.rb +0 -2
  168. data/lib/kamal/configuration/validator/configuration.rb +0 -6
  169. data/lib/kamal/version.rb +0 -3
  170. /data/lib/{kamal → dash}/configuration/docs/alias.yml +0 -0
  171. /data/lib/{kamal → dash}/configuration/docs/boot.yml +0 -0
  172. /data/lib/{kamal → dash}/configuration/docs/logging.yml +0 -0
  173. /data/lib/{kamal → dash}/configuration/docs/output.yml +0 -0
  174. /data/lib/{kamal → dash}/configuration/docs/role.yml +0 -0
  175. /data/lib/{kamal → dash}/configuration/docs/servers.yml +0 -0
  176. /data/lib/{kamal → dash}/configuration/docs/ssh.yml +0 -0
  177. /data/lib/{kamal → dash}/configuration/docs/sshkit.yml +0 -0
  178. /data/lib/{kamal → dash}/sshkit_with_ext.rb +0 -0
@@ -1,4 +1,4 @@
1
- module Kamal::Commands::App::Images
1
+ module Dash::Commands::App::Images
2
2
  def list_images
3
3
  docker :image, :ls, config.repository
4
4
  end
@@ -1,4 +1,4 @@
1
- module Kamal::Commands::App::Logging
1
+ module Dash::Commands::App::Logging
2
2
  def logs(container_id: nil, timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
3
3
  pipe \
4
4
  container_id_command(container_id),
@@ -1,4 +1,4 @@
1
- module Kamal::Commands::App::Proxy
1
+ module Dash::Commands::App::Proxy
2
2
  delegate :container_name, to: :"config.proxy_boot", prefix: :proxy
3
3
 
4
4
  def deploy(target:)
@@ -39,6 +39,6 @@ module Kamal::Commands::App::Proxy
39
39
 
40
40
  private
41
41
  def proxy_exec(*command)
42
- docker :exec, proxy_container_name, "kamal-proxy", *command
42
+ docker :exec, proxy_container_name, "dash-proxy", *command
43
43
  end
44
44
  end
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::App < Kamal::Commands::Base
1
+ class Dash::Commands::App < Dash::Commands::Base
2
2
  include Assets, Containers, ErrorPages, Execution, Images, Logging, Proxy
3
3
 
4
4
  ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
@@ -18,7 +18,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
18
18
  "--detach",
19
19
  "--restart", role.restart_policy,
20
20
  "--name", container_name,
21
- "--network", "kamal",
21
+ "--network", "dash",
22
22
  *([ "--hostname", hostname ] if hostname),
23
23
  "--env", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
24
24
  "--env", "KAMAL_VERSION=\"#{config.version}\"",
@@ -1,6 +1,6 @@
1
- class Kamal::Commands::Auditor < Kamal::Commands::Base
1
+ class Dash::Commands::Auditor < Dash::Commands::Base
2
2
  attr_reader :details
3
- delegate :escape_shell_value, to: Kamal::Utils
3
+ delegate :escape_shell_value, to: Dash::Utils
4
4
 
5
5
  def initialize(config, **details)
6
6
  super(config)
@@ -10,7 +10,7 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
10
10
  # Runs remotely
11
11
  def record(line, **details)
12
12
  combine \
13
- make_run_directory,
13
+ ensure_run_directory,
14
14
  append([ :echo, escape_shell_value(audit_line(line, **details)) ], audit_log_file)
15
15
  end
16
16
 
@@ -29,10 +29,6 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
29
29
  tags(**self.details, **details)
30
30
  end
31
31
 
32
- def make_run_directory
33
- [ :mkdir, "-p", config.run_directory ]
34
- end
35
-
36
32
  def audit_line(line, **details)
37
33
  "#{audit_tags(**details).except(:version, :service_version, :service)} #{line}"
38
34
  end
@@ -1,6 +1,6 @@
1
- module Kamal::Commands
1
+ module Dash::Commands
2
2
  class Base
3
- delegate :sensitive, :argumentize, to: Kamal::Utils
3
+ delegate :sensitive, :argumentize, to: Dash::Utils
4
4
 
5
5
  # Prefixed onto the docker state when the container declares no healthcheck at all, so
6
6
  # "nothing is probing this container" stays distinguishable from "the probe passed" —
@@ -32,6 +32,32 @@ module Kamal::Commands
32
32
  [ :mkdir, "-p", path ]
33
33
  end
34
34
 
35
+ # Creates the run directory, renaming a pre-3b `.kamal` into place first.
36
+ #
37
+ # Lives on Base because two unlocked paths reach the run directory before
38
+ # Dash::Cli::Base#ensure_run_directory does — the auditor records "Pulled
39
+ # image" during `build:pull`, and every `mkdir -p .dash/...` underneath it
40
+ # creates the parent. If any of them made the directory with a bare mkdir,
41
+ # `.dash` would exist by the time the guard ran and the legacy tree would be
42
+ # stranded. Everything that can be first must run the same command.
43
+ #
44
+ # The migration is safe to repeat on every command:
45
+ #
46
+ # - Idempotent - once `.dash` exists the second guard is false forever.
47
+ # - Atomic - the two are siblings in the SSH user's home, so this is a
48
+ # rename within one filesystem, never a copy.
49
+ # - Invisible to running containers - a bind mount resolves to an inode,
50
+ # so the live proxy keeps serving from the renamed directory and only
51
+ # picks up the new path when it is next recreated.
52
+ #
53
+ # `test` leads deliberately: SSHKit's command map passes `if`/`test`/`time`/
54
+ # `exec` through untouched and prefixes everything else with `/usr/bin/env`.
55
+ # The trailing `|| true` keeps the exit status zero when there is nothing to
56
+ # migrate, since callers execute this with raise_on_non_zero_exit on.
57
+ def ensure_run_directory
58
+ combine migrate_legacy_run_directory, make_directory(config.run_directory)
59
+ end
60
+
35
61
  def remove_directory(path)
36
62
  [ :rm, "-r", path ]
37
63
  end
@@ -51,6 +77,16 @@ module Kamal::Commands
51
77
  end
52
78
 
53
79
  private
80
+ def migrate_legacy_run_directory
81
+ any \
82
+ combine(
83
+ [ :test, "-d", Dash::Configuration::LEGACY_RUN_DIRECTORY ],
84
+ [ :test, "!", "-e", config.run_directory ],
85
+ [ :mv, Dash::Configuration::LEGACY_RUN_DIRECTORY, config.run_directory ]
86
+ ),
87
+ [ :true ]
88
+ end
89
+
54
90
  def combine(*commands, by: "&&")
55
91
  commands
56
92
  .compact
@@ -107,7 +143,7 @@ module Kamal::Commands
107
143
  end
108
144
 
109
145
  def tags(**details)
110
- Kamal::Tags.from_config(config, **details)
146
+ Dash::Tags.from_config(config, **details)
111
147
  end
112
148
 
113
149
  def ssh_config_args
@@ -1,9 +1,9 @@
1
- class Kamal::Commands::Builder::Base < Kamal::Commands::Base
1
+ class Dash::Commands::Builder::Base < Dash::Commands::Base
2
2
  class BuilderError < StandardError; end
3
3
 
4
4
  ENDPOINT_DOCKER_HOST_INSPECT = "'{{.Endpoints.docker.Host}}'"
5
5
 
6
- delegate :argumentize, to: Kamal::Utils
6
+ delegate :argumentize, to: Dash::Utils
7
7
  delegate \
8
8
  :args, :secrets, :dockerfile, :target, :arches, :local_arches, :remote_arches, :remote,
9
9
  :pack?, :pack_builder, :pack_buildpacks,
@@ -1,4 +1,4 @@
1
- module Kamal::Commands::Builder::Clone
1
+ module Dash::Commands::Builder::Clone
2
2
  def clone
3
3
  git :clone, escaped_root, "--recurse-submodules", path: config.builder.clone_directory.shellescape
4
4
  end
@@ -7,7 +7,7 @@ module Kamal::Commands::Builder::Clone
7
7
  [
8
8
  git(:remote, "set-url", :origin, escaped_root, path: escaped_build_directory),
9
9
  git(:fetch, :origin, path: escaped_build_directory),
10
- git(:reset, "--hard", Kamal::Git.revision, path: escaped_build_directory),
10
+ git(:reset, "--hard", Dash::Git.revision, path: escaped_build_directory),
11
11
  git(:clean, "-fdx", path: escaped_build_directory),
12
12
  git(:submodule, :update, "--init", path: escaped_build_directory),
13
13
  git(:gc, "--auto", "--quiet", path: escaped_build_directory)
@@ -23,7 +23,7 @@ module Kamal::Commands::Builder::Clone
23
23
  end
24
24
 
25
25
  def escaped_root
26
- Kamal::Git.root.shellescape
26
+ Dash::Git.root.shellescape
27
27
  end
28
28
 
29
29
  def escaped_build_directory
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Builder::Cloud < Kamal::Commands::Builder::Base
1
+ class Dash::Commands::Builder::Cloud < Dash::Commands::Builder::Base
2
2
  # Expects `driver` to be of format "cloud docker-org-name/builder-name"
3
3
 
4
4
  def create
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Builder::Hybrid < Kamal::Commands::Builder::Remote
1
+ class Dash::Commands::Builder::Hybrid < Dash::Commands::Builder::Remote
2
2
  def create
3
3
  combine \
4
4
  create_local_buildx,
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
1
+ class Dash::Commands::Builder::Local < Dash::Commands::Builder::Base
2
2
  def create
3
3
  return if docker_driver?
4
4
 
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Builder::Pack < Kamal::Commands::Builder::Base
1
+ class Dash::Commands::Builder::Pack < Dash::Commands::Builder::Base
2
2
  def push(export_action = "registry", tag_as_dirty: false, no_cache: false)
3
3
  combine \
4
4
  build(tag_as_dirty: tag_as_dirty, no_cache: no_cache),
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Builder::Remote < Kamal::Commands::Builder::Base
1
+ class Dash::Commands::Builder::Remote < Dash::Commands::Builder::Base
2
2
  def create
3
3
  chain \
4
4
  create_remote_context,
@@ -1,6 +1,6 @@
1
1
  require "active_support/core_ext/string/filters"
2
2
 
3
- class Kamal::Commands::Builder < Kamal::Commands::Base
3
+ class Dash::Commands::Builder < Dash::Commands::Base
4
4
  delegate \
5
5
  :create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder,
6
6
  :validate_image, :first_mirror, :login_to_registry_locally?, :push_env,
@@ -13,7 +13,7 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
13
13
  include Clone
14
14
 
15
15
  def name
16
- target.class.to_s.remove("Kamal::Commands::Builder::").underscore.inquiry
16
+ target.class.to_s.remove("Dash::Commands::Builder::").underscore.inquiry
17
17
  end
18
18
 
19
19
  def target
@@ -33,22 +33,22 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
33
33
  end
34
34
 
35
35
  def remote
36
- @remote ||= Kamal::Commands::Builder::Remote.new(config)
36
+ @remote ||= Dash::Commands::Builder::Remote.new(config)
37
37
  end
38
38
 
39
39
  def local
40
- @local ||= Kamal::Commands::Builder::Local.new(config)
40
+ @local ||= Dash::Commands::Builder::Local.new(config)
41
41
  end
42
42
 
43
43
  def hybrid
44
- @hybrid ||= Kamal::Commands::Builder::Hybrid.new(config)
44
+ @hybrid ||= Dash::Commands::Builder::Hybrid.new(config)
45
45
  end
46
46
 
47
47
  def pack
48
- @pack ||= Kamal::Commands::Builder::Pack.new(config)
48
+ @pack ||= Dash::Commands::Builder::Pack.new(config)
49
49
  end
50
50
 
51
51
  def cloud
52
- @cloud ||= Kamal::Commands::Builder::Cloud.new(config)
52
+ @cloud ||= Dash::Commands::Builder::Cloud.new(config)
53
53
  end
54
54
  end
@@ -0,0 +1,89 @@
1
+ class Dash::Commands::Docker < Dash::Commands::Base
2
+ # Install Docker using the https://github.com/docker/docker-install convenience script.
3
+ def install
4
+ pipe get_docker, :sh
5
+ end
6
+
7
+ # Checks the Docker client version. Fails if Docker is not installed.
8
+ def installed?
9
+ docker "-v"
10
+ end
11
+
12
+ # Checks the Docker server version. Fails if Docker is not running.
13
+ def running?
14
+ docker :version
15
+ end
16
+
17
+ # Do we have superuser access to install Docker and start system services?
18
+ def superuser?
19
+ [ '[ "${EUID:-$(id -u)}" -eq 0 ] || sudo -nl usermod >/dev/null' ]
20
+ end
21
+
22
+ def root?
23
+ [ '[ "${EUID:-$(id -u)}" -eq 0 ]' ]
24
+ end
25
+
26
+ def in_docker_group?
27
+ [ 'id -nG "${USER:-$(id -un)}" | grep -qw docker' ]
28
+ end
29
+
30
+ def add_to_docker_group
31
+ [ 'sudo -n usermod -aG docker "${USER:-$(id -un)}"' ]
32
+ end
33
+
34
+ def refresh_session
35
+ [ "kill -HUP $PPID" ]
36
+ end
37
+
38
+ # Checks that an image's manifest can be fetched from its registry. Fails if it's missing or we're unauthorized.
39
+ def manifest_available?(image)
40
+ docker :manifest, :inspect, image
41
+ end
42
+
43
+ def create_network
44
+ docker :network, :create, Dash::Configuration::Proxy::NETWORK
45
+ end
46
+
47
+ # Stage 3c: docker cannot rename a network, so `dash` is created alongside
48
+ # `kamal` and everything still on the old one is joined to the new one.
49
+ #
50
+ # App containers would be replaced by the next deploy anyway; accessories are
51
+ # not, and that is the whole point — without this a renamed proxy cannot
52
+ # reach `db` or `redis`. Connecting a container that is already attached
53
+ # fails, so each connect tolerates its own failure rather than aborting the
54
+ # sweep. The old network is never removed; that is documented manual cleanup
55
+ # and stage 3d's code change.
56
+ def connect_legacy_network_containers
57
+ any \
58
+ combine(
59
+ legacy_network_exists,
60
+ pipe(legacy_network_container_names, connect_each_to_network)
61
+ ),
62
+ [ :true ]
63
+ end
64
+
65
+ private
66
+ def legacy_network_exists
67
+ docker :network, :inspect, Dash::Configuration::Proxy::LEGACY_NETWORK, ">", "/dev/null", "2>&1"
68
+ end
69
+
70
+ def legacy_network_container_names
71
+ docker :network, :inspect, Dash::Configuration::Proxy::LEGACY_NETWORK,
72
+ "--format", "'{{range .Containers}}{{.Name}}{{\"\\n\"}}{{end}}'"
73
+ end
74
+
75
+ # Already-attached containers make `network connect` fail; tolerate each
76
+ # one's failure rather than letting it abort the sweep.
77
+ def connect_each_to_network
78
+ [ :xargs, "-r", "-I{}", "sh", "-c",
79
+ "'docker network connect #{Dash::Configuration::Proxy::NETWORK} {} 2>/dev/null || true'" ]
80
+ end
81
+
82
+ def get_docker
83
+ shell \
84
+ any \
85
+ [ :curl, "-fsSL", "https://get.docker.com" ],
86
+ [ :wget, "-O -", "https://get.docker.com" ],
87
+ [ :echo, "\"exit 1\"" ]
88
+ end
89
+ end
@@ -1,4 +1,4 @@
1
- class Kamal::Commands::Hook < Kamal::Commands::Base
1
+ class Dash::Commands::Hook < Dash::Commands::Base
2
2
  def run(hook)
3
3
  [ hook_file(hook) ]
4
4
  end
@@ -1,7 +1,7 @@
1
- class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
2
- include Kamal::Commands::Proxy::CertTransfer
1
+ class Dash::Commands::Loadbalancer < Dash::Commands::Base
2
+ include Dash::Commands::Proxy::CertTransfer
3
3
 
4
- delegate :argumentize, :optionize, to: Kamal::Utils
4
+ delegate :argumentize, :optionize, to: Dash::Utils
5
5
 
6
6
  attr_reader :loadbalancer_config
7
7
 
@@ -14,11 +14,11 @@ class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
14
14
  docker \
15
15
  :run,
16
16
  "--name", container_name,
17
- "--network", "kamal",
17
+ "--network", "dash",
18
18
  "--detach",
19
19
  "--restart", "unless-stopped",
20
20
  "--label", label,
21
- "--label", "#{Kamal::Commands::Proxy::CONFIG_DIGEST_LABEL}=#{loadbalancer_config.run_config_digest}",
21
+ "--label", "#{Dash::Commands::Proxy::CONFIG_DIGEST_LABEL}=#{loadbalancer_config.run_config_digest}",
22
22
  *config_volume,
23
23
  *run_args,
24
24
  *loadbalancer_config.run.image,
@@ -38,31 +38,32 @@ class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
38
38
  end
39
39
 
40
40
  def deploy(targets: [])
41
- docker :exec, container_name, "kamal-proxy", "deploy", loadbalancer_config.config.service,
41
+ docker :exec, container_name, "dash-proxy", "deploy", loadbalancer_config.config.service,
42
42
  *loadbalancer_config.deploy_command_args(targets: targets)
43
43
  end
44
44
 
45
- def domains(subcommand)
46
- docker :exec, container_name, "kamal-proxy", "domains", subcommand
45
+ # `retry` takes a host, or --all; the rest take no arguments.
46
+ def domains(subcommand, *args)
47
+ docker :exec, container_name, "dash-proxy", "domains", subcommand, *args
47
48
  end
48
49
 
49
50
  def list(json: false)
50
- docker :exec, container_name, "kamal-proxy", :list, *("--json" if json)
51
+ docker :exec, container_name, "dash-proxy", :list, *("--json" if json)
51
52
  end
52
53
 
53
54
  # Cache policy is edge-only under load balancing (see the layering contract),
54
55
  # so the cache admin surface lives here - registered under the bare service
55
56
  # name, unlike the per-role services on the proxy hosts.
56
57
  def cache_stats(count: false, json: false)
57
- docker :exec, container_name, "kamal-proxy", :cache, :stats, *optionize({ count: count || nil, json: json || nil }.compact)
58
+ docker :exec, container_name, "dash-proxy", :cache, :stats, *optionize({ count: count || nil, json: json || nil }.compact)
58
59
  end
59
60
 
60
61
  def cache_purge(service, path_prefix: nil)
61
- docker :exec, container_name, "kamal-proxy", :cache, :purge, service, *optionize({ "path-prefix": path_prefix }.compact)
62
+ docker :exec, container_name, "dash-proxy", :cache, :purge, service, *optionize({ "path-prefix": path_prefix }.compact)
62
63
  end
63
64
 
64
65
  def config_digest
65
- docker :inspect, container_name, "--format", "'{{ index .Config.Labels \"#{Kamal::Commands::Proxy::CONFIG_DIGEST_LABEL}\" }}'"
66
+ docker :inspect, container_name, "--format", Dash::Commands::Proxy::CONFIG_DIGEST_FORMAT
66
67
  end
67
68
 
68
69
  def container_id(only_running: false)
@@ -93,16 +94,24 @@ class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
93
94
  end
94
95
 
95
96
  # Prune by the label the container was actually created with - on a shared
96
- # proxy host that is the kamal-proxy title, and pruning by the loadbalancer
97
- # title would leave the container behind for `run` to collide with.
97
+ # proxy host that is the dash-proxy title, and pruning by the loadbalancer
98
+ # title would leave the container behind for `run` to collide with. Both the
99
+ # current and the pre-rename title are pruned, so a container created before
100
+ # the rename is not left behind to collide either.
98
101
  def remove_container
99
- docker :container, :prune, "--force", "--filter", "label=#{label}"
102
+ combine \
103
+ prune_containers_titled(image_title),
104
+ prune_containers_titled(legacy_image_title)
100
105
  end
101
106
 
102
107
  # Image label filters match labels baked into the image, and the load balancer
103
- # runs the kamal-proxy image whichever host it sits on.
108
+ # runs the dash-proxy image whichever host it sits on. Both titles are matched
109
+ # so a host still carrying a pre-rename image is cleaned up too; Docker ANDs
110
+ # multiple `--filter label=` values, so that is two commands.
104
111
  def remove_image
105
- docker :image, :prune, "--all", "--force", "--filter", "label=org.opencontainers.image.title=kamal-proxy"
112
+ combine \
113
+ prune_images_titled(Dash::Configuration::Proxy::IMAGE_TITLE),
114
+ prune_images_titled(Dash::Configuration::Proxy::LEGACY_IMAGE_TITLE)
106
115
  end
107
116
 
108
117
  def ensure_directory
@@ -110,7 +119,7 @@ class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
110
119
  end
111
120
 
112
121
  # Where the proxy secrets env file lands (see Proxy::Run#secrets_path) -
113
- # the same .kamal/proxy directory the per-app proxy hosts use.
122
+ # the same .dash/proxy directory the per-app proxy hosts use.
114
123
  def ensure_proxy_directory
115
124
  make_directory loadbalancer_config.run.host_directory
116
125
  end
@@ -152,28 +161,50 @@ class Kamal::Commands::Loadbalancer < Kamal::Commands::Base
152
161
  loadbalancer_config.on_proxy_host?
153
162
  end
154
163
 
164
+ # The full `key=value` the container is created with, so `--label #{label}`
165
+ # stays correct. The prune helpers take a bare title instead.
155
166
  def label
167
+ "org.opencontainers.image.title=#{image_title}"
168
+ end
169
+
170
+ def image_title
156
171
  if on_proxy_host?
157
- "org.opencontainers.image.title=kamal-proxy"
172
+ Dash::Configuration::Proxy::IMAGE_TITLE
158
173
  else
159
- "org.opencontainers.image.title=kamal-loadbalancer"
174
+ Dash::Configuration::Proxy::LOADBALANCER_IMAGE_TITLE
160
175
  end
161
176
  end
162
177
 
163
- # kamal-proxy keeps its state under /home/kamal-proxy/.config/kamal-proxy
178
+ def legacy_image_title
179
+ if on_proxy_host?
180
+ Dash::Configuration::Proxy::LEGACY_IMAGE_TITLE
181
+ else
182
+ Dash::Configuration::Proxy::LEGACY_LOADBALANCER_IMAGE_TITLE
183
+ end
184
+ end
185
+
186
+ def prune_containers_titled(title)
187
+ docker :container, :prune, "--force", "--filter", "label=org.opencontainers.image.title=#{title}"
188
+ end
189
+
190
+ def prune_images_titled(title)
191
+ docker :image, :prune, "--all", "--force", "--filter", "label=org.opencontainers.image.title=#{title}"
192
+ end
193
+
194
+ # dash-proxy keeps its state under /home/dash-proxy/.config/dash-proxy
164
195
  # whichever host it runs on - only the volume name differs, so a dedicated
165
196
  # load balancer and a shared proxy host never fight over the same volume.
166
197
  # (The apps-config mount comes with run_args, via the proxy's run surface.)
167
198
  def config_volume
168
199
  if on_proxy_host?
169
- [ "--volume", "kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy" ]
200
+ [ "--volume", "dash-proxy-config:/home/dash-proxy/.config/dash-proxy" ]
170
201
  else
171
- [ "--volume", "kamal-loadbalancer-config:/home/kamal-proxy/.config/kamal-proxy" ]
202
+ [ "--volume", "dash-loadbalancer-config:/home/dash-proxy/.config/dash-proxy" ]
172
203
  end
173
204
  end
174
205
 
175
206
  # The certificate store lives in whichever config volume this loadbalancer
176
- # actually mounts — the shared kamal-proxy one on a proxy host.
207
+ # actually mounts — the shared dash-proxy one on a proxy host.
177
208
  def cert_store_volume_args
178
209
  config_volume
179
210
  end
@@ -2,9 +2,9 @@ require "active_support/duration"
2
2
  require "time"
3
3
  require "base64"
4
4
 
5
- class Kamal::Commands::Lock < Kamal::Commands::Base
5
+ class Dash::Commands::Lock < Dash::Commands::Base
6
6
  # The deploy lock is scoped to service+destination, so two destinations can
7
- # deploy at once. Server-scoped resources — above all the single kamal-proxy
7
+ # deploy at once. Server-scoped resources — above all the single dash-proxy
8
8
  # container a host runs for every destination on it — need a lock that every
9
9
  # destination contends for, hence :server.
10
10
  SCOPES = %i[ destination server ].freeze
@@ -85,7 +85,7 @@ class Kamal::Commands::Lock < Kamal::Commands::Base
85
85
  end
86
86
 
87
87
  def locked_by
88
- Kamal::Git.user_name
88
+ Dash::Git.user_name
89
89
  rescue Errno::ENOENT
90
90
  "Unknown"
91
91
  end
@@ -10,7 +10,7 @@
10
10
  # The including class provides `container_name`, `cert_store_volume_args` (the
11
11
  # config volume mount) and `one_off_image` (the image tokens for a one-off
12
12
  # container).
13
- module Kamal::Commands::Proxy::CertTransfer
13
+ module Dash::Commands::Proxy::CertTransfer
14
14
  CERT_ARCHIVE_FILENAME = "certs-export.tar.gz"
15
15
  CERT_IMPORT_STAGING_FILENAME = "certs-import"
16
16
  CONTAINER_IMPORT_PATH = "/tmp/kamal-cert-import"
@@ -18,20 +18,20 @@ module Kamal::Commands::Proxy::CertTransfer
18
18
  # Through the RPC socket of the running container, under the proxy's own
19
19
  # certificate write lock, so a backup taken mid-renewal is never torn.
20
20
  def export_certs
21
- docker :exec, container_name, "kamal-proxy", :export, :certs, certs_archive_container_path
21
+ docker :exec, container_name, "dash-proxy", :export, :certs, certs_archive_container_path
22
22
  end
23
23
 
24
24
  # Reads the data directory offline over the config volume — only safe when
25
- # the container is stopped, which Kamal::Cli::Proxy guarantees.
25
+ # the container is stopped, which Dash::Cli::Proxy guarantees.
26
26
  def export_certs_offline
27
27
  docker :run, "--rm",
28
28
  *cert_store_volume_args,
29
29
  *config.proxy_boot.apps_volume.docker_args,
30
30
  *one_off_image,
31
- "kamal-proxy", :export, :certs, certs_archive_container_path
31
+ "dash-proxy", :export, :certs, certs_archive_container_path
32
32
  end
33
33
 
34
- # Offline by design (kamal-proxy import has no RPC path): the one-off
34
+ # Offline by design (dash-proxy import has no RPC path): the one-off
35
35
  # container mounts the config volume — creating it when no proxy has booted
36
36
  # yet, which is the Traefik-migration case — and the staged source streams
37
37
  # through stdin.
@@ -42,7 +42,7 @@ module Kamal::Commands::Proxy::CertTransfer
42
42
  # run whatever follows on the target host.
43
43
  import_command = shell [
44
44
  "cat > #{CONTAINER_IMPORT_PATH} &&",
45
- "kamal-proxy import certs",
45
+ "dash-proxy import certs",
46
46
  *optionize({ source_flag => CONTAINER_IMPORT_PATH, resolver: resolver, force: force || nil, verify: verify || nil }.compact, with: "=")
47
47
  ]
48
48