kamal 1.3.1 → 1.5.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/lib/kamal/cli/accessory.rb +38 -29
- data/lib/kamal/cli/app/boot.rb +67 -0
- data/lib/kamal/cli/app/prepare_assets.rb +24 -0
- data/lib/kamal/cli/app.rb +25 -67
- data/lib/kamal/cli/base.rb +23 -8
- data/lib/kamal/cli/env.rb +3 -5
- data/lib/kamal/cli/main.rb +7 -4
- data/lib/kamal/cli/prune.rb +6 -2
- data/lib/kamal/cli/server.rb +3 -1
- data/lib/kamal/cli/templates/deploy.yml +5 -1
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +7 -0
- data/lib/kamal/cli/traefik.rb +16 -13
- data/lib/kamal/commander/specifics.rb +49 -0
- data/lib/kamal/commander.rb +9 -33
- data/lib/kamal/commands/accessory.rb +2 -2
- data/lib/kamal/commands/app/assets.rb +12 -12
- data/lib/kamal/commands/app/cord.rb +4 -4
- data/lib/kamal/commands/app/execution.rb +10 -8
- data/lib/kamal/commands/app/images.rb +1 -1
- data/lib/kamal/commands/app/logging.rb +2 -2
- data/lib/kamal/commands/app.rb +38 -18
- data/lib/kamal/commands/auditor.rb +1 -1
- data/lib/kamal/commands/base.rb +12 -0
- data/lib/kamal/commands/builder/base.rb +22 -5
- data/lib/kamal/commands/builder/multiarch.rb +17 -9
- data/lib/kamal/commands/builder/native/cached.rb +7 -6
- data/lib/kamal/commands/builder/native/remote.rb +9 -9
- data/lib/kamal/commands/builder/native.rb +8 -7
- data/lib/kamal/commands/docker.rb +10 -1
- data/lib/kamal/commands/healthcheck.rb +0 -1
- data/lib/kamal/commands/hook.rb +1 -1
- data/lib/kamal/commands/lock.rb +19 -9
- data/lib/kamal/commands/prune.rb +4 -4
- data/lib/kamal/commands/registry.rb +4 -1
- data/lib/kamal/commands/server.rb +1 -1
- data/lib/kamal/commands/traefik.rb +10 -16
- data/lib/kamal/configuration/accessory.rb +10 -20
- data/lib/kamal/configuration/boot.rb +1 -1
- data/lib/kamal/configuration/builder.rb +11 -3
- data/lib/kamal/configuration/env.rb +40 -0
- data/lib/kamal/configuration/role.rb +23 -40
- data/lib/kamal/configuration.rb +53 -21
- data/lib/kamal/env_file.rb +12 -15
- data/lib/kamal/sshkit_with_ext.rb +1 -0
- data/lib/kamal/utils.rb +7 -3
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +1 -1
- metadata +8 -3
data/lib/kamal/cli/traefik.rb
CHANGED
@@ -11,20 +11,23 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
|
|
11
11
|
|
12
12
|
desc "reboot", "Reboot Traefik on servers (stop container, remove container, start new container)"
|
13
13
|
option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel"
|
14
|
+
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
14
15
|
def reboot
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
confirming "This will cause a brief outage on each host. Are you sure?" do
|
17
|
+
mutating do
|
18
|
+
host_groups = options[:rolling] ? KAMAL.traefik_hosts : [ KAMAL.traefik_hosts ]
|
19
|
+
host_groups.each do |hosts|
|
20
|
+
host_list = Array(hosts).join(",")
|
21
|
+
run_hook "pre-traefik-reboot", hosts: host_list
|
22
|
+
on(hosts) do
|
23
|
+
execute *KAMAL.auditor.record("Rebooted traefik"), verbosity: :debug
|
24
|
+
execute *KAMAL.registry.login
|
25
|
+
execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
|
26
|
+
execute *KAMAL.traefik.remove_container
|
27
|
+
execute *KAMAL.traefik.run
|
28
|
+
end
|
29
|
+
run_hook "post-traefik-reboot", hosts: host_list
|
26
30
|
end
|
27
|
-
run_hook "post-traefik-reboot", hosts: host_list
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -44,7 +47,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
|
|
44
47
|
mutating do
|
45
48
|
on(KAMAL.traefik_hosts) do
|
46
49
|
execute *KAMAL.auditor.record("Stopped traefik"), verbosity: :debug
|
47
|
-
execute *KAMAL.traefik.stop
|
50
|
+
execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Kamal::Commander::Specifics
|
2
|
+
attr_reader :primary_host, :primary_role, :hosts, :roles
|
3
|
+
delegate :stable_sort!, to: Kamal::Utils
|
4
|
+
|
5
|
+
def initialize(config, specific_hosts, specific_roles)
|
6
|
+
@config, @specific_hosts, @specific_roles = config, specific_hosts, specific_roles
|
7
|
+
|
8
|
+
@roles, @hosts = specified_roles, specified_hosts
|
9
|
+
|
10
|
+
@primary_host = specific_hosts&.first || primary_specific_role&.primary_host || config.primary_host
|
11
|
+
@primary_role = primary_or_first_role(roles_on(primary_host))
|
12
|
+
|
13
|
+
stable_sort!(roles) { |role| role == primary_role ? 0 : 1 }
|
14
|
+
stable_sort!(hosts) { |host| roles_on(host).any? { |role| role == primary_role } ? 0 : 1 }
|
15
|
+
end
|
16
|
+
|
17
|
+
def roles_on(host)
|
18
|
+
roles.select { |role| role.hosts.include?(host.to_s) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def traefik_hosts
|
22
|
+
specific_hosts || config.traefik_hosts
|
23
|
+
end
|
24
|
+
|
25
|
+
def accessory_hosts
|
26
|
+
specific_hosts || config.accessories.flat_map(&:hosts)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
attr_reader :config, :specific_hosts, :specific_roles
|
31
|
+
|
32
|
+
def primary_specific_role
|
33
|
+
primary_or_first_role(specific_roles) if specific_roles.present?
|
34
|
+
end
|
35
|
+
|
36
|
+
def primary_or_first_role(roles)
|
37
|
+
roles.detect { |role| role == config.primary_role } || roles.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def specified_roles
|
41
|
+
(specific_roles || config.roles) \
|
42
|
+
.select { |role| ((specific_hosts || config.all_hosts) & role.hosts).any? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def specified_hosts
|
46
|
+
(specific_hosts || config.all_hosts) \
|
47
|
+
.select { |host| (specific_roles || config.roles).flat_map(&:hosts).include?(host) }
|
48
|
+
end
|
49
|
+
end
|
data/lib/kamal/commander.rb
CHANGED
@@ -3,11 +3,13 @@ require "active_support/core_ext/module/delegation"
|
|
3
3
|
|
4
4
|
class Kamal::Commander
|
5
5
|
attr_accessor :verbosity, :holding_lock, :hold_lock_on_error
|
6
|
+
delegate :hosts, :roles, :primary_host, :primary_role, :roles_on, :traefik_hosts, :accessory_hosts, to: :specifics
|
6
7
|
|
7
8
|
def initialize
|
8
9
|
self.verbosity = :info
|
9
10
|
self.holding_lock = false
|
10
11
|
self.hold_lock_on_error = false
|
12
|
+
@specifics = nil
|
11
13
|
end
|
12
14
|
|
13
15
|
def config
|
@@ -24,10 +26,12 @@ class Kamal::Commander
|
|
24
26
|
attr_reader :specific_roles, :specific_hosts
|
25
27
|
|
26
28
|
def specific_primary!
|
29
|
+
@specifics = nil
|
27
30
|
self.specific_hosts = [ config.primary_host ]
|
28
31
|
end
|
29
32
|
|
30
33
|
def specific_roles=(role_names)
|
34
|
+
@specifics = nil
|
31
35
|
if role_names.present?
|
32
36
|
@specific_roles = Kamal::Utils.filter_specific_items(role_names, config.roles)
|
33
37
|
|
@@ -40,6 +44,7 @@ class Kamal::Commander
|
|
40
44
|
end
|
41
45
|
|
42
46
|
def specific_hosts=(hosts)
|
47
|
+
@specifics = nil
|
43
48
|
if hosts.present?
|
44
49
|
@specific_hosts = Kamal::Utils.filter_specific_items(hosts, config.all_hosts)
|
45
50
|
|
@@ -51,39 +56,6 @@ class Kamal::Commander
|
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
def primary_host
|
55
|
-
# Given a list of specific roles, make an effort to match up with the primary_role
|
56
|
-
specific_hosts&.first || specific_roles&.detect { |role| role.name == config.primary_role }&.primary_host || specific_roles&.first&.primary_host || config.primary_host
|
57
|
-
end
|
58
|
-
|
59
|
-
def primary_role
|
60
|
-
roles_on(primary_host).first
|
61
|
-
end
|
62
|
-
|
63
|
-
def roles
|
64
|
-
(specific_roles || config.roles).select do |role|
|
65
|
-
((specific_hosts || config.all_hosts) & role.hosts).any?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def hosts
|
70
|
-
(specific_hosts || config.all_hosts).select do |host|
|
71
|
-
(specific_roles || config.roles).flat_map(&:hosts).include?(host)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def roles_on(host)
|
76
|
-
roles.select { |role| role.hosts.include?(host.to_s) }.map(&:name)
|
77
|
-
end
|
78
|
-
|
79
|
-
def traefik_hosts
|
80
|
-
specific_hosts || config.traefik_hosts
|
81
|
-
end
|
82
|
-
|
83
|
-
def accessory_hosts
|
84
|
-
specific_hosts || config.accessories.flat_map(&:hosts)
|
85
|
-
end
|
86
|
-
|
87
59
|
def accessory_names
|
88
60
|
config.accessories&.collect(&:name) || []
|
89
61
|
end
|
@@ -181,4 +153,8 @@ class Kamal::Commander
|
|
181
153
|
SSHKit.config.command_map[:docker] = "docker" # No need to use /usr/bin/env, just clogs up the logs
|
182
154
|
SSHKit.config.output_verbosity = verbosity
|
183
155
|
end
|
156
|
+
|
157
|
+
def specifics
|
158
|
+
@specifics ||= Kamal::Commander::Specifics.new(config, specific_hosts, specific_roles)
|
159
|
+
end
|
184
160
|
end
|
@@ -99,11 +99,11 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def make_env_directory
|
102
|
-
make_directory accessory_config.
|
102
|
+
make_directory accessory_config.env.secrets_directory
|
103
103
|
end
|
104
104
|
|
105
105
|
def remove_env_file
|
106
|
-
[:rm, "-f", accessory_config.
|
106
|
+
[ :rm, "-f", accessory_config.env.secrets_file ]
|
107
107
|
end
|
108
108
|
|
109
109
|
private
|
@@ -1,23 +1,23 @@
|
|
1
1
|
module Kamal::Commands::App::Assets
|
2
2
|
def extract_assets
|
3
|
-
asset_container = "#{
|
3
|
+
asset_container = "#{role.container_prefix}-assets"
|
4
4
|
|
5
5
|
combine \
|
6
|
-
make_directory(
|
7
|
-
[*docker(:stop, "-t 1", asset_container, "2> /dev/null"), "|| true"],
|
8
|
-
docker(:run, "--name", asset_container, "--detach", "--rm", config.
|
9
|
-
docker(:cp, "-L", "#{asset_container}:#{
|
6
|
+
make_directory(role.asset_extracted_path),
|
7
|
+
[ *docker(:stop, "-t 1", asset_container, "2> /dev/null"), "|| true" ],
|
8
|
+
docker(:run, "--name", asset_container, "--detach", "--rm", config.absolute_image, "sleep 1000000"),
|
9
|
+
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_path),
|
10
10
|
docker(:stop, "-t 1", asset_container),
|
11
11
|
by: "&&"
|
12
12
|
end
|
13
13
|
|
14
14
|
def sync_asset_volumes(old_version: nil)
|
15
|
-
new_extracted_path, new_volume_path =
|
15
|
+
new_extracted_path, new_volume_path = role.asset_extracted_path(config.version), role.asset_volume.host_path
|
16
16
|
if old_version.present?
|
17
|
-
old_extracted_path, old_volume_path =
|
17
|
+
old_extracted_path, old_volume_path = role.asset_extracted_path(old_version), role.asset_volume(old_version).host_path
|
18
18
|
end
|
19
19
|
|
20
|
-
commands = [make_directory(new_volume_path), copy_contents(new_extracted_path, new_volume_path)]
|
20
|
+
commands = [ make_directory(new_volume_path), copy_contents(new_extracted_path, new_volume_path) ]
|
21
21
|
|
22
22
|
if old_version.present?
|
23
23
|
commands << copy_contents(new_extracted_path, old_volume_path, continue_on_error: true)
|
@@ -29,8 +29,8 @@ module Kamal::Commands::App::Assets
|
|
29
29
|
|
30
30
|
def clean_up_assets
|
31
31
|
chain \
|
32
|
-
find_and_remove_older_siblings(
|
33
|
-
find_and_remove_older_siblings(
|
32
|
+
find_and_remove_older_siblings(role.asset_extracted_path),
|
33
|
+
find_and_remove_older_siblings(role.asset_volume_path)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
@@ -39,13 +39,13 @@ module Kamal::Commands::App::Assets
|
|
39
39
|
:find,
|
40
40
|
Pathname.new(path).dirname.to_s,
|
41
41
|
"-maxdepth 1",
|
42
|
-
"-name", "'#{
|
42
|
+
"-name", "'#{role.container_prefix}-*'",
|
43
43
|
"!", "-name", Pathname.new(path).basename.to_s,
|
44
44
|
"-exec rm -rf \"{}\" +"
|
45
45
|
]
|
46
46
|
end
|
47
47
|
|
48
48
|
def copy_contents(source, destination, continue_on_error: false)
|
49
|
-
[ :cp, "-rnT", "#{source}", destination, *("|| true" if continue_on_error)]
|
49
|
+
[ :cp, "-rnT", "#{source}", destination, *("|| true" if continue_on_error) ]
|
50
50
|
end
|
51
51
|
end
|
@@ -2,7 +2,7 @@ module Kamal::Commands::App::Cord
|
|
2
2
|
def cord(version:)
|
3
3
|
pipe \
|
4
4
|
docker(:inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", container_name(version)),
|
5
|
-
[:awk, "'$2 == \"#{
|
5
|
+
[ :awk, "'$2 == \"#{role.cord_volume.container_path}\" {print $1}'" ]
|
6
6
|
end
|
7
7
|
|
8
8
|
def tie_cord(cord)
|
@@ -12,11 +12,11 @@ module Kamal::Commands::App::Cord
|
|
12
12
|
def cut_cord(cord)
|
13
13
|
remove_directory(cord)
|
14
14
|
end
|
15
|
-
|
16
|
-
private
|
15
|
+
|
16
|
+
private
|
17
17
|
def create_empty_file(file)
|
18
18
|
chain \
|
19
19
|
make_directory_for(file),
|
20
|
-
[:touch, file]
|
20
|
+
[ :touch, file ]
|
21
21
|
end
|
22
22
|
end
|
@@ -1,27 +1,29 @@
|
|
1
1
|
module Kamal::Commands::App::Execution
|
2
|
-
def execute_in_existing_container(*command, interactive: false)
|
2
|
+
def execute_in_existing_container(*command, interactive: false, env:)
|
3
3
|
docker :exec,
|
4
4
|
("-it" if interactive),
|
5
|
+
*argumentize("--env", env),
|
5
6
|
container_name,
|
6
7
|
*command
|
7
8
|
end
|
8
9
|
|
9
|
-
def execute_in_new_container(*command, interactive: false)
|
10
|
+
def execute_in_new_container(*command, interactive: false, env:)
|
10
11
|
docker :run,
|
11
12
|
("-it" if interactive),
|
12
13
|
"--rm",
|
13
|
-
*
|
14
|
+
*role&.env_args,
|
15
|
+
*argumentize("--env", env),
|
14
16
|
*config.volume_args,
|
15
|
-
*
|
17
|
+
*role&.option_args,
|
16
18
|
config.absolute_image,
|
17
19
|
*command
|
18
20
|
end
|
19
21
|
|
20
|
-
def execute_in_existing_container_over_ssh(*command, host:)
|
21
|
-
run_over_ssh execute_in_existing_container(*command, interactive: true), host: host
|
22
|
+
def execute_in_existing_container_over_ssh(*command, host:, env:)
|
23
|
+
run_over_ssh execute_in_existing_container(*command, interactive: true, env: env), host: host
|
22
24
|
end
|
23
25
|
|
24
|
-
def execute_in_new_container_over_ssh(*command, host:)
|
25
|
-
run_over_ssh execute_in_new_container(*command, interactive: true), host: host
|
26
|
+
def execute_in_new_container_over_ssh(*command, host:, env:)
|
27
|
+
run_over_ssh execute_in_new_container(*command, interactive: true, env: env), host: host
|
26
28
|
end
|
27
29
|
end
|
@@ -6,11 +6,11 @@ module Kamal::Commands::App::Logging
|
|
6
6
|
("grep '#{grep}'" if grep)
|
7
7
|
end
|
8
8
|
|
9
|
-
def follow_logs(host:, grep: nil)
|
9
|
+
def follow_logs(host:, lines: nil, grep: nil)
|
10
10
|
run_over_ssh \
|
11
11
|
pipe(
|
12
12
|
current_running_container_id,
|
13
|
-
"xargs docker logs --timestamps --tail
|
13
|
+
"xargs docker logs --timestamps#{" --tail #{lines}" if lines} --follow 2>&1",
|
14
14
|
(%(grep "#{grep}") if grep)
|
15
15
|
),
|
16
16
|
host: host
|
data/lib/kamal/commands/app.rb
CHANGED
@@ -3,12 +3,11 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
3
3
|
|
4
4
|
ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
|
5
5
|
|
6
|
-
attr_reader :role, :
|
6
|
+
attr_reader :role, :role
|
7
7
|
|
8
8
|
def initialize(config, role: nil)
|
9
9
|
super(config)
|
10
10
|
@role = role
|
11
|
-
@role_config = config.role(self.role)
|
12
11
|
end
|
13
12
|
|
14
13
|
def run(hostname: nil)
|
@@ -16,18 +15,18 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
16
15
|
"--detach",
|
17
16
|
"--restart unless-stopped",
|
18
17
|
"--name", container_name,
|
19
|
-
*(["--hostname", hostname] if hostname),
|
18
|
+
*([ "--hostname", hostname ] if hostname),
|
20
19
|
"-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
21
20
|
"-e", "KAMAL_VERSION=\"#{config.version}\"",
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
21
|
+
*role.env_args,
|
22
|
+
*role.health_check_args,
|
23
|
+
*role.logging_args,
|
25
24
|
*config.volume_args,
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
25
|
+
*role.asset_volume_args,
|
26
|
+
*role.label_args,
|
27
|
+
*role.option_args,
|
29
28
|
config.absolute_image,
|
30
|
-
|
29
|
+
role.cmd
|
31
30
|
end
|
32
31
|
|
33
32
|
def start
|
@@ -50,7 +49,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
50
49
|
|
51
50
|
|
52
51
|
def current_running_container_id
|
53
|
-
|
52
|
+
current_running_container(format: "--quiet")
|
54
53
|
end
|
55
54
|
|
56
55
|
def container_id_for_version(version, only_running: false)
|
@@ -58,36 +57,57 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
58
57
|
end
|
59
58
|
|
60
59
|
def current_running_version
|
61
|
-
|
60
|
+
pipe \
|
61
|
+
current_running_container(format: "--format '{{.Names}}'"),
|
62
|
+
extract_version_from_name
|
62
63
|
end
|
63
64
|
|
64
65
|
def list_versions(*docker_args, statuses: nil)
|
65
66
|
pipe \
|
66
67
|
docker(:ps, *filter_args(statuses: statuses), *docker_args, "--format", '"{{.Names}}"'),
|
67
|
-
|
68
|
+
extract_version_from_name
|
68
69
|
end
|
69
70
|
|
70
71
|
|
71
72
|
def make_env_directory
|
72
|
-
make_directory
|
73
|
+
make_directory role.env.secrets_directory
|
73
74
|
end
|
74
75
|
|
75
76
|
def remove_env_file
|
76
|
-
[ :rm, "-f",
|
77
|
+
[ :rm, "-f", role.env.secrets_file ]
|
77
78
|
end
|
78
79
|
|
79
80
|
|
80
81
|
private
|
81
82
|
def container_name(version = nil)
|
82
|
-
[
|
83
|
+
[ role.container_prefix, version || config.version ].compact.join("-")
|
84
|
+
end
|
85
|
+
|
86
|
+
def latest_image_id
|
87
|
+
docker :image, :ls, *argumentize("--filter", "reference=#{config.latest_image}"), "--format", "'{{.ID}}'"
|
88
|
+
end
|
89
|
+
|
90
|
+
def current_running_container(format:)
|
91
|
+
pipe \
|
92
|
+
shell(chain(latest_image_container(format: format), latest_container(format: format))),
|
93
|
+
[ :head, "-1" ]
|
94
|
+
end
|
95
|
+
|
96
|
+
def latest_image_container(format:)
|
97
|
+
latest_container format: format, filters: [ "ancestor=$(#{latest_image_id.join(" ")})" ]
|
98
|
+
end
|
99
|
+
|
100
|
+
def latest_container(format:, filters: nil)
|
101
|
+
docker :ps, "--latest", *format, *filter_args(statuses: ACTIVE_DOCKER_STATUSES), argumentize("--filter", filters)
|
83
102
|
end
|
84
103
|
|
85
104
|
def filter_args(statuses: nil)
|
86
105
|
argumentize "--filter", filters(statuses: statuses)
|
87
106
|
end
|
88
107
|
|
89
|
-
def
|
90
|
-
|
108
|
+
def extract_version_from_name
|
109
|
+
# Extract SHA from "service-role-dest-SHA"
|
110
|
+
%(while read line; do echo ${line##{role.container_prefix}-}; done)
|
91
111
|
end
|
92
112
|
|
93
113
|
def filters(statuses: nil)
|
@@ -21,7 +21,7 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
|
|
21
21
|
def audit_log_file
|
22
22
|
file = [ config.service, config.destination, "audit.log" ].compact.join("-")
|
23
23
|
|
24
|
-
|
24
|
+
File.join(config.run_directory, file)
|
25
25
|
end
|
26
26
|
|
27
27
|
def audit_tags(**details)
|
data/lib/kamal/commands/base.rb
CHANGED
@@ -62,14 +62,26 @@ module Kamal::Commands
|
|
62
62
|
combine *commands, by: ">"
|
63
63
|
end
|
64
64
|
|
65
|
+
def any(*commands)
|
66
|
+
combine *commands, by: "||"
|
67
|
+
end
|
68
|
+
|
65
69
|
def xargs(command)
|
66
70
|
[ :xargs, command ].flatten
|
67
71
|
end
|
68
72
|
|
73
|
+
def shell(command)
|
74
|
+
[ :sh, "-c", "'#{command.flatten.join(" ").gsub("'", "'\\\\''")}'" ]
|
75
|
+
end
|
76
|
+
|
69
77
|
def docker(*args)
|
70
78
|
args.compact.unshift :docker
|
71
79
|
end
|
72
80
|
|
81
|
+
def git(*args)
|
82
|
+
args.compact.unshift :git
|
83
|
+
end
|
84
|
+
|
73
85
|
def tags(**details)
|
74
86
|
Kamal::Tags.from_config(config, **details)
|
75
87
|
end
|
@@ -3,7 +3,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
3
3
|
class BuilderError < StandardError; end
|
4
4
|
|
5
5
|
delegate :argumentize, to: Kamal::Utils
|
6
|
-
delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, to: :builder_config
|
6
|
+
delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, :git_archive?, to: :builder_config
|
7
7
|
|
8
8
|
def clean
|
9
9
|
docker :image, :rm, "--force", config.absolute_image
|
@@ -13,8 +13,18 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
13
13
|
docker :pull, config.absolute_image
|
14
14
|
end
|
15
15
|
|
16
|
+
def push
|
17
|
+
if git_archive?
|
18
|
+
pipe \
|
19
|
+
git(:archive, "--format=tar", :HEAD),
|
20
|
+
build_and_push
|
21
|
+
else
|
22
|
+
build_and_push
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
16
26
|
def build_options
|
17
|
-
[ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile ]
|
27
|
+
[ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_ssh ]
|
18
28
|
end
|
19
29
|
|
20
30
|
def build_context
|
@@ -24,7 +34,10 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
24
34
|
def validate_image
|
25
35
|
pipe \
|
26
36
|
docker(:inspect, "-f", "'{{ .Config.Labels.service }}'", config.absolute_image),
|
27
|
-
|
37
|
+
any(
|
38
|
+
[ :grep, "-x", config.service ],
|
39
|
+
"(echo \"Image #{config.absolute_image} is missing the 'service' label\" && exit 1)"
|
40
|
+
)
|
28
41
|
end
|
29
42
|
|
30
43
|
|
@@ -35,8 +48,8 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
35
48
|
|
36
49
|
def build_cache
|
37
50
|
if cache_to && cache_from
|
38
|
-
["--cache-to", cache_to,
|
39
|
-
"--cache-from", cache_from]
|
51
|
+
[ "--cache-to", cache_to,
|
52
|
+
"--cache-from", cache_from ]
|
40
53
|
end
|
41
54
|
end
|
42
55
|
|
@@ -60,6 +73,10 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
60
73
|
end
|
61
74
|
end
|
62
75
|
|
76
|
+
def build_ssh
|
77
|
+
argumentize "--ssh", ssh if ssh.present?
|
78
|
+
end
|
79
|
+
|
63
80
|
def builder_config
|
64
81
|
config.builder
|
65
82
|
end
|
@@ -7,15 +7,6 @@ class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base
|
|
7
7
|
docker :buildx, :rm, builder_name
|
8
8
|
end
|
9
9
|
|
10
|
-
def push
|
11
|
-
docker :buildx, :build,
|
12
|
-
"--push",
|
13
|
-
"--platform", "linux/amd64,linux/arm64",
|
14
|
-
"--builder", builder_name,
|
15
|
-
*build_options,
|
16
|
-
build_context
|
17
|
-
end
|
18
|
-
|
19
10
|
def info
|
20
11
|
combine \
|
21
12
|
docker(:context, :ls),
|
@@ -26,4 +17,21 @@ class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base
|
|
26
17
|
def builder_name
|
27
18
|
"kamal-#{config.service}-multiarch"
|
28
19
|
end
|
20
|
+
|
21
|
+
def platform_names
|
22
|
+
if local_arch
|
23
|
+
"linux/#{local_arch}"
|
24
|
+
else
|
25
|
+
"linux/amd64,linux/arm64"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_and_push
|
30
|
+
docker :buildx, :build,
|
31
|
+
"--push",
|
32
|
+
"--platform", platform_names,
|
33
|
+
"--builder", builder_name,
|
34
|
+
*build_options,
|
35
|
+
build_context
|
36
|
+
end
|
29
37
|
end
|
@@ -7,10 +7,11 @@ class Kamal::Commands::Builder::Native::Cached < Kamal::Commands::Builder::Nativ
|
|
7
7
|
docker :buildx, :rm, builder_name
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
private
|
11
|
+
def build_and_push
|
12
|
+
docker :buildx, :build,
|
13
|
+
"--push",
|
14
|
+
*build_options,
|
15
|
+
build_context
|
16
|
+
end
|
16
17
|
end
|
@@ -11,15 +11,6 @@ class Kamal::Commands::Builder::Native::Remote < Kamal::Commands::Builder::Nativ
|
|
11
11
|
remove_buildx
|
12
12
|
end
|
13
13
|
|
14
|
-
def push
|
15
|
-
docker :buildx, :build,
|
16
|
-
"--push",
|
17
|
-
"--platform", platform,
|
18
|
-
"--builder", builder_name,
|
19
|
-
*build_options,
|
20
|
-
build_context
|
21
|
-
end
|
22
|
-
|
23
14
|
def info
|
24
15
|
chain \
|
25
16
|
docker(:context, :ls),
|
@@ -56,4 +47,13 @@ class Kamal::Commands::Builder::Native::Remote < Kamal::Commands::Builder::Nativ
|
|
56
47
|
def remove_buildx
|
57
48
|
docker :buildx, :rm, builder_name
|
58
49
|
end
|
50
|
+
|
51
|
+
def build_and_push
|
52
|
+
docker :buildx, :build,
|
53
|
+
"--push",
|
54
|
+
"--platform", platform,
|
55
|
+
"--builder", builder_name,
|
56
|
+
*build_options,
|
57
|
+
build_context
|
58
|
+
end
|
59
59
|
end
|
@@ -7,14 +7,15 @@ class Kamal::Commands::Builder::Native < Kamal::Commands::Builder::Base
|
|
7
7
|
# No-op on native without cache
|
8
8
|
end
|
9
9
|
|
10
|
-
def push
|
11
|
-
combine \
|
12
|
-
docker(:build, *build_options, build_context),
|
13
|
-
docker(:push, config.absolute_image),
|
14
|
-
docker(:push, config.latest_image)
|
15
|
-
end
|
16
|
-
|
17
10
|
def info
|
18
11
|
# No-op on native
|
19
12
|
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def build_and_push
|
16
|
+
combine \
|
17
|
+
docker(:build, *build_options, build_context),
|
18
|
+
docker(:push, config.absolute_image),
|
19
|
+
docker(:push, config.latest_image)
|
20
|
+
end
|
20
21
|
end
|