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::Cli::Main < Dash::Cli::Base
|
|
2
2
|
desc "setup", "Setup all accessories, push the env, and deploy app to servers"
|
|
3
3
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
|
4
4
|
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
@@ -8,7 +8,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
8
8
|
invoke_options = deploy_options
|
|
9
9
|
|
|
10
10
|
say "Ensure Docker is installed...", :magenta
|
|
11
|
-
invoke "
|
|
11
|
+
invoke "dash:cli:server:bootstrap", [], invoke_options
|
|
12
12
|
|
|
13
13
|
deploy(boot_accessories: true)
|
|
14
14
|
end
|
|
@@ -26,36 +26,36 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
26
26
|
print_config_banner
|
|
27
27
|
|
|
28
28
|
say "Validate configuration and secrets...", :magenta
|
|
29
|
-
|
|
29
|
+
DASH.config.validate_secrets!(include_accessories: boot_accessories)
|
|
30
30
|
|
|
31
31
|
if options[:skip_push]
|
|
32
32
|
say "Pull app image...", :magenta
|
|
33
|
-
invoke "
|
|
33
|
+
invoke "dash:cli:build:pull", [], invoke_options
|
|
34
34
|
else
|
|
35
35
|
say "Build and push app image...", :magenta
|
|
36
|
-
invoke "
|
|
36
|
+
invoke "dash:cli:build:deliver", [], invoke_options
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
modify(lock: true) do
|
|
40
40
|
run_hook "pre-deploy", secrets: true
|
|
41
41
|
|
|
42
|
-
say "Ensure
|
|
43
|
-
invoke "
|
|
42
|
+
say "Ensure dash-proxy is running...", :magenta
|
|
43
|
+
invoke "dash:cli:proxy:boot", [], invoke_options
|
|
44
44
|
|
|
45
|
-
invoke "
|
|
45
|
+
invoke "dash:cli:accessory:boot", [ "all" ], invoke_options if boot_accessories
|
|
46
46
|
|
|
47
47
|
say "Detect stale containers...", :magenta
|
|
48
|
-
invoke "
|
|
48
|
+
invoke "dash:cli:app:stale_containers", [], invoke_options.merge(stop: true)
|
|
49
49
|
|
|
50
|
-
invoke "
|
|
50
|
+
invoke "dash:cli:app:boot", [], invoke_options
|
|
51
51
|
|
|
52
|
-
if
|
|
52
|
+
if DASH.config.proxy.load_balancing?
|
|
53
53
|
say "Updating loadbalancer configuration...", :magenta
|
|
54
|
-
invoke "
|
|
54
|
+
invoke "dash:cli:proxy:loadbalancer", [ "deploy" ], invoke_options
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
say "Prune old containers and images...", :magenta
|
|
58
|
-
invoke "
|
|
58
|
+
invoke "dash:cli:prune:all", [], invoke_options
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting
|
|
66
|
+
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting dash-proxy and pruning"
|
|
67
67
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
|
68
68
|
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
69
69
|
def redeploy
|
|
@@ -74,27 +74,27 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
74
74
|
print_config_banner
|
|
75
75
|
|
|
76
76
|
say "Validate configuration and secrets...", :magenta
|
|
77
|
-
|
|
77
|
+
DASH.config.validate_secrets!
|
|
78
78
|
|
|
79
79
|
if options[:skip_push]
|
|
80
80
|
say "Pull app image...", :magenta
|
|
81
|
-
invoke "
|
|
81
|
+
invoke "dash:cli:build:pull", [], invoke_options
|
|
82
82
|
else
|
|
83
83
|
say "Build and push app image...", :magenta
|
|
84
|
-
invoke "
|
|
84
|
+
invoke "dash:cli:build:deliver", [], invoke_options
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
modify(lock: true) do
|
|
88
88
|
run_hook "pre-deploy", secrets: true
|
|
89
89
|
|
|
90
90
|
say "Detect stale containers...", :magenta
|
|
91
|
-
invoke "
|
|
91
|
+
invoke "dash:cli:app:stale_containers", [], invoke_options.merge(stop: true)
|
|
92
92
|
|
|
93
|
-
invoke "
|
|
93
|
+
invoke "dash:cli:app:boot", [], invoke_options
|
|
94
94
|
|
|
95
|
-
if
|
|
95
|
+
if DASH.config.proxy.load_balancing?
|
|
96
96
|
say "Updating loadbalancer configuration...", :magenta
|
|
97
|
-
invoke "
|
|
97
|
+
invoke "dash:cli:proxy:loadbalancer", [ "deploy" ], invoke_options
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
end
|
|
@@ -112,12 +112,12 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
112
112
|
modify(lock: true) do
|
|
113
113
|
invoke_options = deploy_options
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
DASH.config.version = version
|
|
116
116
|
|
|
117
117
|
if container_available?(version)
|
|
118
118
|
run_hook "pre-deploy", secrets: true
|
|
119
119
|
|
|
120
|
-
invoke "
|
|
120
|
+
invoke "dash:cli:app:boot", [], invoke_options.merge(version: version)
|
|
121
121
|
rolled_back = true
|
|
122
122
|
else
|
|
123
123
|
say "The app version '#{version}' is not available as a container (use 'dash app containers' for available versions)", :red
|
|
@@ -131,23 +131,23 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
131
131
|
|
|
132
132
|
desc "details", "Show details about all containers"
|
|
133
133
|
def details
|
|
134
|
-
invoke "
|
|
135
|
-
invoke "
|
|
136
|
-
invoke "
|
|
134
|
+
invoke "dash:cli:proxy:details"
|
|
135
|
+
invoke "dash:cli:app:details"
|
|
136
|
+
invoke "dash:cli:accessory:details", [ "all" ]
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
desc "audit", "Show audit log from servers"
|
|
140
140
|
def audit
|
|
141
141
|
quiet = options[:quiet]
|
|
142
|
-
on(
|
|
143
|
-
puts_by_host host, capture_with_info(*
|
|
142
|
+
on(DASH.hosts) do |host|
|
|
143
|
+
puts_by_host host, capture_with_info(*DASH.auditor.reveal), quiet: quiet
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
desc "config", "Show combined config (including secrets!)"
|
|
148
148
|
def config
|
|
149
149
|
run_locally do
|
|
150
|
-
puts
|
|
150
|
+
puts Dash::Utils.redacted(DASH.config.to_h).to_yaml
|
|
151
151
|
end
|
|
152
152
|
end
|
|
153
153
|
|
|
@@ -155,9 +155,9 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
155
155
|
def docs(section = nil)
|
|
156
156
|
case section
|
|
157
157
|
when NilClass
|
|
158
|
-
puts
|
|
158
|
+
puts Dash::Configuration.validation_doc
|
|
159
159
|
else
|
|
160
|
-
puts
|
|
160
|
+
puts Dash::Configuration.const_get(section.titlecase.to_sym).validation_doc
|
|
161
161
|
end
|
|
162
162
|
rescue NameError
|
|
163
163
|
puts "No documentation found for #{section}"
|
|
@@ -168,7 +168,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
168
168
|
say "Running readiness checks...", :magenta
|
|
169
169
|
pre_connect_if_required
|
|
170
170
|
|
|
171
|
-
doctor =
|
|
171
|
+
doctor = Dash::Cli::Doctor.new
|
|
172
172
|
doctor.run
|
|
173
173
|
|
|
174
174
|
print_doctor_report doctor.results
|
|
@@ -176,11 +176,11 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
176
176
|
if doctor.successful?
|
|
177
177
|
say doctor_summary(doctor), :green
|
|
178
178
|
else
|
|
179
|
-
raise
|
|
179
|
+
raise Dash::Cli::DoctorError, doctor_failure_message(doctor)
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
182
|
|
|
183
|
-
desc "init", "Create config stub in config/deploy.yml and secrets stub in .
|
|
183
|
+
desc "init", "Create config stub in config/deploy.yml and secrets stub in .dash"
|
|
184
184
|
option :bundle, type: :boolean, default: false, desc: "Add dash to the Gemfile and create a bin/dash binstub"
|
|
185
185
|
def init
|
|
186
186
|
require "fileutils"
|
|
@@ -193,18 +193,23 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
193
193
|
puts "Created configuration file in config/deploy.yml"
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
# Resolved rather than hardcoded to .dash: a project still on .kamal must
|
|
197
|
+
# keep getting its stubs there, or init would create a second directory that
|
|
198
|
+
# silently wins resolution and orphans the operator's real secrets.
|
|
199
|
+
project_directory = Dash::ProjectDirectory.path
|
|
200
|
+
|
|
201
|
+
unless (secrets_file = Pathname.new(File.expand_path("#{project_directory}/secrets"))).exist?
|
|
197
202
|
FileUtils.mkdir_p secrets_file.dirname
|
|
198
203
|
FileUtils.cp_r Pathname.new(File.expand_path("templates/secrets", __dir__)), secrets_file
|
|
199
|
-
puts "Created
|
|
204
|
+
puts "Created #{project_directory}/secrets file"
|
|
200
205
|
end
|
|
201
206
|
|
|
202
|
-
unless (hooks_dir = Pathname.new(File.expand_path("
|
|
207
|
+
unless (hooks_dir = Pathname.new(File.expand_path("#{project_directory}/hooks"))).exist?
|
|
203
208
|
hooks_dir.mkpath
|
|
204
209
|
Pathname.new(File.expand_path("templates/sample_hooks", __dir__)).each_child do |sample_hook|
|
|
205
210
|
FileUtils.cp sample_hook, hooks_dir, preserve: true
|
|
206
211
|
end
|
|
207
|
-
puts "Created sample hooks in
|
|
212
|
+
puts "Created sample hooks in #{project_directory}/hooks"
|
|
208
213
|
end
|
|
209
214
|
|
|
210
215
|
if options[:bundle]
|
|
@@ -221,44 +226,50 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
221
226
|
end
|
|
222
227
|
end
|
|
223
228
|
|
|
224
|
-
desc "remove", "Remove
|
|
229
|
+
desc "remove", "Remove dash-proxy, app, accessories, and registry session from servers"
|
|
225
230
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
|
226
231
|
def remove
|
|
227
232
|
confirming "This will remove all containers and images. Are you sure?" do
|
|
228
233
|
modify(lock: true) do
|
|
229
|
-
invoke "
|
|
230
|
-
invoke "
|
|
231
|
-
invoke "
|
|
232
|
-
invoke "
|
|
234
|
+
invoke "dash:cli:app:remove", [], options.without(:confirmed)
|
|
235
|
+
invoke "dash:cli:proxy:remove", [], options.without(:confirmed)
|
|
236
|
+
invoke "dash:cli:accessory:remove", [ "all" ], options
|
|
237
|
+
invoke "dash:cli:registry:remove", [], options.without(:confirmed).merge(skip_local: true)
|
|
233
238
|
end
|
|
234
239
|
end
|
|
235
240
|
end
|
|
236
241
|
|
|
242
|
+
desc "migrate", "Move this project's .kamal directory to .dash"
|
|
243
|
+
option :dry_run, type: :boolean, default: false, desc: "Report what would move without touching anything"
|
|
244
|
+
def migrate
|
|
245
|
+
Dash::Cli::Main::Migrate.new(dry_run: options[:dry_run]).run.each { |message, color| say message, color }
|
|
246
|
+
end
|
|
247
|
+
|
|
237
248
|
desc "upgrade", "Upgrade from Kamal 1.x to 2.0"
|
|
238
249
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
|
239
250
|
option :rolling, type: :boolean, default: false, desc: "Upgrade one host at a time"
|
|
240
251
|
def upgrade
|
|
241
|
-
confirming "This will replace Traefik with
|
|
252
|
+
confirming "This will replace Traefik with dash-proxy and restart all accessories" do
|
|
242
253
|
modify(lock: true) do
|
|
243
254
|
if options[:rolling]
|
|
244
|
-
|
|
245
|
-
|
|
255
|
+
DASH.hosts.each do |host|
|
|
256
|
+
DASH.with_specific_hosts(host) do
|
|
246
257
|
say "Upgrading #{host}...", :magenta
|
|
247
|
-
if
|
|
248
|
-
invoke "
|
|
249
|
-
reset_invocation(
|
|
258
|
+
if DASH.app_hosts.include?(host)
|
|
259
|
+
invoke "dash:cli:proxy:upgrade", [], options.merge(confirmed: true, rolling: false)
|
|
260
|
+
reset_invocation(Dash::Cli::Proxy)
|
|
250
261
|
end
|
|
251
|
-
if
|
|
252
|
-
invoke "
|
|
253
|
-
reset_invocation(
|
|
262
|
+
if DASH.accessory_hosts.include?(host)
|
|
263
|
+
invoke "dash:cli:accessory:upgrade", [ "all" ], options.merge(confirmed: true, rolling: false)
|
|
264
|
+
reset_invocation(Dash::Cli::Accessory)
|
|
254
265
|
end
|
|
255
266
|
say "Upgraded #{host}", :magenta
|
|
256
267
|
end
|
|
257
268
|
end
|
|
258
269
|
else
|
|
259
270
|
say "Upgrading all hosts...", :magenta
|
|
260
|
-
invoke "
|
|
261
|
-
invoke "
|
|
271
|
+
invoke "dash:cli:proxy:upgrade", [], options.merge(confirmed: true)
|
|
272
|
+
invoke "dash:cli:accessory:upgrade", [ "all" ], options.merge(confirmed: true)
|
|
262
273
|
say "Upgraded all hosts", :magenta
|
|
263
274
|
end
|
|
264
275
|
end
|
|
@@ -267,42 +278,42 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
267
278
|
|
|
268
279
|
desc "version", "Show dash version"
|
|
269
280
|
def version
|
|
270
|
-
puts
|
|
281
|
+
puts Dash::VERSION
|
|
271
282
|
end
|
|
272
283
|
|
|
273
284
|
desc "accessory", "Manage accessories (db/redis/search)"
|
|
274
|
-
subcommand "accessory",
|
|
285
|
+
subcommand "accessory", Dash::Cli::Accessory
|
|
275
286
|
|
|
276
287
|
desc "app", "Manage application"
|
|
277
|
-
subcommand "app",
|
|
288
|
+
subcommand "app", Dash::Cli::App
|
|
278
289
|
|
|
279
290
|
desc "build", "Build application image"
|
|
280
|
-
subcommand "build",
|
|
291
|
+
subcommand "build", Dash::Cli::Build
|
|
281
292
|
|
|
282
293
|
desc "lock", "Manage the deploy lock"
|
|
283
|
-
subcommand "lock",
|
|
294
|
+
subcommand "lock", Dash::Cli::Lock
|
|
284
295
|
|
|
285
|
-
desc "proxy", "Manage
|
|
286
|
-
subcommand "proxy",
|
|
296
|
+
desc "proxy", "Manage dash-proxy"
|
|
297
|
+
subcommand "proxy", Dash::Cli::Proxy
|
|
287
298
|
|
|
288
299
|
desc "prune", "Prune old application images and containers"
|
|
289
|
-
subcommand "prune",
|
|
300
|
+
subcommand "prune", Dash::Cli::Prune
|
|
290
301
|
|
|
291
302
|
desc "registry", "Login and -out of the image registry"
|
|
292
|
-
subcommand "registry",
|
|
303
|
+
subcommand "registry", Dash::Cli::Registry
|
|
293
304
|
|
|
294
305
|
desc "secrets", "Helpers for extracting secrets"
|
|
295
|
-
subcommand "secrets",
|
|
306
|
+
subcommand "secrets", Dash::Cli::Secrets
|
|
296
307
|
|
|
297
308
|
desc "server", "Bootstrap servers with curl and Docker"
|
|
298
|
-
subcommand "server",
|
|
309
|
+
subcommand "server", Dash::Cli::Server
|
|
299
310
|
|
|
300
311
|
private
|
|
301
312
|
def container_available?(version)
|
|
302
313
|
begin
|
|
303
|
-
on(
|
|
304
|
-
|
|
305
|
-
container_id = capture_with_info(*
|
|
314
|
+
on(DASH.app_hosts) do
|
|
315
|
+
DASH.roles_on(host).each do |role|
|
|
316
|
+
container_id = capture_with_info(*DASH.app(role: role, host: host).container_id_for_version(version))
|
|
306
317
|
raise "Container not found" unless container_id.present?
|
|
307
318
|
end
|
|
308
319
|
end
|
|
@@ -321,13 +332,13 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
321
332
|
def deploy_options
|
|
322
333
|
base_options = options.without("skip_push")
|
|
323
334
|
base_options = base_options.except("no_cache") unless base_options["no_cache"]
|
|
324
|
-
{ "version" =>
|
|
335
|
+
{ "version" => DASH.config.version }.merge(base_options)
|
|
325
336
|
end
|
|
326
337
|
|
|
327
338
|
def print_doctor_report(results)
|
|
328
339
|
results.group_by(&:title).each do |title, rows|
|
|
329
340
|
say title
|
|
330
|
-
rows.each { |row| say " #{row}",
|
|
341
|
+
rows.each { |row| say " #{row}", Dash::Cli::Doctor::STATUS_COLORS[row.status] }
|
|
331
342
|
end
|
|
332
343
|
end
|
|
333
344
|
|
|
@@ -345,7 +356,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
345
356
|
end
|
|
346
357
|
|
|
347
358
|
def print_config_banner
|
|
348
|
-
config =
|
|
359
|
+
config = DASH.config
|
|
349
360
|
|
|
350
361
|
say "Deploying #{config.service}#{" to #{config.destination}" if config.destination} (version #{config.abbreviated_version})", :magenta
|
|
351
362
|
config.roles.each do |role|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Dash::Cli::Proxy::Drift
|
|
2
2
|
attr_reader :host, :sshkit
|
|
3
3
|
delegate :capture_with_info, to: :sshkit
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ class Kamal::Cli::Proxy::Drift
|
|
|
24
24
|
@expected_digest ||= if proxy.proxy_run_config
|
|
25
25
|
proxy.proxy_run_config.config_digest
|
|
26
26
|
else
|
|
27
|
-
|
|
27
|
+
Dash::Configuration::Proxy::Run.digest(capture_with_info(*proxy.boot_config).strip)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -34,6 +34,6 @@ class Kamal::Cli::Proxy::Drift
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def proxy
|
|
37
|
-
@proxy ||=
|
|
37
|
+
@proxy ||= DASH.proxy(host)
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Stage 3c migration: brings a host that still carries pre-rename container
|
|
2
|
+
# identity onto the renamed one.
|
|
3
|
+
#
|
|
4
|
+
# Three steps, run in this order on each proxy host before the normal boot:
|
|
5
|
+
#
|
|
6
|
+
# 1. Bridge the network. Docker cannot rename one, so `dash` is created
|
|
7
|
+
# alongside `kamal` and everything still attached to the old network joins
|
|
8
|
+
# the new one. App containers would be replaced by the next deploy anyway;
|
|
9
|
+
# accessories are not, which is the whole reason this exists — without it a
|
|
10
|
+
# renamed proxy cannot reach `db` or `redis`.
|
|
11
|
+
#
|
|
12
|
+
# 2. Copy the config volume. It holds the routing table and the ACME account
|
|
13
|
+
# and certificate cache, so losing it means re-issuing every certificate
|
|
14
|
+
# and spending Let's Encrypt rate limits to get back to where we were. This
|
|
15
|
+
# must happen before the new container starts.
|
|
16
|
+
#
|
|
17
|
+
# 3. Replace the legacy container. A rename means the old container has to
|
|
18
|
+
# release ports 80/443 before the new one can claim them, and no
|
|
19
|
+
# port-holder handoff spans two container names — so this stage accepts a
|
|
20
|
+
# brief outage per host. Deliberate; see zoolutions/dash#124.
|
|
21
|
+
#
|
|
22
|
+
# Every step is idempotent and guarded on its destination not already existing,
|
|
23
|
+
# so a second deploy is a no-op. Nothing here removes the legacy network or
|
|
24
|
+
# volume: an operator who wants them gone removes them by hand, and stage 3d
|
|
25
|
+
# deletes this class outright.
|
|
26
|
+
class Dash::Cli::Proxy::LegacyRename
|
|
27
|
+
attr_reader :host, :sshkit
|
|
28
|
+
delegate :execute, to: :sshkit
|
|
29
|
+
|
|
30
|
+
def initialize(host, sshkit)
|
|
31
|
+
@host = host
|
|
32
|
+
@sshkit = sshkit
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def run
|
|
36
|
+
bridge_network
|
|
37
|
+
adopt_config_volume
|
|
38
|
+
replace_legacy_container
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
def bridge_network
|
|
43
|
+
execute *DASH.docker.connect_legacy_network_containers
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def adopt_config_volume
|
|
47
|
+
execute *DASH.proxy(host).copy_legacy_config_volume
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The drain timeout the proxy is configured with, so a busy host is not cut
|
|
51
|
+
# off mid-request any more abruptly than a normal reboot would.
|
|
52
|
+
def replace_legacy_container
|
|
53
|
+
proxy = DASH.proxy(host)
|
|
54
|
+
|
|
55
|
+
execute *proxy.remove_legacy_container(timeout: DASH.config.drain_timeout)
|
|
56
|
+
execute *proxy.remove_legacy_holder_container
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ownership bookkeeping for a load balancer host that more than one dash app
|
|
2
2
|
# may be deploying to. Kamal only ever sees one deploy.yml at a time, so the
|
|
3
3
|
# other apps are visible solely through the files they left on the host.
|
|
4
|
-
class
|
|
4
|
+
class Dash::Cli::Proxy::LoadbalancerClaim
|
|
5
5
|
attr_reader :host, :sshkit
|
|
6
6
|
delegate :capture_with_info, :execute, :upload!, :warn, to: :sshkit
|
|
7
7
|
|
|
@@ -55,11 +55,11 @@ class Kamal::Cli::Proxy::LoadbalancerClaim
|
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
def config
|
|
58
|
-
|
|
58
|
+
DASH.loadbalancer_config
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def commands
|
|
62
|
-
|
|
62
|
+
DASH.loadbalancer
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Owner tokens are "<service-and-destination> <repository>"; the repository
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Unlike the proxy hosts' port-holder handoff this is stop -> run: the
|
|
6
6
|
# loadbalancer keeps its service state in the config volume, which the
|
|
7
7
|
# replacement container re-mounts, so every app's routes survive the gap.
|
|
8
|
-
class
|
|
8
|
+
class Dash::Cli::Proxy::LoadbalancerReboot
|
|
9
9
|
READY_TIMEOUT = 30
|
|
10
10
|
|
|
11
11
|
attr_reader :host, :sshkit
|
|
@@ -17,30 +17,30 @@ class Kamal::Cli::Proxy::LoadbalancerReboot
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def run
|
|
20
|
-
execute *
|
|
21
|
-
execute *
|
|
20
|
+
execute *DASH.auditor.record("Rebooted loadbalancer"), verbosity: :debug
|
|
21
|
+
execute *DASH.registry.login
|
|
22
22
|
|
|
23
|
-
info "Stopping and removing #{
|
|
24
|
-
execute *
|
|
25
|
-
execute *
|
|
23
|
+
info "Stopping and removing #{DASH.loadbalancer.container_name} on #{host}, if running..."
|
|
24
|
+
execute *DASH.loadbalancer.stop, raise_on_non_zero_exit: false
|
|
25
|
+
execute *DASH.loadbalancer.remove_container
|
|
26
26
|
|
|
27
|
-
if (lb_run =
|
|
28
|
-
execute *
|
|
27
|
+
if (lb_run = DASH.loadbalancer_config.run).secrets?
|
|
28
|
+
execute *DASH.loadbalancer.ensure_proxy_directory
|
|
29
29
|
upload! lb_run.secrets_io, lb_run.secrets_path, mode: "0600"
|
|
30
30
|
else
|
|
31
|
-
execute *
|
|
31
|
+
execute *DASH.loadbalancer.remove_proxy_secrets_file, raise_on_non_zero_exit: false
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
execute *
|
|
35
|
-
|
|
36
|
-
execute *
|
|
34
|
+
execute *DASH.loadbalancer.ensure_apps_config_directory
|
|
35
|
+
Dash::Cli::Proxy::LoadbalancerClaim.new(host, sshkit).claim_run_config(replace: true)
|
|
36
|
+
execute *DASH.loadbalancer.run
|
|
37
37
|
|
|
38
38
|
wait_until_ready
|
|
39
39
|
verify_service if re_register_service
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# dash-proxy keeps its service state in the config volume, which the
|
|
42
42
|
# replacement container re-mounts - every app's routes survive.
|
|
43
|
-
services = capture_with_info(*
|
|
43
|
+
services = capture_with_info(*DASH.loadbalancer.list).strip
|
|
44
44
|
info "Services registered on the load balancer at #{host} after reboot:\n#{services}"
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -49,9 +49,9 @@ class Kamal::Cli::Proxy::LoadbalancerReboot
|
|
|
49
49
|
deadline = Time.now + READY_TIMEOUT
|
|
50
50
|
|
|
51
51
|
begin
|
|
52
|
-
capture_with_info(*
|
|
52
|
+
capture_with_info(*DASH.loadbalancer.list, verbosity: :debug)
|
|
53
53
|
rescue SSHKit::Command::Failed
|
|
54
|
-
raise
|
|
54
|
+
raise Dash::Cli::BootError, "the load balancer on #{host} did not become ready within #{READY_TIMEOUT} seconds" if Time.now >= deadline
|
|
55
55
|
sleep 0.5
|
|
56
56
|
retry
|
|
57
57
|
end
|
|
@@ -67,21 +67,21 @@ class Kamal::Cli::Proxy::LoadbalancerReboot
|
|
|
67
67
|
# --recheck-targets-on-restore re-verifies). No owner record, or a foreign
|
|
68
68
|
# one, means nothing of ours to restore.
|
|
69
69
|
def re_register_service
|
|
70
|
-
owner = capture_with_info(*
|
|
71
|
-
return false unless owner ==
|
|
70
|
+
owner = capture_with_info(*DASH.loadbalancer.read_service_owner, raise_on_non_zero_exit: false).strip
|
|
71
|
+
return false unless owner == DASH.loadbalancer_config.owner_token
|
|
72
72
|
|
|
73
|
-
info "Re-registering #{
|
|
74
|
-
execute *
|
|
73
|
+
info "Re-registering #{DASH.config.service} with the load balancer on #{host}..."
|
|
74
|
+
execute *DASH.loadbalancer.deploy(targets: DASH.loadbalancer_config.target_hosts)
|
|
75
75
|
true
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# `list --json` returns {"services": {"<name>": ...}} - exact key
|
|
79
79
|
# membership, same as the per-host proxy reboot's verification.
|
|
80
80
|
def verify_service
|
|
81
|
-
listed = JSON.parse(capture_with_info(*
|
|
81
|
+
listed = JSON.parse(capture_with_info(*DASH.loadbalancer.list(json: true))).fetch("services", {}).keys
|
|
82
82
|
|
|
83
|
-
unless listed.include?(
|
|
84
|
-
raise
|
|
83
|
+
unless listed.include?(DASH.config.service)
|
|
84
|
+
raise Dash::Cli::BootError, "the load balancer on #{host} is missing service #{DASH.config.service} after reboot"
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|