kamal 1.8.3 → 2.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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/kamal/cli/accessory.rb +92 -38
  4. data/lib/kamal/cli/alias/command.rb +10 -0
  5. data/lib/kamal/cli/app/{prepare_assets.rb → assets.rb} +1 -1
  6. data/lib/kamal/cli/app/boot.rb +23 -16
  7. data/lib/kamal/cli/app/error_pages.rb +33 -0
  8. data/lib/kamal/cli/app/ssl_certificates.rb +28 -0
  9. data/lib/kamal/cli/app.rb +132 -30
  10. data/lib/kamal/cli/base.rb +57 -53
  11. data/lib/kamal/cli/build.rb +81 -38
  12. data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
  13. data/lib/kamal/cli/healthcheck/poller.rb +18 -39
  14. data/lib/kamal/cli/lock.rb +2 -3
  15. data/lib/kamal/cli/main.rb +60 -59
  16. data/lib/kamal/cli/proxy.rb +290 -0
  17. data/lib/kamal/cli/prune.rb +0 -1
  18. data/lib/kamal/cli/registry.rb +2 -0
  19. data/lib/kamal/cli/secrets.rb +49 -0
  20. data/lib/kamal/cli/server.rb +6 -5
  21. data/lib/kamal/cli/templates/deploy.yml +53 -53
  22. data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +2 -12
  23. data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
  24. data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +1 -1
  25. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  26. data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
  27. data/lib/kamal/cli/templates/sample_hooks/pre-build.sample +1 -1
  28. data/lib/kamal/cli/templates/sample_hooks/pre-connect.sample +1 -1
  29. data/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample +19 -6
  30. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
  31. data/lib/kamal/cli/templates/secrets +17 -0
  32. data/lib/kamal/cli.rb +2 -0
  33. data/lib/kamal/commander/specifics.rb +19 -6
  34. data/lib/kamal/commander.rb +39 -32
  35. data/lib/kamal/commands/accessory/proxy.rb +16 -0
  36. data/lib/kamal/commands/accessory.rb +19 -19
  37. data/lib/kamal/commands/app/assets.rb +10 -10
  38. data/lib/kamal/commands/app/containers.rb +2 -2
  39. data/lib/kamal/commands/app/error_pages.rb +9 -0
  40. data/lib/kamal/commands/app/execution.rb +7 -4
  41. data/lib/kamal/commands/app/images.rb +1 -1
  42. data/lib/kamal/commands/app/logging.rb +16 -6
  43. data/lib/kamal/commands/app/proxy.rb +32 -0
  44. data/lib/kamal/commands/app.rb +25 -24
  45. data/lib/kamal/commands/auditor.rb +12 -3
  46. data/lib/kamal/commands/base.rb +54 -8
  47. data/lib/kamal/commands/builder/base.rb +46 -16
  48. data/lib/kamal/commands/builder/clone.rb +16 -14
  49. data/lib/kamal/commands/builder/cloud.rb +22 -0
  50. data/lib/kamal/commands/builder/hybrid.rb +21 -0
  51. data/lib/kamal/commands/builder/local.rb +14 -0
  52. data/lib/kamal/commands/builder/pack.rb +46 -0
  53. data/lib/kamal/commands/builder/remote.rb +63 -0
  54. data/lib/kamal/commands/builder.rb +21 -45
  55. data/lib/kamal/commands/docker.rb +4 -0
  56. data/lib/kamal/commands/hook.rb +8 -2
  57. data/lib/kamal/commands/lock.rb +2 -6
  58. data/lib/kamal/commands/proxy.rb +127 -0
  59. data/lib/kamal/commands/prune.rb +1 -9
  60. data/lib/kamal/commands/registry.rb +9 -7
  61. data/lib/kamal/commands/server.rb +11 -1
  62. data/lib/kamal/configuration/accessory.rb +89 -12
  63. data/lib/kamal/configuration/alias.rb +15 -0
  64. data/lib/kamal/configuration/builder.rb +73 -15
  65. data/lib/kamal/configuration/docs/accessory.yml +53 -15
  66. data/lib/kamal/configuration/docs/alias.yml +26 -0
  67. data/lib/kamal/configuration/docs/boot.yml +3 -3
  68. data/lib/kamal/configuration/docs/builder.yml +63 -38
  69. data/lib/kamal/configuration/docs/configuration.yml +62 -46
  70. data/lib/kamal/configuration/docs/env.yml +61 -17
  71. data/lib/kamal/configuration/docs/logging.yml +3 -3
  72. data/lib/kamal/configuration/docs/proxy.yml +168 -0
  73. data/lib/kamal/configuration/docs/registry.yml +20 -13
  74. data/lib/kamal/configuration/docs/role.yml +14 -13
  75. data/lib/kamal/configuration/docs/servers.yml +2 -2
  76. data/lib/kamal/configuration/docs/ssh.yml +23 -19
  77. data/lib/kamal/configuration/docs/sshkit.yml +4 -4
  78. data/lib/kamal/configuration/env/tag.rb +4 -3
  79. data/lib/kamal/configuration/env.rb +19 -17
  80. data/lib/kamal/configuration/proxy/boot.rb +129 -0
  81. data/lib/kamal/configuration/proxy.rb +124 -0
  82. data/lib/kamal/configuration/registry.rb +7 -6
  83. data/lib/kamal/configuration/role.rb +69 -98
  84. data/lib/kamal/configuration/servers.rb +8 -1
  85. data/lib/kamal/configuration/validator/accessory.rb +6 -2
  86. data/lib/kamal/configuration/validator/alias.rb +15 -0
  87. data/lib/kamal/configuration/validator/builder.rb +6 -0
  88. data/lib/kamal/configuration/validator/proxy.rb +25 -0
  89. data/lib/kamal/configuration/validator/role.rb +3 -1
  90. data/lib/kamal/configuration/validator/servers.rb +1 -1
  91. data/lib/kamal/configuration/validator.rb +62 -24
  92. data/lib/kamal/configuration.rb +96 -50
  93. data/lib/kamal/docker.rb +30 -0
  94. data/lib/kamal/env_file.rb +7 -1
  95. data/lib/kamal/git.rb +10 -0
  96. data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +51 -0
  97. data/lib/kamal/secrets/adapters/base.rb +33 -0
  98. data/lib/kamal/secrets/adapters/bitwarden.rb +81 -0
  99. data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +66 -0
  100. data/lib/kamal/secrets/adapters/doppler.rb +57 -0
  101. data/lib/kamal/secrets/adapters/enpass.rb +71 -0
  102. data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
  103. data/lib/kamal/secrets/adapters/last_pass.rb +40 -0
  104. data/lib/kamal/secrets/adapters/one_password.rb +104 -0
  105. data/lib/kamal/secrets/adapters/passbolt.rb +130 -0
  106. data/lib/kamal/secrets/adapters/test.rb +14 -0
  107. data/lib/kamal/secrets/adapters.rb +16 -0
  108. data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +33 -0
  109. data/lib/kamal/secrets.rb +42 -0
  110. data/lib/kamal/sshkit_with_ext.rb +1 -0
  111. data/lib/kamal/utils.rb +30 -0
  112. data/lib/kamal/version.rb +1 -1
  113. data/lib/kamal.rb +3 -1
  114. metadata +63 -36
  115. data/lib/kamal/cli/env.rb +0 -54
  116. data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
  117. data/lib/kamal/cli/templates/sample_hooks/pre-traefik-reboot.sample +0 -3
  118. data/lib/kamal/cli/templates/template.env +0 -2
  119. data/lib/kamal/cli/traefik.rb +0 -122
  120. data/lib/kamal/commands/app/cord.rb +0 -22
  121. data/lib/kamal/commands/builder/multiarch/remote.rb +0 -65
  122. data/lib/kamal/commands/builder/multiarch.rb +0 -41
  123. data/lib/kamal/commands/builder/native/cached.rb +0 -25
  124. data/lib/kamal/commands/builder/native/remote.rb +0 -67
  125. data/lib/kamal/commands/builder/native.rb +0 -20
  126. data/lib/kamal/commands/traefik.rb +0 -85
  127. data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
  128. data/lib/kamal/configuration/docs/traefik.yml +0 -62
  129. data/lib/kamal/configuration/healthcheck.rb +0 -63
  130. data/lib/kamal/configuration/traefik.rb +0 -60
@@ -11,14 +11,7 @@ module Kamal::Commands
11
11
  end
12
12
 
13
13
  def run_over_ssh(*command, host:)
14
- "ssh".tap do |cmd|
15
- if config.ssh.proxy && config.ssh.proxy.is_a?(Net::SSH::Proxy::Jump)
16
- cmd << " -J #{config.ssh.proxy.jump_proxies}"
17
- elsif config.ssh.proxy && config.ssh.proxy.is_a?(Net::SSH::Proxy::Command)
18
- cmd << " -o ProxyCommand='#{config.ssh.proxy.command_line_template}'"
19
- end
20
- cmd << " -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
21
- end
14
+ "ssh#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
22
15
  end
23
16
 
24
17
  def container_id_for(container_name:, only_running: false)
@@ -37,6 +30,16 @@ module Kamal::Commands
37
30
  [ :rm, "-r", path ]
38
31
  end
39
32
 
33
+ def remove_file(path)
34
+ [ :rm, path ]
35
+ end
36
+
37
+ def ensure_docker_installed
38
+ combine \
39
+ ensure_local_docker_installed,
40
+ ensure_local_buildx_installed
41
+ end
42
+
40
43
  private
41
44
  def combine(*commands, by: "&&")
42
45
  commands
@@ -65,6 +68,10 @@ module Kamal::Commands
65
68
  combine *commands, by: "||"
66
69
  end
67
70
 
71
+ def substitute(*commands)
72
+ "\$\(#{commands.join(" ")}\)"
73
+ end
74
+
68
75
  def xargs(command)
69
76
  [ :xargs, command ].flatten
70
77
  end
@@ -77,12 +84,51 @@ module Kamal::Commands
77
84
  args.compact.unshift :docker
78
85
  end
79
86
 
87
+ def pack(*args)
88
+ args.compact.unshift :pack
89
+ end
90
+
80
91
  def git(*args, path: nil)
81
92
  [ :git, *([ "-C", path ] if path), *args.compact ]
82
93
  end
83
94
 
95
+ def grep(*args)
96
+ args.compact.unshift :grep
97
+ end
98
+
84
99
  def tags(**details)
85
100
  Kamal::Tags.from_config(config, **details)
86
101
  end
102
+
103
+ def ssh_proxy_args
104
+ case config.ssh.proxy
105
+ when Net::SSH::Proxy::Jump
106
+ " -J #{config.ssh.proxy.jump_proxies}"
107
+ when Net::SSH::Proxy::Command
108
+ " -o ProxyCommand='#{config.ssh.proxy.command_line_template}'"
109
+ end
110
+ end
111
+
112
+ def ssh_keys_args
113
+ "#{ ssh_keys.join("") if ssh_keys}" + "#{" -o IdentitiesOnly=yes" if config.ssh&.keys_only}"
114
+ end
115
+
116
+ def ssh_keys
117
+ config.ssh.keys&.map do |key|
118
+ " -i #{key}"
119
+ end
120
+ end
121
+
122
+ def ensure_local_docker_installed
123
+ docker "--version"
124
+ end
125
+
126
+ def ensure_local_buildx_installed
127
+ docker :buildx, "version"
128
+ end
129
+
130
+ def docker_interactive_args
131
+ STDIN.isatty ? "-it" : "-i"
132
+ end
87
133
  end
88
134
  end
@@ -1,22 +1,46 @@
1
-
2
1
  class Kamal::Commands::Builder::Base < Kamal::Commands::Base
3
2
  class BuilderError < StandardError; end
4
3
 
5
4
  ENDPOINT_DOCKER_HOST_INSPECT = "'{{.Endpoints.docker.Host}}'"
6
5
 
7
6
  delegate :argumentize, to: Kamal::Utils
8
- delegate :args, :secrets, :dockerfile, :target, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, to: :builder_config
7
+ delegate \
8
+ :args, :secrets, :dockerfile, :target, :arches, :local_arches, :remote_arches, :remote,
9
+ :pack?, :pack_builder, :pack_buildpacks,
10
+ :cache_from, :cache_to, :ssh, :provenance, :sbom, :driver, :docker_driver?,
11
+ to: :builder_config
9
12
 
10
13
  def clean
11
14
  docker :image, :rm, "--force", config.absolute_image
12
15
  end
13
16
 
17
+ def push(export_action = "registry", tag_as_dirty: false)
18
+ docker :buildx, :build,
19
+ "--output=type=#{export_action}",
20
+ *platform_options(arches),
21
+ *([ "--builder", builder_name ] unless docker_driver?),
22
+ *build_tag_options(tag_as_dirty: tag_as_dirty),
23
+ *build_options,
24
+ build_context,
25
+ "2>&1"
26
+ end
27
+
14
28
  def pull
15
29
  docker :pull, config.absolute_image
16
30
  end
17
31
 
32
+ def info
33
+ combine \
34
+ docker(:context, :ls),
35
+ docker(:buildx, :ls)
36
+ end
37
+
38
+ def inspect_builder
39
+ docker :buildx, :inspect, builder_name unless docker_driver?
40
+ end
41
+
18
42
  def build_options
19
- [ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_target, *build_ssh ]
43
+ [ *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_target, *build_ssh, *builder_provenance, *builder_sbom ]
20
44
  end
21
45
 
22
46
  def build_context
@@ -32,21 +56,19 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
32
56
  )
33
57
  end
34
58
 
35
- def context_hosts
36
- :true
37
- end
38
-
39
- def config_context_hosts
40
- []
41
- end
42
-
43
59
  def first_mirror
44
60
  docker(:info, "--format '{{index .RegistryConfig.Mirrors 0}}'")
45
61
  end
46
62
 
47
63
  private
48
- def build_tags
49
- [ "-t", config.absolute_image, "-t", config.latest_image ]
64
+ def build_tag_names(tag_as_dirty: false)
65
+ tag_names = [ config.absolute_image, config.latest_image ]
66
+ tag_names.map! { |t| "#{t}-dirty" } if tag_as_dirty
67
+ tag_names
68
+ end
69
+
70
+ def build_tag_options(tag_as_dirty: false)
71
+ build_tag_names(tag_as_dirty: tag_as_dirty).flat_map { |name| [ "-t", name ] }
50
72
  end
51
73
 
52
74
  def build_cache
@@ -65,7 +87,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
65
87
  end
66
88
 
67
89
  def build_secrets
68
- argumentize "--secret", secrets.collect { |secret| [ "id", secret ] }
90
+ argumentize "--secret", secrets.keys.collect { |secret| [ "id", secret ] }
69
91
  end
70
92
 
71
93
  def build_dockerfile
@@ -84,11 +106,19 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
84
106
  argumentize "--ssh", ssh if ssh.present?
85
107
  end
86
108
 
109
+ def builder_provenance
110
+ argumentize "--provenance", provenance unless provenance.nil?
111
+ end
112
+
113
+ def builder_sbom
114
+ argumentize "--sbom", sbom unless sbom.nil?
115
+ end
116
+
87
117
  def builder_config
88
118
  config.builder
89
119
  end
90
120
 
91
- def context_host(builder_name)
92
- docker :context, :inspect, builder_name, "--format", ENDPOINT_DOCKER_HOST_INSPECT
121
+ def platform_options(arches)
122
+ argumentize "--platform", arches.map { |arch| "linux/#{arch}" }.join(",") if arches.any?
93
123
  end
94
124
  end
@@ -1,29 +1,31 @@
1
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
2
  def clone
9
- git :clone, Kamal::Git.root, "--recurse-submodules", path: clone_directory
3
+ git :clone, escaped_root, "--recurse-submodules", path: config.builder.clone_directory.shellescape
10
4
  end
11
5
 
12
6
  def clone_reset_steps
13
7
  [
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
- git(:submodule, :update, "--init", path: build_directory)
8
+ git(:remote, "set-url", :origin, escaped_root, path: escaped_build_directory),
9
+ git(:fetch, :origin, path: escaped_build_directory),
10
+ git(:reset, "--hard", Kamal::Git.revision, path: escaped_build_directory),
11
+ git(:clean, "-fdx", path: escaped_build_directory),
12
+ git(:submodule, :update, "--init", path: escaped_build_directory)
19
13
  ]
20
14
  end
21
15
 
22
16
  def clone_status
23
- git :status, "--porcelain", path: build_directory
17
+ git :status, "--porcelain", path: escaped_build_directory
24
18
  end
25
19
 
26
20
  def clone_revision
27
- git :"rev-parse", :HEAD, path: build_directory
21
+ git :"rev-parse", :HEAD, path: escaped_build_directory
22
+ end
23
+
24
+ def escaped_root
25
+ Kamal::Git.root.shellescape
26
+ end
27
+
28
+ def escaped_build_directory
29
+ config.builder.build_directory.shellescape
28
30
  end
29
31
  end
@@ -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
@@ -0,0 +1,21 @@
1
+ class Kamal::Commands::Builder::Hybrid < Kamal::Commands::Builder::Remote
2
+ def create
3
+ combine \
4
+ create_local_buildx,
5
+ create_remote_context,
6
+ append_remote_buildx
7
+ end
8
+
9
+ private
10
+ def builder_name
11
+ "kamal-hybrid-#{driver}-#{remote.gsub(/[^a-z0-9_-]/, "-")}"
12
+ end
13
+
14
+ def create_local_buildx
15
+ docker :buildx, :create, *platform_options(local_arches), "--name", builder_name, "--driver=#{driver}"
16
+ end
17
+
18
+ def append_remote_buildx
19
+ docker :buildx, :create, *platform_options(remote_arches), "--append", "--name", builder_name, remote_context_name
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
2
+ def create
3
+ docker :buildx, :create, "--name", builder_name, "--driver=#{driver}" unless docker_driver?
4
+ end
5
+
6
+ def remove
7
+ docker :buildx, :rm, builder_name unless docker_driver?
8
+ end
9
+
10
+ private
11
+ def builder_name
12
+ "kamal-local-#{driver}"
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ class Kamal::Commands::Builder::Pack < Kamal::Commands::Builder::Base
2
+ def push(export_action = "registry")
3
+ combine \
4
+ build,
5
+ export(export_action)
6
+ end
7
+
8
+ def remove;end
9
+
10
+ def info
11
+ pack :builder, :inspect, pack_builder
12
+ end
13
+ alias_method :inspect_builder, :info
14
+
15
+ private
16
+ def build
17
+ pack(:build,
18
+ config.repository,
19
+ "--platform", platform,
20
+ "--creation-time", "now",
21
+ "--builder", pack_builder,
22
+ buildpacks,
23
+ "-t", config.absolute_image,
24
+ "-t", config.latest_image,
25
+ "--env", "BP_IMAGE_LABELS=service=#{config.service}",
26
+ *argumentize("--env", args),
27
+ *argumentize("--env", secrets, sensitive: true),
28
+ "--path", build_context)
29
+ end
30
+
31
+ def export(export_action)
32
+ return unless export_action == "registry"
33
+
34
+ combine \
35
+ docker(:push, config.absolute_image),
36
+ docker(:push, config.latest_image)
37
+ end
38
+
39
+ def platform
40
+ "linux/#{local_arches.first}"
41
+ end
42
+
43
+ def buildpacks
44
+ (pack_buildpacks << "paketo-buildpacks/image-labels").map { |buildpack| [ "--buildpack", buildpack ] }
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ class Kamal::Commands::Builder::Remote < Kamal::Commands::Builder::Base
2
+ def create
3
+ chain \
4
+ create_remote_context,
5
+ create_buildx
6
+ end
7
+
8
+ def remove
9
+ chain \
10
+ remove_remote_context,
11
+ remove_buildx
12
+ end
13
+
14
+ def info
15
+ chain \
16
+ docker(:context, :ls),
17
+ docker(:buildx, :ls)
18
+ end
19
+
20
+ def inspect_builder
21
+ combine \
22
+ combine inspect_buildx, inspect_remote_context,
23
+ [ "(echo no compatible builder && exit 1)" ],
24
+ by: "||"
25
+ end
26
+
27
+ private
28
+ def builder_name
29
+ "kamal-remote-#{remote.gsub(/[^a-z0-9_-]/, "-")}"
30
+ end
31
+
32
+ def remote_context_name
33
+ "#{builder_name}-context"
34
+ end
35
+
36
+ def inspect_buildx
37
+ pipe \
38
+ docker(:buildx, :inspect, builder_name),
39
+ grep("-q", "Endpoint:.*#{remote_context_name}")
40
+ end
41
+
42
+ def inspect_remote_context
43
+ pipe \
44
+ docker(:context, :inspect, remote_context_name, "--format", ENDPOINT_DOCKER_HOST_INSPECT),
45
+ grep("-xq", remote)
46
+ end
47
+
48
+ def create_remote_context
49
+ docker :context, :create, remote_context_name, "--description", "'#{builder_name} host'", "--docker", "'host=#{remote}'"
50
+ end
51
+
52
+ def remove_remote_context
53
+ docker :context, :rm, remote_context_name
54
+ end
55
+
56
+ def create_buildx
57
+ docker :buildx, :create, "--name", builder_name, remote_context_name
58
+ end
59
+
60
+ def remove_buildx
61
+ docker :buildx, :rm, builder_name
62
+ end
63
+ 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, :context_hosts, :config_context_hosts, :validate_image,
5
- :first_mirror, to: :target
4
+ delegate :create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder, :validate_image, :first_mirror, to: :target
5
+ delegate :local?, :remote?, :pack?, :cloud?, to: "config.builder"
6
6
 
7
7
  include Clone
8
8
 
@@ -11,62 +11,38 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
11
11
  end
12
12
 
13
13
  def target
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
14
+ if remote?
15
+ if local?
16
+ hybrid
21
17
  else
22
- multiarch
18
+ remote
23
19
  end
20
+ elsif pack?
21
+ pack
22
+ elsif cloud?
23
+ cloud
24
24
  else
25
- if config.builder.cached?
26
- native_cached
27
- else
28
- native
29
- end
25
+ local
30
26
  end
31
27
  end
32
28
 
33
- def native
34
- @native ||= Kamal::Commands::Builder::Native.new(config)
29
+ def remote
30
+ @remote ||= Kamal::Commands::Builder::Remote.new(config)
35
31
  end
36
32
 
37
- def native_cached
38
- @native ||= Kamal::Commands::Builder::Native::Cached.new(config)
33
+ def local
34
+ @local ||= Kamal::Commands::Builder::Local.new(config)
39
35
  end
40
36
 
41
- def native_remote
42
- @native ||= Kamal::Commands::Builder::Native::Remote.new(config)
37
+ def hybrid
38
+ @hybrid ||= Kamal::Commands::Builder::Hybrid.new(config)
43
39
  end
44
40
 
45
- def multiarch
46
- @multiarch ||= Kamal::Commands::Builder::Multiarch.new(config)
41
+ def pack
42
+ @pack ||= Kamal::Commands::Builder::Pack.new(config)
47
43
  end
48
44
 
49
- def multiarch_remote
50
- @multiarch_remote ||= Kamal::Commands::Builder::Multiarch::Remote.new(config)
45
+ def cloud
46
+ @cloud ||= Kamal::Commands::Builder::Cloud.new(config)
51
47
  end
52
-
53
-
54
- def ensure_local_dependencies_installed
55
- if name.native?
56
- ensure_local_docker_installed
57
- else
58
- combine \
59
- ensure_local_docker_installed,
60
- ensure_local_buildx_installed
61
- end
62
- end
63
-
64
- private
65
- def ensure_local_docker_installed
66
- docker "--version"
67
- end
68
-
69
- def ensure_local_buildx_installed
70
- docker :buildx, "version"
71
- end
72
48
  end
@@ -19,6 +19,10 @@ class Kamal::Commands::Docker < Kamal::Commands::Base
19
19
  [ '[ "${EUID:-$(id -u)}" -eq 0 ] || command -v sudo >/dev/null || command -v su >/dev/null' ]
20
20
  end
21
21
 
22
+ def create_network
23
+ docker :network, :create, :kamal
24
+ end
25
+
22
26
  private
23
27
  def get_docker
24
28
  shell \
@@ -1,6 +1,12 @@
1
1
  class Kamal::Commands::Hook < Kamal::Commands::Base
2
- def run(hook, **details)
3
- [ hook_file(hook), env: tags(**details).env ]
2
+ def run(hook)
3
+ [ hook_file(hook) ]
4
+ end
5
+
6
+ def env(secrets: false, **details)
7
+ tags(**details).env.tap do |env|
8
+ env.merge!(config.secrets.to_h) if secrets
9
+ end
4
10
  end
5
11
 
6
12
  def hook_exists?(hook)
@@ -44,14 +44,10 @@ class Kamal::Commands::Lock < Kamal::Commands::Base
44
44
  "/dev/null"
45
45
  end
46
46
 
47
- def locks_dir
48
- File.join(config.run_directory, "locks")
49
- end
50
-
51
47
  def lock_dir
52
- dir_name = [ config.service, config.destination ].compact.join("-")
48
+ dir_name = [ "lock", config.service, config.destination ].compact.join("-")
53
49
 
54
- File.join(locks_dir, dir_name)
50
+ File.join(config.run_directory, dir_name)
55
51
  end
56
52
 
57
53
  def lock_details_file
@@ -0,0 +1,127 @@
1
+ class Kamal::Commands::Proxy < Kamal::Commands::Base
2
+ delegate :argumentize, :optionize, to: Kamal::Utils
3
+
4
+ def run
5
+ pipe boot_config, xargs(docker_run)
6
+ end
7
+
8
+ def start
9
+ docker :container, :start, container_name
10
+ end
11
+
12
+ def stop(name: container_name)
13
+ docker :container, :stop, name
14
+ end
15
+
16
+ def start_or_run
17
+ combine start, run, by: "||"
18
+ end
19
+
20
+ def info
21
+ docker :ps, "--filter", "name=^#{container_name}$"
22
+ end
23
+
24
+ def version
25
+ pipe \
26
+ docker(:inspect, container_name, "--format '{{.Config.Image}}'"),
27
+ [ :awk, "-F:", "'{print \$NF}'" ]
28
+ end
29
+
30
+ def logs(timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
31
+ pipe \
32
+ docker(:logs, container_name, ("--since #{since}" if since), ("--tail #{lines}" if lines), ("--timestamps" if timestamps), "2>&1"),
33
+ ("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
34
+ end
35
+
36
+ def follow_logs(host:, timestamps: true, grep: nil, grep_options: nil)
37
+ run_over_ssh pipe(
38
+ docker(:logs, container_name, ("--timestamps" if timestamps), "--tail", "10", "--follow", "2>&1"),
39
+ (%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
40
+ ).join(" "), host: host
41
+ end
42
+
43
+ def remove_container
44
+ docker :container, :prune, "--force", "--filter", "label=org.opencontainers.image.title=kamal-proxy"
45
+ end
46
+
47
+ def remove_image
48
+ docker :image, :prune, "--all", "--force", "--filter", "label=org.opencontainers.image.title=kamal-proxy"
49
+ end
50
+
51
+ def cleanup_traefik
52
+ chain \
53
+ docker(:container, :stop, "traefik"),
54
+ combine(
55
+ docker(:container, :prune, "--force", "--filter", "label=org.opencontainers.image.title=Traefik"),
56
+ docker(:image, :prune, "--all", "--force", "--filter", "label=org.opencontainers.image.title=Traefik")
57
+ )
58
+ end
59
+
60
+ def ensure_proxy_directory
61
+ make_directory config.proxy_boot.host_directory
62
+ end
63
+
64
+ def remove_proxy_directory
65
+ remove_directory config.proxy_boot.host_directory
66
+ end
67
+
68
+ def ensure_apps_config_directory
69
+ make_directory config.proxy_boot.apps_directory
70
+ end
71
+
72
+ def boot_config
73
+ [ :echo, "#{substitute(read_boot_options)} #{substitute(read_image)}:#{substitute(read_image_version)} #{substitute(read_run_command)}" ]
74
+ end
75
+
76
+ def read_boot_options
77
+ read_file(config.proxy_boot.options_file, default: config.proxy_boot.default_boot_options.join(" "))
78
+ end
79
+
80
+ def read_image
81
+ read_file(config.proxy_boot.image_file, default: config.proxy_boot.image_default)
82
+ end
83
+
84
+ def read_image_version
85
+ read_file(config.proxy_boot.image_version_file, default: Kamal::Configuration::Proxy::Boot::MINIMUM_VERSION)
86
+ end
87
+
88
+ def read_run_command
89
+ read_file(config.proxy_boot.run_command_file)
90
+ end
91
+
92
+ def reset_boot_options
93
+ remove_file config.proxy_boot.options_file
94
+ end
95
+
96
+ def reset_image
97
+ remove_file config.proxy_boot.image_file
98
+ end
99
+
100
+ def reset_image_version
101
+ remove_file config.proxy_boot.image_version_file
102
+ end
103
+
104
+ def reset_run_command
105
+ remove_file config.proxy_boot.run_command_file
106
+ end
107
+
108
+ private
109
+ def container_name
110
+ config.proxy_boot.container_name
111
+ end
112
+
113
+ def read_file(file, default: nil)
114
+ combine [ :cat, file, "2>", "/dev/null" ], [ :echo, "\"#{default}\"" ], by: "||"
115
+ end
116
+
117
+ def docker_run
118
+ docker \
119
+ :run,
120
+ "--name", container_name,
121
+ "--network", "kamal",
122
+ "--detach",
123
+ "--restart", "unless-stopped",
124
+ "--volume", "kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy",
125
+ *config.proxy_boot.apps_volume.docker_args
126
+ end
127
+ end