kamal 1.5.2 → 1.7.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kamal/cli/accessory.rb +30 -24
  3. data/lib/kamal/cli/app/boot.rb +70 -18
  4. data/lib/kamal/cli/app/prepare_assets.rb +1 -1
  5. data/lib/kamal/cli/app.rb +60 -47
  6. data/lib/kamal/cli/base.rb +26 -28
  7. data/lib/kamal/cli/build/clone.rb +61 -0
  8. data/lib/kamal/cli/build.rb +64 -53
  9. data/lib/kamal/cli/env.rb +5 -5
  10. data/lib/kamal/cli/healthcheck/barrier.rb +31 -0
  11. data/lib/kamal/cli/healthcheck/error.rb +2 -0
  12. data/lib/kamal/cli/healthcheck/poller.rb +6 -7
  13. data/lib/kamal/cli/main.rb +49 -44
  14. data/lib/kamal/cli/prune.rb +3 -3
  15. data/lib/kamal/cli/registry.rb +9 -10
  16. data/lib/kamal/cli/server.rb +39 -15
  17. data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +1 -1
  18. data/lib/kamal/cli/traefik.rb +13 -11
  19. data/lib/kamal/cli.rb +1 -1
  20. data/lib/kamal/commander.rb +6 -6
  21. data/lib/kamal/commands/accessory.rb +4 -4
  22. data/lib/kamal/commands/app/containers.rb +8 -0
  23. data/lib/kamal/commands/app/execution.rb +3 -3
  24. data/lib/kamal/commands/app/logging.rb +5 -5
  25. data/lib/kamal/commands/app.rb +6 -5
  26. data/lib/kamal/commands/base.rb +2 -3
  27. data/lib/kamal/commands/builder/base.rb +19 -12
  28. data/lib/kamal/commands/builder/clone.rb +28 -0
  29. data/lib/kamal/commands/builder/multiarch/remote.rb +10 -0
  30. data/lib/kamal/commands/builder/multiarch.rb +13 -9
  31. data/lib/kamal/commands/builder/native/cached.rb +14 -6
  32. data/lib/kamal/commands/builder/native/remote.rb +17 -9
  33. data/lib/kamal/commands/builder/native.rb +6 -7
  34. data/lib/kamal/commands/builder.rb +19 -11
  35. data/lib/kamal/commands/registry.rb +4 -13
  36. data/lib/kamal/commands/traefik.rb +8 -47
  37. data/lib/kamal/configuration/accessory.rb +30 -41
  38. data/lib/kamal/configuration/boot.rb +9 -4
  39. data/lib/kamal/configuration/builder.rb +61 -30
  40. data/lib/kamal/configuration/docs/accessory.yml +90 -0
  41. data/lib/kamal/configuration/docs/boot.yml +19 -0
  42. data/lib/kamal/configuration/docs/builder.yml +107 -0
  43. data/lib/kamal/configuration/docs/configuration.yml +157 -0
  44. data/lib/kamal/configuration/docs/env.yml +72 -0
  45. data/lib/kamal/configuration/docs/healthcheck.yml +59 -0
  46. data/lib/kamal/configuration/docs/logging.yml +21 -0
  47. data/lib/kamal/configuration/docs/registry.yml +49 -0
  48. data/lib/kamal/configuration/docs/role.yml +52 -0
  49. data/lib/kamal/configuration/docs/servers.yml +27 -0
  50. data/lib/kamal/configuration/docs/ssh.yml +46 -0
  51. data/lib/kamal/configuration/docs/sshkit.yml +23 -0
  52. data/lib/kamal/configuration/docs/traefik.yml +62 -0
  53. data/lib/kamal/configuration/env/tag.rb +12 -0
  54. data/lib/kamal/configuration/env.rb +10 -14
  55. data/lib/kamal/configuration/healthcheck.rb +63 -0
  56. data/lib/kamal/configuration/logging.rb +33 -0
  57. data/lib/kamal/configuration/registry.rb +31 -0
  58. data/lib/kamal/configuration/role.rb +72 -61
  59. data/lib/kamal/configuration/servers.rb +18 -0
  60. data/lib/kamal/configuration/ssh.rb +11 -8
  61. data/lib/kamal/configuration/sshkit.rb +9 -7
  62. data/lib/kamal/configuration/traefik.rb +60 -0
  63. data/lib/kamal/configuration/validation.rb +27 -0
  64. data/lib/kamal/configuration/validator/accessory.rb +9 -0
  65. data/lib/kamal/configuration/validator/builder.rb +9 -0
  66. data/lib/kamal/configuration/validator/env.rb +54 -0
  67. data/lib/kamal/configuration/validator/registry.rb +25 -0
  68. data/lib/kamal/configuration/validator/role.rb +11 -0
  69. data/lib/kamal/configuration/validator/servers.rb +7 -0
  70. data/lib/kamal/configuration/validator.rb +140 -0
  71. data/lib/kamal/configuration.rb +50 -63
  72. data/lib/kamal/git.rb +4 -0
  73. data/lib/kamal/sshkit_with_ext.rb +36 -0
  74. data/lib/kamal/version.rb +1 -1
  75. data/lib/kamal.rb +2 -0
  76. metadata +64 -9
  77. data/lib/kamal/cli/healthcheck.rb +0 -21
  78. data/lib/kamal/commands/healthcheck.rb +0 -59
@@ -1,7 +1,7 @@
1
1
  class Kamal::Cli::Traefik < Kamal::Cli::Base
2
2
  desc "boot", "Boot Traefik on servers"
3
3
  def boot
4
- mutating do
4
+ with_lock do
5
5
  on(KAMAL.traefik_hosts) do
6
6
  execute *KAMAL.registry.login
7
7
  execute *KAMAL.traefik.start_or_run
@@ -14,7 +14,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
14
14
  option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
15
15
  def reboot
16
16
  confirming "This will cause a brief outage on each host. Are you sure?" do
17
- mutating do
17
+ with_lock do
18
18
  host_groups = options[:rolling] ? KAMAL.traefik_hosts : [ KAMAL.traefik_hosts ]
19
19
  host_groups.each do |hosts|
20
20
  host_list = Array(hosts).join(",")
@@ -34,7 +34,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
34
34
 
35
35
  desc "start", "Start existing Traefik container on servers"
36
36
  def start
37
- mutating do
37
+ with_lock do
38
38
  on(KAMAL.traefik_hosts) do
39
39
  execute *KAMAL.auditor.record("Started traefik"), verbosity: :debug
40
40
  execute *KAMAL.traefik.start
@@ -44,7 +44,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
44
44
 
45
45
  desc "stop", "Stop existing Traefik container on servers"
46
46
  def stop
47
- mutating do
47
+ with_lock do
48
48
  on(KAMAL.traefik_hosts) do
49
49
  execute *KAMAL.auditor.record("Stopped traefik"), verbosity: :debug
50
50
  execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
@@ -54,7 +54,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
54
54
 
55
55
  desc "restart", "Restart existing Traefik container on servers"
56
56
  def restart
57
- mutating do
57
+ with_lock do
58
58
  stop
59
59
  start
60
60
  end
@@ -69,29 +69,31 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
69
69
  option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)"
70
70
  option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server"
71
71
  option :grep, aliases: "-g", desc: "Show lines with grep match only (use this to fetch specific requests by id)"
72
+ option :grep_options, aliases: "-o", desc: "Additional options supplied to grep"
72
73
  option :follow, aliases: "-f", desc: "Follow logs on primary server (or specific host set by --hosts)"
73
74
  def logs
74
75
  grep = options[:grep]
76
+ grep_options = options[:grep_options]
75
77
 
76
78
  if options[:follow]
77
79
  run_locally do
78
80
  info "Following logs on #{KAMAL.primary_host}..."
79
- info KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep)
80
- exec KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep)
81
+ info KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
82
+ exec KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
81
83
  end
82
84
  else
83
85
  since = options[:since]
84
86
  lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
85
87
 
86
88
  on(KAMAL.traefik_hosts) do |host|
87
- puts_by_host host, capture(*KAMAL.traefik.logs(since: since, lines: lines, grep: grep)), type: "Traefik"
89
+ puts_by_host host, capture(*KAMAL.traefik.logs(since: since, lines: lines, grep: grep, grep_options: grep_options)), type: "Traefik"
88
90
  end
89
91
  end
90
92
  end
91
93
 
92
94
  desc "remove", "Remove Traefik container and image from servers"
93
95
  def remove
94
- mutating do
96
+ with_lock do
95
97
  stop
96
98
  remove_container
97
99
  remove_image
@@ -100,7 +102,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
100
102
 
101
103
  desc "remove_container", "Remove Traefik container from servers", hide: true
102
104
  def remove_container
103
- mutating do
105
+ with_lock do
104
106
  on(KAMAL.traefik_hosts) do
105
107
  execute *KAMAL.auditor.record("Removed traefik container"), verbosity: :debug
106
108
  execute *KAMAL.traefik.remove_container
@@ -110,7 +112,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
110
112
 
111
113
  desc "remove_image", "Remove Traefik image from servers", hide: true
112
114
  def remove_image
113
- mutating do
115
+ with_lock do
114
116
  on(KAMAL.traefik_hosts) do
115
117
  execute *KAMAL.auditor.record("Removed traefik image"), verbosity: :debug
116
118
  execute *KAMAL.traefik.remove_image
data/lib/kamal/cli.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Kamal::Cli
2
- class LockError < StandardError; end
3
2
  class HookError < StandardError; end
3
+ class LockError < StandardError; end
4
4
  end
5
5
 
6
6
  # SSHKit uses instance eval, so we need a global const for ergonomics
@@ -2,13 +2,13 @@ require "active_support/core_ext/enumerable"
2
2
  require "active_support/core_ext/module/delegation"
3
3
 
4
4
  class Kamal::Commander
5
- attr_accessor :verbosity, :holding_lock, :hold_lock_on_error
5
+ attr_accessor :verbosity, :holding_lock, :connected
6
6
  delegate :hosts, :roles, :primary_host, :primary_role, :roles_on, :traefik_hosts, :accessory_hosts, to: :specifics
7
7
 
8
8
  def initialize
9
9
  self.verbosity = :info
10
10
  self.holding_lock = false
11
- self.hold_lock_on_error = false
11
+ self.connected = false
12
12
  @specifics = nil
13
13
  end
14
14
 
@@ -65,8 +65,8 @@ class Kamal::Commander
65
65
  end
66
66
 
67
67
 
68
- def app(role: nil)
69
- Kamal::Commands::App.new(config, role: role)
68
+ def app(role: nil, host: nil)
69
+ Kamal::Commands::App.new(config, role: role, host: host)
70
70
  end
71
71
 
72
72
  def accessory(name)
@@ -138,8 +138,8 @@ class Kamal::Commander
138
138
  self.holding_lock
139
139
  end
140
140
 
141
- def hold_lock_on_error?
142
- self.hold_lock_on_error
141
+ def connected?
142
+ self.connected
143
143
  end
144
144
 
145
145
  private
@@ -36,17 +36,17 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
36
36
  end
37
37
 
38
38
 
39
- def logs(since: nil, lines: nil, grep: nil)
39
+ def logs(since: nil, lines: nil, grep: nil, grep_options: nil)
40
40
  pipe \
41
41
  docker(:logs, service_name, (" --since #{since}" if since), (" --tail #{lines}" if lines), "--timestamps", "2>&1"),
42
- ("grep '#{grep}'" if grep)
42
+ ("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
43
43
  end
44
44
 
45
- def follow_logs(grep: nil)
45
+ def follow_logs(grep: nil, grep_options: nil)
46
46
  run_over_ssh \
47
47
  pipe \
48
48
  docker(:logs, service_name, "--timestamps", "--tail", "10", "--follow", "2>&1"),
49
- (%(grep "#{grep}") if grep)
49
+ (%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
50
50
  end
51
51
 
52
52
 
@@ -1,4 +1,6 @@
1
1
  module Kamal::Commands::App::Containers
2
+ DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
3
+
2
4
  def list_containers
3
5
  docker :container, :ls, "--all", *filter_args
4
6
  end
@@ -20,4 +22,10 @@ module Kamal::Commands::App::Containers
20
22
  def remove_containers
21
23
  docker :container, :prune, "--force", *filter_args
22
24
  end
25
+
26
+ def container_health_log(version:)
27
+ pipe \
28
+ container_id_for(container_name: container_name(version)),
29
+ xargs(docker(:inspect, "--format", DOCKER_HEALTH_LOG_FORMAT))
30
+ end
23
31
  end
@@ -11,7 +11,7 @@ module Kamal::Commands::App::Execution
11
11
  docker :run,
12
12
  ("-it" if interactive),
13
13
  "--rm",
14
- *role&.env_args,
14
+ *role&.env_args(host),
15
15
  *argumentize("--env", env),
16
16
  *config.volume_args,
17
17
  *role&.option_args,
@@ -19,11 +19,11 @@ module Kamal::Commands::App::Execution
19
19
  *command
20
20
  end
21
21
 
22
- def execute_in_existing_container_over_ssh(*command, host:, env:)
22
+ def execute_in_existing_container_over_ssh(*command, env:)
23
23
  run_over_ssh execute_in_existing_container(*command, interactive: true, env: env), host: host
24
24
  end
25
25
 
26
- def execute_in_new_container_over_ssh(*command, host:, env:)
26
+ def execute_in_new_container_over_ssh(*command, env:)
27
27
  run_over_ssh execute_in_new_container(*command, interactive: true, env: env), host: host
28
28
  end
29
29
  end
@@ -1,17 +1,17 @@
1
1
  module Kamal::Commands::App::Logging
2
- def logs(since: nil, lines: nil, grep: nil)
2
+ def logs(version: nil, since: nil, lines: nil, grep: nil, grep_options: nil)
3
3
  pipe \
4
- current_running_container_id,
4
+ version ? container_id_for_version(version) : current_running_container_id,
5
5
  "xargs docker logs#{" --since #{since}" if since}#{" --tail #{lines}" if lines} 2>&1",
6
- ("grep '#{grep}'" if grep)
6
+ ("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
7
7
  end
8
8
 
9
- def follow_logs(host:, lines: nil, grep: nil)
9
+ def follow_logs(host:, lines: nil, grep: nil, grep_options: nil)
10
10
  run_over_ssh \
11
11
  pipe(
12
12
  current_running_container_id,
13
13
  "xargs docker logs --timestamps#{" --tail #{lines}" if lines} --follow 2>&1",
14
- (%(grep "#{grep}") if grep)
14
+ (%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
15
15
  ),
16
16
  host: host
17
17
  end
@@ -3,11 +3,12 @@ class Kamal::Commands::App < Kamal::Commands::Base
3
3
 
4
4
  ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
5
5
 
6
- attr_reader :role, :role
6
+ attr_reader :role, :host
7
7
 
8
- def initialize(config, role: nil)
8
+ def initialize(config, role: nil, host: nil)
9
9
  super(config)
10
10
  @role = role
11
+ @host = host
11
12
  end
12
13
 
13
14
  def run(hostname: nil)
@@ -18,7 +19,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
18
19
  *([ "--hostname", hostname ] if hostname),
19
20
  "-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
20
21
  "-e", "KAMAL_VERSION=\"#{config.version}\"",
21
- *role.env_args,
22
+ *role.env_args(host),
22
23
  *role.health_check_args,
23
24
  *role.logging_args,
24
25
  *config.volume_args,
@@ -70,11 +71,11 @@ class Kamal::Commands::App < Kamal::Commands::Base
70
71
 
71
72
 
72
73
  def make_env_directory
73
- make_directory role.env.secrets_directory
74
+ make_directory role.env(host).secrets_directory
74
75
  end
75
76
 
76
77
  def remove_env_file
77
- [ :rm, "-f", role.env.secrets_file ]
78
+ [ :rm, "-f", role.env(host).secrets_file ]
78
79
  end
79
80
 
80
81
 
@@ -3,7 +3,6 @@ module Kamal::Commands
3
3
  delegate :sensitive, :argumentize, to: Kamal::Utils
4
4
 
5
5
  DOCKER_HEALTH_STATUS_FORMAT = "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'"
6
- DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
7
6
 
8
7
  attr_accessor :config
9
8
 
@@ -78,8 +77,8 @@ module Kamal::Commands
78
77
  args.compact.unshift :docker
79
78
  end
80
79
 
81
- def git(*args)
82
- args.compact.unshift :git
80
+ def git(*args, path: nil)
81
+ [ :git, *([ "-C", path ] if path), *args.compact ]
83
82
  end
84
83
 
85
84
  def tags(**details)
@@ -2,8 +2,10 @@
2
2
  class Kamal::Commands::Builder::Base < Kamal::Commands::Base
3
3
  class BuilderError < StandardError; end
4
4
 
5
+ ENDPOINT_DOCKER_HOST_INSPECT = "'{{.Endpoints.docker.Host}}'"
6
+
5
7
  delegate :argumentize, to: Kamal::Utils
6
- delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, :git_archive?, to: :builder_config
8
+ delegate :args, :secrets, :dockerfile, :target, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, to: :builder_config
7
9
 
8
10
  def clean
9
11
  docker :image, :rm, "--force", config.absolute_image
@@ -13,18 +15,8 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
13
15
  docker :pull, config.absolute_image
14
16
  end
15
17
 
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
-
26
18
  def build_options
27
- [ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_ssh ]
19
+ [ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_target, *build_ssh ]
28
20
  end
29
21
 
30
22
  def build_context
@@ -40,6 +32,13 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
40
32
  )
41
33
  end
42
34
 
35
+ def context_hosts
36
+ :true
37
+ end
38
+
39
+ def config_context_hosts
40
+ []
41
+ end
43
42
 
44
43
  private
45
44
  def build_tags
@@ -73,6 +72,10 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
73
72
  end
74
73
  end
75
74
 
75
+ def build_target
76
+ argumentize "--target", target if target.present?
77
+ end
78
+
76
79
  def build_ssh
77
80
  argumentize "--ssh", ssh if ssh.present?
78
81
  end
@@ -80,4 +83,8 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
80
83
  def builder_config
81
84
  config.builder
82
85
  end
86
+
87
+ def context_host(builder_name)
88
+ docker :context, :inspect, builder_name, "--format", ENDPOINT_DOCKER_HOST_INSPECT
89
+ end
83
90
  end
@@ -0,0 +1,28 @@
1
+ module Kamal::Commands::Builder::Clone
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ delegate :clone_directory, :build_directory, to: :"config.builder"
6
+ end
7
+
8
+ def clone
9
+ git :clone, Kamal::Git.root, path: clone_directory
10
+ end
11
+
12
+ def clone_reset_steps
13
+ [
14
+ git(:remote, "set-url", :origin, Kamal::Git.root, path: build_directory),
15
+ git(:fetch, :origin, path: build_directory),
16
+ git(:reset, "--hard", Kamal::Git.revision, path: build_directory),
17
+ git(:clean, "-fdx", path: build_directory)
18
+ ]
19
+ end
20
+
21
+ def clone_status
22
+ git :status, "--porcelain", path: build_directory
23
+ end
24
+
25
+ def clone_revision
26
+ git :"rev-parse", :HEAD, path: build_directory
27
+ end
28
+ end
@@ -12,6 +12,16 @@ class Kamal::Commands::Builder::Multiarch::Remote < Kamal::Commands::Builder::Mu
12
12
  super
13
13
  end
14
14
 
15
+ def context_hosts
16
+ chain \
17
+ context_host(builder_name_with_arch(local_arch)),
18
+ context_host(builder_name_with_arch(remote_arch))
19
+ end
20
+
21
+ def config_context_hosts
22
+ [ local_host, remote_host ].compact
23
+ end
24
+
15
25
  private
16
26
  def builder_name
17
27
  super + "-remote"
@@ -13,6 +13,19 @@ class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base
13
13
  docker(:buildx, :ls)
14
14
  end
15
15
 
16
+ def push
17
+ docker :buildx, :build,
18
+ "--push",
19
+ "--platform", platform_names,
20
+ "--builder", builder_name,
21
+ *build_options,
22
+ build_context
23
+ end
24
+
25
+ def context_hosts
26
+ docker :buildx, :inspect, builder_name, "> /dev/null"
27
+ end
28
+
16
29
  private
17
30
  def builder_name
18
31
  "kamal-#{config.service}-multiarch"
@@ -25,13 +38,4 @@ class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base
25
38
  "linux/amd64,linux/arm64"
26
39
  end
27
40
  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
37
41
  end
@@ -1,17 +1,25 @@
1
1
  class Kamal::Commands::Builder::Native::Cached < Kamal::Commands::Builder::Native
2
2
  def create
3
- docker :buildx, :create, "--use", "--driver=docker-container"
3
+ docker :buildx, :create, "--name", builder_name, "--use", "--driver=docker-container"
4
4
  end
5
5
 
6
6
  def remove
7
7
  docker :buildx, :rm, builder_name
8
8
  end
9
9
 
10
+ def push
11
+ docker :buildx, :build,
12
+ "--push",
13
+ *build_options,
14
+ build_context
15
+ end
16
+
17
+ def context_hosts
18
+ docker :buildx, :inspect, builder_name, "> /dev/null"
19
+ end
20
+
10
21
  private
11
- def build_and_push
12
- docker :buildx, :build,
13
- "--push",
14
- *build_options,
15
- build_context
22
+ def builder_name
23
+ "kamal-#{config.service}-native-cached"
16
24
  end
17
25
  end
@@ -17,6 +17,23 @@ class Kamal::Commands::Builder::Native::Remote < Kamal::Commands::Builder::Nativ
17
17
  docker(:buildx, :ls)
18
18
  end
19
19
 
20
+ def push
21
+ docker :buildx, :build,
22
+ "--push",
23
+ "--platform", platform,
24
+ "--builder", builder_name,
25
+ *build_options,
26
+ build_context
27
+ end
28
+
29
+ def context_hosts
30
+ context_host(builder_name_with_arch)
31
+ end
32
+
33
+ def config_context_hosts
34
+ [ remote_host ]
35
+ end
36
+
20
37
 
21
38
  private
22
39
  def builder_name
@@ -47,13 +64,4 @@ class Kamal::Commands::Builder::Native::Remote < Kamal::Commands::Builder::Nativ
47
64
  def remove_buildx
48
65
  docker :buildx, :rm, builder_name
49
66
  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
67
  end
@@ -11,11 +11,10 @@ class Kamal::Commands::Builder::Native < Kamal::Commands::Builder::Base
11
11
  # No-op on native
12
12
  end
13
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
14
+ def push
15
+ combine \
16
+ docker(:build, *build_options, build_context),
17
+ docker(:push, config.absolute_image),
18
+ docker(:push, config.latest_image)
19
+ end
21
20
  end
@@ -1,24 +1,32 @@
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, :validate_image, to: :target
4
+ delegate :create, :remove, :push, :clean, :pull, :info, :context_hosts, :config_context_hosts, :validate_image,
5
+ to: :target
6
+
7
+ include Clone
5
8
 
6
9
  def name
7
10
  target.class.to_s.remove("Kamal::Commands::Builder::").underscore.inquiry
8
11
  end
9
12
 
10
13
  def target
11
- case
12
- when !config.builder.multiarch? && !config.builder.cached?
13
- native
14
- when !config.builder.multiarch? && config.builder.cached?
15
- native_cached
16
- when config.builder.local? && config.builder.remote?
17
- multiarch_remote
18
- when config.builder.remote?
19
- native_remote
14
+ if config.builder.multiarch?
15
+ if config.builder.remote?
16
+ if config.builder.local?
17
+ multiarch_remote
18
+ else
19
+ native_remote
20
+ end
21
+ else
22
+ multiarch
23
+ end
20
24
  else
21
- multiarch
25
+ if config.builder.cached?
26
+ native_cached
27
+ else
28
+ native
29
+ end
22
30
  end
23
31
  end
24
32
 
@@ -3,21 +3,12 @@ class Kamal::Commands::Registry < Kamal::Commands::Base
3
3
 
4
4
  def login
5
5
  docker :login,
6
- registry["server"],
7
- "-u", sensitive(Kamal::Utils.escape_shell_value(lookup("username"))),
8
- "-p", sensitive(Kamal::Utils.escape_shell_value(lookup("password")))
6
+ registry.server,
7
+ "-u", sensitive(Kamal::Utils.escape_shell_value(registry.username)),
8
+ "-p", sensitive(Kamal::Utils.escape_shell_value(registry.password))
9
9
  end
10
10
 
11
11
  def logout
12
- docker :logout, registry["server"]
12
+ docker :logout, registry.server
13
13
  end
14
-
15
- private
16
- def lookup(key)
17
- if registry[key].is_a?(Array)
18
- ENV.fetch(registry[key].first).dup
19
- else
20
- registry[key]
21
- end
22
- end
23
14
  end