kamal 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kamal/cli/accessory.rb +1 -1
- data/lib/kamal/cli/alias/command.rb +1 -0
- data/lib/kamal/cli/app.rb +15 -3
- data/lib/kamal/cli/base.rb +16 -1
- data/lib/kamal/cli/build.rb +36 -14
- data/lib/kamal/cli/main.rb +4 -3
- data/lib/kamal/cli/proxy.rb +2 -4
- data/lib/kamal/cli/registry.rb +2 -0
- data/lib/kamal/cli/templates/deploy.yml +2 -2
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- data/lib/kamal/cli.rb +1 -0
- data/lib/kamal/commander.rb +16 -25
- data/lib/kamal/commands/accessory.rb +1 -5
- data/lib/kamal/commands/app/assets.rb +4 -4
- data/lib/kamal/commands/base.rb +14 -0
- data/lib/kamal/commands/builder/base.rb +12 -5
- data/lib/kamal/commands/builder/cloud.rb +22 -0
- data/lib/kamal/commands/builder.rb +6 -20
- data/lib/kamal/commands/registry.rb +9 -7
- data/lib/kamal/configuration/accessory.rb +36 -19
- data/lib/kamal/configuration/builder.rb +4 -0
- data/lib/kamal/configuration/docs/accessory.yml +20 -1
- data/lib/kamal/configuration/docs/builder.yml +3 -0
- data/lib/kamal/configuration/registry.rb +6 -6
- data/lib/kamal/configuration/role.rb +6 -6
- data/lib/kamal/configuration/validator/role.rb +1 -1
- data/lib/kamal/configuration.rb +29 -12
- data/lib/kamal/docker.rb +30 -0
- data/lib/kamal/git.rb +10 -0
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +12 -4
- data/lib/kamal/secrets/adapters/base.rb +5 -2
- data/lib/kamal/secrets/adapters/bitwarden.rb +2 -2
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +72 -0
- data/lib/kamal/secrets/adapters/doppler.rb +15 -11
- data/lib/kamal/secrets/adapters/enpass.rb +71 -0
- data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +3 -2
- data/lib/kamal/secrets/adapters/one_password.rb +2 -2
- data/lib/kamal/secrets/adapters/test.rb +2 -2
- data/lib/kamal/secrets/adapters.rb +2 -0
- data/lib/kamal/version.rb +1 -1
- metadata +10 -4
- data/lib/kamal/secrets/adapters/test_optional_account.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '01499d423cd415dea520fe78d0e5f17b0d67d3ef2d241e56abb84e2deaeb3f65'
|
4
|
+
data.tar.gz: 826b542e67f360b9d019d886a454fff796b73cda57b5e201edc2981e5059a1dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbc7aa2632e0e5810666cb6d93ce698461fd3290dd5813c11bb88dd9faa4d6f7f015140c24a928b588df34316b814aec6ce710cbb4a28aa19713cc3420c15ae3
|
7
|
+
data.tar.gz: 2c818511055983038c9cbc9674a6f9c122de98296e27bf47441b02f3f9474176416e07cf1928bfc5b333648e51bb9ff4d857249173df82127e2ed29a124a97a7
|
data/lib/kamal/cli/accessory.rb
CHANGED
@@ -292,7 +292,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
292
292
|
def prepare(name)
|
293
293
|
with_accessory(name) do |accessory, hosts|
|
294
294
|
on(hosts) do
|
295
|
-
execute *KAMAL.registry.login
|
295
|
+
execute *KAMAL.registry.login(registry_config: accessory.registry)
|
296
296
|
execute *KAMAL.docker.create_network
|
297
297
|
rescue SSHKit::Command::Failed => e
|
298
298
|
raise unless e.message.include?("already exists")
|
data/lib/kamal/cli/app.rb
CHANGED
@@ -16,10 +16,18 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
16
16
|
# Primary hosts and roles are returned first, so they can open the barrier
|
17
17
|
barrier = Kamal::Cli::Healthcheck::Barrier.new
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
host_boot_groups.each do |hosts|
|
20
|
+
host_list = Array(hosts).join(",")
|
21
|
+
run_hook "pre-app-boot", hosts: host_list
|
22
|
+
|
23
|
+
on(hosts) do |host|
|
24
|
+
KAMAL.roles_on(host).each do |role|
|
25
|
+
Kamal::Cli::App::Boot.new(host, role, self, version, barrier).run
|
26
|
+
end
|
22
27
|
end
|
28
|
+
|
29
|
+
run_hook "post-app-boot", hosts: host_list
|
30
|
+
sleep KAMAL.config.boot.wait if KAMAL.config.boot.wait
|
23
31
|
end
|
24
32
|
|
25
33
|
# Tag once the app booted on all hosts
|
@@ -340,4 +348,8 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
340
348
|
yield
|
341
349
|
end
|
342
350
|
end
|
351
|
+
|
352
|
+
def host_boot_groups
|
353
|
+
KAMAL.config.boot.limit ? KAMAL.hosts.each_slice(KAMAL.config.boot.limit).to_a : [ KAMAL.hosts ]
|
354
|
+
end
|
343
355
|
end
|
data/lib/kamal/cli/base.rb
CHANGED
@@ -5,7 +5,7 @@ module Kamal::Cli
|
|
5
5
|
class Base < Thor
|
6
6
|
include SSHKit::DSL
|
7
7
|
|
8
|
-
def self.exit_on_failure?()
|
8
|
+
def self.exit_on_failure?() true end
|
9
9
|
def self.dynamic_command_class() Kamal::Cli::Alias::Command end
|
10
10
|
|
11
11
|
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
|
@@ -30,6 +30,7 @@ module Kamal::Cli
|
|
30
30
|
else
|
31
31
|
super
|
32
32
|
end
|
33
|
+
|
33
34
|
initialize_commander unless KAMAL.configured?
|
34
35
|
end
|
35
36
|
|
@@ -194,5 +195,19 @@ module Kamal::Cli
|
|
194
195
|
ENV.clear
|
195
196
|
ENV.update(current_env)
|
196
197
|
end
|
198
|
+
|
199
|
+
def ensure_docker_installed
|
200
|
+
run_locally do
|
201
|
+
begin
|
202
|
+
execute *KAMAL.builder.ensure_docker_installed
|
203
|
+
rescue SSHKit::Command::Failed => e
|
204
|
+
error = e.message =~ /command not found/ ?
|
205
|
+
"Docker is not installed locally" :
|
206
|
+
"Docker buildx plugin is not installed locally"
|
207
|
+
|
208
|
+
raise DependencyError, error
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
197
212
|
end
|
198
213
|
end
|
data/lib/kamal/cli/build.rb
CHANGED
@@ -5,15 +5,16 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
5
5
|
|
6
6
|
desc "deliver", "Build app and push app image to registry then pull image on servers"
|
7
7
|
def deliver
|
8
|
-
push
|
9
|
-
pull
|
8
|
+
invoke :push
|
9
|
+
invoke :pull
|
10
10
|
end
|
11
11
|
|
12
12
|
desc "push", "Build and push app image to registry"
|
13
|
+
option :output, type: :string, default: "registry", banner: "export_type", desc: "Exported type for the build result, and may be any exported type supported by 'buildx --output'."
|
13
14
|
def push
|
14
15
|
cli = self
|
15
16
|
|
16
|
-
|
17
|
+
ensure_docker_installed
|
17
18
|
run_hook "pre-build"
|
18
19
|
|
19
20
|
uncommitted_changes = Kamal::Git.uncommitted_changes
|
@@ -49,7 +50,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
49
50
|
end
|
50
51
|
|
51
52
|
# Get the command here to ensure the Dir.chdir doesn't interfere with it
|
52
|
-
push = KAMAL.builder.push
|
53
|
+
push = KAMAL.builder.push(cli.options[:output])
|
53
54
|
|
54
55
|
KAMAL.with_verbosity(:debug) do
|
55
56
|
Dir.chdir(KAMAL.config.builder.build_directory) { execute *push }
|
@@ -108,21 +109,42 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
112
|
+
desc "dev", "Build using the working directory, tag it as dirty, and push to local image store."
|
113
|
+
option :output, type: :string, default: "docker", banner: "export_type", desc: "Exported type for the build result, and may be any exported type supported by 'buildx --output'."
|
114
|
+
def dev
|
115
|
+
cli = self
|
116
|
+
|
117
|
+
ensure_docker_installed
|
118
|
+
|
119
|
+
docker_included_files = Set.new(Kamal::Docker.included_files)
|
120
|
+
git_uncommitted_files = Set.new(Kamal::Git.uncommitted_files)
|
121
|
+
git_untracked_files = Set.new(Kamal::Git.untracked_files)
|
122
|
+
|
123
|
+
docker_uncommitted_files = docker_included_files & git_uncommitted_files
|
124
|
+
if docker_uncommitted_files.any?
|
125
|
+
say "WARNING: Files with uncommitted changes will be present in the dev container:", :yellow
|
126
|
+
docker_uncommitted_files.sort.each { |f| say " #{f}", :yellow }
|
127
|
+
say
|
128
|
+
end
|
129
|
+
|
130
|
+
docker_untracked_files = docker_included_files & git_untracked_files
|
131
|
+
if docker_untracked_files.any?
|
132
|
+
say "WARNING: Untracked files will be present in the dev container:", :yellow
|
133
|
+
docker_untracked_files.sort.each { |f| say " #{f}", :yellow }
|
134
|
+
say
|
135
|
+
end
|
120
136
|
|
121
|
-
|
137
|
+
with_env(KAMAL.config.builder.secrets) do
|
138
|
+
run_locally do
|
139
|
+
build = KAMAL.builder.push(cli.options[:output], tag_as_dirty: true)
|
140
|
+
KAMAL.with_verbosity(:debug) do
|
141
|
+
execute(*build)
|
122
142
|
end
|
123
143
|
end
|
124
144
|
end
|
145
|
+
end
|
125
146
|
|
147
|
+
private
|
126
148
|
def connect_to_remote_host(remote_host)
|
127
149
|
remote_uri = URI.parse(remote_host)
|
128
150
|
if remote_uri.scheme == "ssh"
|
data/lib/kamal/cli/main.rb
CHANGED
@@ -9,15 +9,14 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
9
9
|
say "Ensure Docker is installed...", :magenta
|
10
10
|
invoke "kamal:cli:server:bootstrap", [], invoke_options
|
11
11
|
|
12
|
-
|
13
|
-
deploy
|
12
|
+
deploy(boot_accessories: true)
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
17
|
desc "deploy", "Deploy app to servers"
|
19
18
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
20
|
-
def deploy
|
19
|
+
def deploy(boot_accessories: false)
|
21
20
|
runtime = print_runtime do
|
22
21
|
invoke_options = deploy_options
|
23
22
|
|
@@ -38,6 +37,8 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
38
37
|
say "Ensure kamal-proxy is running...", :magenta
|
39
38
|
invoke "kamal:cli:proxy:boot", [], invoke_options
|
40
39
|
|
40
|
+
invoke "kamal:cli:accessory:boot", [ "all" ], invoke_options if boot_accessories
|
41
|
+
|
41
42
|
say "Detect stale containers...", :magenta
|
42
43
|
invoke "kamal:cli:app:stale_containers", [], invoke_options.merge(stop: true)
|
43
44
|
|
data/lib/kamal/cli/proxy.rb
CHANGED
@@ -23,6 +23,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
23
23
|
|
24
24
|
desc "boot_config <set|get|reset>", "Manage kamal-proxy boot configuration"
|
25
25
|
option :publish, type: :boolean, default: true, desc: "Publish the proxy ports on the host"
|
26
|
+
option :publish_host_ip, type: :string, repeatable: true, default: nil, desc: "Host IP address to bind HTTP/HTTPS traffic to. Defaults to all interfaces"
|
26
27
|
option :http_port, type: :numeric, default: Kamal::Configuration::PROXY_HTTP_PORT, desc: "HTTP port to publish on the host"
|
27
28
|
option :https_port, type: :numeric, default: Kamal::Configuration::PROXY_HTTPS_PORT, desc: "HTTPS port to publish on the host"
|
28
29
|
option :log_max_size, type: :string, default: Kamal::Configuration::PROXY_LOG_MAX_SIZE, desc: "Max size of proxy logs"
|
@@ -31,7 +32,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
31
32
|
case subcommand
|
32
33
|
when "set"
|
33
34
|
boot_options = [
|
34
|
-
*(KAMAL.config.proxy_publish_args(options[:http_port], options[:https_port]) if options[:publish]),
|
35
|
+
*(KAMAL.config.proxy_publish_args(options[:http_port], options[:https_port], options[:publish_host_ip]) if options[:publish]),
|
35
36
|
*(KAMAL.config.proxy_logging_args(options[:log_max_size])),
|
36
37
|
*options[:docker_options].map { |option| "--#{option}" }
|
37
38
|
]
|
@@ -67,9 +68,6 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
|
|
67
68
|
execute *KAMAL.auditor.record("Rebooted proxy"), verbosity: :debug
|
68
69
|
execute *KAMAL.registry.login
|
69
70
|
|
70
|
-
"Stopping and removing Traefik on #{host}, if running..."
|
71
|
-
execute *KAMAL.proxy.cleanup_traefik
|
72
|
-
|
73
71
|
"Stopping and removing kamal-proxy on #{host}, if running..."
|
74
72
|
execute *KAMAL.proxy.stop, raise_on_non_zero_exit: false
|
75
73
|
execute *KAMAL.proxy.remove_container
|
data/lib/kamal/cli/registry.rb
CHANGED
@@ -3,6 +3,8 @@ class Kamal::Cli::Registry < Kamal::Cli::Base
|
|
3
3
|
option :skip_local, aliases: "-L", type: :boolean, default: false, desc: "Skip local login"
|
4
4
|
option :skip_remote, aliases: "-R", type: :boolean, default: false, desc: "Skip remote login"
|
5
5
|
def login
|
6
|
+
ensure_docker_installed
|
7
|
+
|
6
8
|
run_locally { execute *KAMAL.registry.login } unless options[:skip_local]
|
7
9
|
on(KAMAL.hosts) { execute *KAMAL.registry.login } unless options[:skip_remote]
|
8
10
|
end
|
@@ -38,7 +38,7 @@ builder:
|
|
38
38
|
arch: amd64
|
39
39
|
# Pass in additional build args needed for your Dockerfile.
|
40
40
|
# args:
|
41
|
-
# RUBY_VERSION: <%=
|
41
|
+
# RUBY_VERSION: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
|
42
42
|
|
43
43
|
# Inject ENV variables into containers (secrets come from .kamal/secrets).
|
44
44
|
#
|
@@ -49,7 +49,7 @@ builder:
|
|
49
49
|
# - RAILS_MASTER_KEY
|
50
50
|
|
51
51
|
# Aliases are triggered with "bin/kamal <alias>". You can overwrite arguments on invocation:
|
52
|
-
# "bin/kamal logs -r job" will tail logs from the first server in the job section.
|
52
|
+
# "bin/kamal app logs -r job" will tail logs from the first server in the job section.
|
53
53
|
#
|
54
54
|
# aliases:
|
55
55
|
# shell: app exec --interactive --reuse "bash"
|
data/lib/kamal/cli.rb
CHANGED
data/lib/kamal/commander.rb
CHANGED
@@ -4,13 +4,20 @@ require "active_support/core_ext/object/blank"
|
|
4
4
|
|
5
5
|
class Kamal::Commander
|
6
6
|
attr_accessor :verbosity, :holding_lock, :connected
|
7
|
+
attr_reader :specific_roles, :specific_hosts
|
7
8
|
delegate :hosts, :roles, :primary_host, :primary_role, :roles_on, :proxy_hosts, :accessory_hosts, to: :specifics
|
8
9
|
|
9
10
|
def initialize
|
11
|
+
reset
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
10
15
|
self.verbosity = :info
|
11
16
|
self.holding_lock = false
|
12
17
|
self.connected = false
|
13
|
-
@specifics = nil
|
18
|
+
@specifics = @specific_roles = @specific_hosts = nil
|
19
|
+
@config = @config_kwargs = nil
|
20
|
+
@commands = {}
|
14
21
|
end
|
15
22
|
|
16
23
|
def config
|
@@ -28,8 +35,6 @@ class Kamal::Commander
|
|
28
35
|
@config || @config_kwargs
|
29
36
|
end
|
30
37
|
|
31
|
-
attr_reader :specific_roles, :specific_hosts
|
32
|
-
|
33
38
|
def specific_primary!
|
34
39
|
@specifics = nil
|
35
40
|
if specific_roles.present?
|
@@ -76,11 +81,6 @@ class Kamal::Commander
|
|
76
81
|
config.accessories&.collect(&:name) || []
|
77
82
|
end
|
78
83
|
|
79
|
-
def accessories_on(host)
|
80
|
-
config.accessories.select { |accessory| accessory.hosts.include?(host.to_s) }.map(&:name)
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
84
|
def app(role: nil, host: nil)
|
85
85
|
Kamal::Commands::App.new(config, role: role, host: host)
|
86
86
|
end
|
@@ -94,42 +94,41 @@ class Kamal::Commander
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def builder
|
97
|
-
@builder ||= Kamal::Commands::Builder.new(config)
|
97
|
+
@commands[:builder] ||= Kamal::Commands::Builder.new(config)
|
98
98
|
end
|
99
99
|
|
100
100
|
def docker
|
101
|
-
@docker ||= Kamal::Commands::Docker.new(config)
|
101
|
+
@commands[:docker] ||= Kamal::Commands::Docker.new(config)
|
102
102
|
end
|
103
103
|
|
104
104
|
def hook
|
105
|
-
@hook ||= Kamal::Commands::Hook.new(config)
|
105
|
+
@commands[:hook] ||= Kamal::Commands::Hook.new(config)
|
106
106
|
end
|
107
107
|
|
108
108
|
def lock
|
109
|
-
@lock ||= Kamal::Commands::Lock.new(config)
|
109
|
+
@commands[:lock] ||= Kamal::Commands::Lock.new(config)
|
110
110
|
end
|
111
111
|
|
112
112
|
def proxy
|
113
|
-
@proxy ||= Kamal::Commands::Proxy.new(config)
|
113
|
+
@commands[:proxy] ||= Kamal::Commands::Proxy.new(config)
|
114
114
|
end
|
115
115
|
|
116
116
|
def prune
|
117
|
-
@prune ||= Kamal::Commands::Prune.new(config)
|
117
|
+
@commands[:prune] ||= Kamal::Commands::Prune.new(config)
|
118
118
|
end
|
119
119
|
|
120
120
|
def registry
|
121
|
-
@registry ||= Kamal::Commands::Registry.new(config)
|
121
|
+
@commands[:registry] ||= Kamal::Commands::Registry.new(config)
|
122
122
|
end
|
123
123
|
|
124
124
|
def server
|
125
|
-
@server ||= Kamal::Commands::Server.new(config)
|
125
|
+
@commands[:server] ||= Kamal::Commands::Server.new(config)
|
126
126
|
end
|
127
127
|
|
128
128
|
def alias(name)
|
129
129
|
config.aliases[name]
|
130
130
|
end
|
131
131
|
|
132
|
-
|
133
132
|
def with_verbosity(level)
|
134
133
|
old_level = self.verbosity
|
135
134
|
|
@@ -142,14 +141,6 @@ class Kamal::Commander
|
|
142
141
|
SSHKit.config.output_verbosity = old_level
|
143
142
|
end
|
144
143
|
|
145
|
-
def boot_strategy
|
146
|
-
if config.boot.limit.present?
|
147
|
-
{ in: :groups, limit: config.boot.limit, wait: config.boot.wait }
|
148
|
-
else
|
149
|
-
{}
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
144
|
def holding_lock?
|
154
145
|
self.holding_lock
|
155
146
|
end
|
@@ -4,11 +4,10 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
4
4
|
attr_reader :accessory_config
|
5
5
|
delegate :service_name, :image, :hosts, :port, :files, :directories, :cmd,
|
6
6
|
:network_args, :publish_args, :env_args, :volume_args, :label_args, :option_args,
|
7
|
-
:secrets_io, :secrets_path, :env_directory, :proxy, :running_proxy?,
|
7
|
+
:secrets_io, :secrets_path, :env_directory, :proxy, :running_proxy?, :registry,
|
8
8
|
to: :accessory_config
|
9
9
|
delegate :proxy_container_name, to: :config
|
10
10
|
|
11
|
-
|
12
11
|
def initialize(config, name:)
|
13
12
|
super(config)
|
14
13
|
@accessory_config = config.accessory(name)
|
@@ -42,7 +41,6 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
42
41
|
docker :ps, *service_filter
|
43
42
|
end
|
44
43
|
|
45
|
-
|
46
44
|
def logs(timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
|
47
45
|
pipe \
|
48
46
|
docker(:logs, service_name, (" --since #{since}" if since), (" --tail #{lines}" if lines), ("--timestamps" if timestamps), "2>&1"),
|
@@ -56,7 +54,6 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
56
54
|
(%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
|
57
55
|
end
|
58
56
|
|
59
|
-
|
60
57
|
def execute_in_existing_container(*command, interactive: false)
|
61
58
|
docker :exec,
|
62
59
|
("-it" if interactive),
|
@@ -87,7 +84,6 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
87
84
|
super command, host: hosts.first
|
88
85
|
end
|
89
86
|
|
90
|
-
|
91
87
|
def ensure_local_file_present(local_file)
|
92
88
|
if !local_file.is_a?(StringIO) && !Pathname.new(local_file).exist?
|
93
89
|
raise "Missing file: #{local_file}"
|
@@ -4,10 +4,10 @@ module Kamal::Commands::App::Assets
|
|
4
4
|
|
5
5
|
combine \
|
6
6
|
make_directory(role.asset_extracted_directory),
|
7
|
-
[ *docker(:
|
8
|
-
docker(:
|
9
|
-
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_directory),
|
10
|
-
docker(:
|
7
|
+
[ *docker(:container, :rm, asset_container, "2> /dev/null"), "|| true" ],
|
8
|
+
docker(:container, :create, "--name", asset_container, config.absolute_image),
|
9
|
+
docker(:container, :cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_directory),
|
10
|
+
docker(:container, :rm, asset_container),
|
11
11
|
by: "&&"
|
12
12
|
end
|
13
13
|
|
data/lib/kamal/commands/base.rb
CHANGED
@@ -34,6 +34,12 @@ module Kamal::Commands
|
|
34
34
|
[ :rm, path ]
|
35
35
|
end
|
36
36
|
|
37
|
+
def ensure_docker_installed
|
38
|
+
combine \
|
39
|
+
ensure_local_docker_installed,
|
40
|
+
ensure_local_buildx_installed
|
41
|
+
end
|
42
|
+
|
37
43
|
private
|
38
44
|
def combine(*commands, by: "&&")
|
39
45
|
commands
|
@@ -104,5 +110,13 @@ module Kamal::Commands
|
|
104
110
|
" -i #{key}"
|
105
111
|
end
|
106
112
|
end
|
113
|
+
|
114
|
+
def ensure_local_docker_installed
|
115
|
+
docker "--version"
|
116
|
+
end
|
117
|
+
|
118
|
+
def ensure_local_buildx_installed
|
119
|
+
docker :buildx, "version"
|
120
|
+
end
|
107
121
|
end
|
108
122
|
end
|
@@ -13,11 +13,12 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
13
13
|
docker :image, :rm, "--force", config.absolute_image
|
14
14
|
end
|
15
15
|
|
16
|
-
def push
|
16
|
+
def push(export_action = "registry", tag_as_dirty: false)
|
17
17
|
docker :buildx, :build,
|
18
|
-
"--
|
18
|
+
"--output=type=#{export_action}",
|
19
19
|
*platform_options(arches),
|
20
20
|
*([ "--builder", builder_name ] unless docker_driver?),
|
21
|
+
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
21
22
|
*build_options,
|
22
23
|
build_context
|
23
24
|
end
|
@@ -37,7 +38,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def build_options
|
40
|
-
[ *
|
41
|
+
[ *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_target, *build_ssh, *builder_provenance, *builder_sbom ]
|
41
42
|
end
|
42
43
|
|
43
44
|
def build_context
|
@@ -58,8 +59,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
58
59
|
end
|
59
60
|
|
60
61
|
private
|
61
|
-
def
|
62
|
-
[
|
62
|
+
def build_tag_names(tag_as_dirty: false)
|
63
|
+
tag_names = [ config.absolute_image, config.latest_image ]
|
64
|
+
tag_names.map! { |t| "#{t}-dirty" } if tag_as_dirty
|
65
|
+
tag_names
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_tag_options(tag_as_dirty: false)
|
69
|
+
build_tag_names(tag_as_dirty: tag_as_dirty).flat_map { |name| [ "-t", name ] }
|
63
70
|
end
|
64
71
|
|
65
72
|
def build_cache
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Kamal::Commands::Builder::Cloud < Kamal::Commands::Builder::Base
|
2
|
+
# Expects `driver` to be of format "cloud docker-org-name/builder-name"
|
3
|
+
|
4
|
+
def create
|
5
|
+
docker :buildx, :create, "--driver", driver
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove
|
9
|
+
docker :buildx, :rm, builder_name
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def builder_name
|
14
|
+
driver.gsub(/[ \/]/, "-")
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect_buildx
|
18
|
+
pipe \
|
19
|
+
docker(:buildx, :inspect, builder_name),
|
20
|
+
grep("-q", "Endpoint:.*cloud://.*")
|
21
|
+
end
|
22
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require "active_support/core_ext/string/filters"
|
2
2
|
|
3
3
|
class Kamal::Commands::Builder < Kamal::Commands::Base
|
4
|
-
delegate :create, :remove, :push, :clean, :pull, :info, :inspect_builder, :validate_image, :first_mirror, to: :target
|
5
|
-
delegate :local?, :remote?, to: "config.builder"
|
4
|
+
delegate :create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder, :validate_image, :first_mirror, to: :target
|
5
|
+
delegate :local?, :remote?, :cloud?, to: "config.builder"
|
6
6
|
|
7
7
|
include Clone
|
8
8
|
|
@@ -17,6 +17,8 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
17
17
|
else
|
18
18
|
remote
|
19
19
|
end
|
20
|
+
elsif cloud?
|
21
|
+
cloud
|
20
22
|
else
|
21
23
|
local
|
22
24
|
end
|
@@ -34,23 +36,7 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
34
36
|
@hybrid ||= Kamal::Commands::Builder::Hybrid.new(config)
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
if name.native?
|
40
|
-
ensure_local_docker_installed
|
41
|
-
else
|
42
|
-
combine \
|
43
|
-
ensure_local_docker_installed,
|
44
|
-
ensure_local_buildx_installed
|
45
|
-
end
|
39
|
+
def cloud
|
40
|
+
@cloud ||= Kamal::Commands::Builder::Cloud.new(config)
|
46
41
|
end
|
47
|
-
|
48
|
-
private
|
49
|
-
def ensure_local_docker_installed
|
50
|
-
docker "--version"
|
51
|
-
end
|
52
|
-
|
53
|
-
def ensure_local_buildx_installed
|
54
|
-
docker :buildx, "version"
|
55
|
-
end
|
56
42
|
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
class Kamal::Commands::Registry < Kamal::Commands::Base
|
2
|
-
|
2
|
+
def login(registry_config: nil)
|
3
|
+
registry_config ||= config.registry
|
3
4
|
|
4
|
-
def login
|
5
5
|
docker :login,
|
6
|
-
|
7
|
-
"-u", sensitive(Kamal::Utils.escape_shell_value(
|
8
|
-
"-p", sensitive(Kamal::Utils.escape_shell_value(
|
6
|
+
registry_config.server,
|
7
|
+
"-u", sensitive(Kamal::Utils.escape_shell_value(registry_config.username)),
|
8
|
+
"-p", sensitive(Kamal::Utils.escape_shell_value(registry_config.password))
|
9
9
|
end
|
10
10
|
|
11
|
-
def logout
|
12
|
-
|
11
|
+
def logout(registry_config: nil)
|
12
|
+
registry_config ||= config.registry
|
13
|
+
|
14
|
+
docker :logout, registry_config.server
|
13
15
|
end
|
14
16
|
end
|