kamal 2.7.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/kamal/cli/accessory.rb +27 -7
- data/lib/kamal/cli/alias/command.rb +2 -2
- data/lib/kamal/cli/app/boot.rb +1 -1
- data/lib/kamal/cli/app.rb +74 -115
- data/lib/kamal/cli/base.rb +19 -6
- data/lib/kamal/cli/build/clone.rb +0 -2
- data/lib/kamal/cli/build/port_forwarding.rb +66 -0
- data/lib/kamal/cli/build.rb +70 -35
- data/lib/kamal/cli/healthcheck/poller.rb +1 -1
- data/lib/kamal/cli/main.rb +9 -3
- data/lib/kamal/cli/proxy.rb +42 -35
- data/lib/kamal/cli/registry.rb +37 -7
- data/lib/kamal/cli/secrets.rb +2 -1
- data/lib/kamal/cli/server.rb +12 -1
- data/lib/kamal/cli/templates/deploy.yml +4 -3
- data/lib/kamal/cli/templates/secrets +2 -1
- data/lib/kamal/commander.rb +21 -19
- data/lib/kamal/commands/accessory.rb +5 -0
- data/lib/kamal/commands/app/execution.rb +7 -1
- data/lib/kamal/commands/app.rb +1 -0
- data/lib/kamal/commands/base.rb +15 -2
- data/lib/kamal/commands/builder/base.rb +20 -1
- data/lib/kamal/commands/builder/hybrid.rb +3 -3
- data/lib/kamal/commands/builder/local.rb +8 -2
- data/lib/kamal/commands/builder/pack.rb +5 -5
- data/lib/kamal/commands/builder/remote.rb +15 -3
- data/lib/kamal/commands/builder.rb +8 -2
- data/lib/kamal/commands/docker.rb +17 -1
- data/lib/kamal/commands/proxy.rb +22 -3
- data/lib/kamal/commands/registry.rb +22 -0
- data/lib/kamal/configuration/accessory.rb +56 -25
- data/lib/kamal/configuration/boot.rb +4 -0
- data/lib/kamal/configuration/builder.rb +10 -3
- data/lib/kamal/configuration/docs/accessory.yml +37 -5
- data/lib/kamal/configuration/docs/alias.yml +3 -0
- data/lib/kamal/configuration/docs/boot.yml +12 -10
- data/lib/kamal/configuration/docs/configuration.yml +30 -1
- data/lib/kamal/configuration/docs/proxy.yml +48 -16
- data/lib/kamal/configuration/docs/registry.yml +12 -4
- data/lib/kamal/configuration/docs/ssh.yml +7 -4
- data/lib/kamal/configuration/docs/sshkit.yml +8 -0
- data/lib/kamal/configuration/env.rb +7 -3
- data/lib/kamal/configuration/proxy/boot.rb +4 -9
- data/lib/kamal/configuration/proxy/run.rb +143 -0
- data/lib/kamal/configuration/proxy.rb +7 -3
- data/lib/kamal/configuration/registry.rb +8 -0
- data/lib/kamal/configuration/role.rb +15 -3
- data/lib/kamal/configuration/ssh.rb +18 -3
- data/lib/kamal/configuration/sshkit.rb +4 -0
- data/lib/kamal/configuration/validator/proxy.rb +20 -0
- data/lib/kamal/configuration/validator/registry.rb +5 -3
- data/lib/kamal/configuration/validator.rb +52 -4
- data/lib/kamal/configuration/volume.rb +11 -4
- data/lib/kamal/configuration.rb +89 -5
- data/lib/kamal/secrets/adapters/one_password.rb +1 -1
- data/lib/kamal/secrets/adapters/passbolt.rb +1 -2
- data/lib/kamal/secrets/adapters/test.rb +3 -1
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +15 -1
- data/lib/kamal/secrets.rb +17 -6
- data/lib/kamal/sshkit_with_ext.rb +135 -10
- data/lib/kamal/utils.rb +3 -3
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +1 -0
- metadata +18 -2
|
@@ -68,6 +68,7 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
68
68
|
*network_args,
|
|
69
69
|
*env_args,
|
|
70
70
|
*volume_args,
|
|
71
|
+
*option_args,
|
|
71
72
|
image,
|
|
72
73
|
*command
|
|
73
74
|
end
|
|
@@ -90,6 +91,10 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
90
91
|
end
|
|
91
92
|
end
|
|
92
93
|
|
|
94
|
+
def pull_image
|
|
95
|
+
docker :image, :pull, image
|
|
96
|
+
end
|
|
97
|
+
|
|
93
98
|
def remove_service_directory
|
|
94
99
|
[ :rm, "-rf", service_name ]
|
|
95
100
|
end
|
|
@@ -12,6 +12,7 @@ module Kamal::Commands::App::Execution
|
|
|
12
12
|
(docker_interactive_args if interactive),
|
|
13
13
|
("--detach" if detach),
|
|
14
14
|
("--rm" unless detach),
|
|
15
|
+
"--name", container_name_for_exec,
|
|
15
16
|
"--network", "kamal",
|
|
16
17
|
*role&.env_args(host),
|
|
17
18
|
*argumentize("--env", env),
|
|
@@ -22,11 +23,16 @@ module Kamal::Commands::App::Execution
|
|
|
22
23
|
*command
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
def execute_in_existing_container_over_ssh(*command,
|
|
26
|
+
def execute_in_existing_container_over_ssh(*command, env:)
|
|
26
27
|
run_over_ssh execute_in_existing_container(*command, interactive: true, env: env), host: host
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def execute_in_new_container_over_ssh(*command, env:)
|
|
30
31
|
run_over_ssh execute_in_new_container(*command, interactive: true, env: env), host: host
|
|
31
32
|
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
def container_name_for_exec
|
|
36
|
+
[ role.container_prefix, "exec", config.version, SecureRandom.hex(3) ].compact.join("-")
|
|
37
|
+
end
|
|
32
38
|
end
|
data/lib/kamal/commands/app.rb
CHANGED
|
@@ -23,6 +23,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
|
23
23
|
"--env", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
|
24
24
|
"--env", "KAMAL_VERSION=\"#{config.version}\"",
|
|
25
25
|
"--env", "KAMAL_HOST=\"#{host}\"",
|
|
26
|
+
*([ "--env", "KAMAL_DESTINATION=\"#{config.destination}\"" ] if config.destination),
|
|
26
27
|
*role.env_args(host),
|
|
27
28
|
*role.logging_args,
|
|
28
29
|
*config.volume_args,
|
data/lib/kamal/commands/base.rb
CHANGED
|
@@ -11,11 +11,11 @@ module Kamal::Commands
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def run_over_ssh(*command, host:)
|
|
14
|
-
"ssh#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
|
|
14
|
+
"ssh#{ssh_config_args}#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def container_id_for(container_name:, only_running: false)
|
|
18
|
-
docker :container, :ls, *("--all" unless only_running), "--filter", "name=^#{container_name}$", "--quiet"
|
|
18
|
+
docker :container, :ls, *("--all" unless only_running), "--filter", "'name=^#{container_name}$'", "--quiet"
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def make_directory_for(remote_file)
|
|
@@ -100,6 +100,19 @@ module Kamal::Commands
|
|
|
100
100
|
Kamal::Tags.from_config(config, **details)
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
+
def ssh_config_args
|
|
104
|
+
case config.ssh.config
|
|
105
|
+
when Array
|
|
106
|
+
config.ssh.config.map { |file| " -F #{file}" }.join
|
|
107
|
+
when String
|
|
108
|
+
" -F #{config.ssh.config}"
|
|
109
|
+
when true
|
|
110
|
+
"" # Use default SSH config
|
|
111
|
+
when false
|
|
112
|
+
" -F /dev/null" # Ignore SSH config
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
103
116
|
def ssh_proxy_args
|
|
104
117
|
case config.ssh.proxy
|
|
105
118
|
when Net::SSH::Proxy::Jump
|
|
@@ -14,13 +14,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
|
14
14
|
docker :image, :rm, "--force", config.absolute_image
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def push(export_action = "registry", tag_as_dirty: false)
|
|
17
|
+
def push(export_action = "registry", tag_as_dirty: false, no_cache: false)
|
|
18
18
|
docker :buildx, :build,
|
|
19
19
|
"--output=type=#{export_action}",
|
|
20
20
|
*platform_options(arches),
|
|
21
21
|
*([ "--builder", builder_name ] unless docker_driver?),
|
|
22
22
|
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
|
23
23
|
*build_options,
|
|
24
|
+
*([ "--no-cache" ] if no_cache),
|
|
24
25
|
build_context,
|
|
25
26
|
"2>&1"
|
|
26
27
|
end
|
|
@@ -60,6 +61,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
|
60
61
|
docker(:info, "--format '{{index .RegistryConfig.Mirrors 0}}'")
|
|
61
62
|
end
|
|
62
63
|
|
|
64
|
+
def login_to_registry_locally?
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def push_env
|
|
69
|
+
{}
|
|
70
|
+
end
|
|
71
|
+
|
|
63
72
|
private
|
|
64
73
|
def build_tag_names(tag_as_dirty: false)
|
|
65
74
|
tag_names = [ config.absolute_image, config.latest_image ]
|
|
@@ -118,6 +127,16 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
|
118
127
|
config.builder
|
|
119
128
|
end
|
|
120
129
|
|
|
130
|
+
def registry_config
|
|
131
|
+
config.registry
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def driver_options
|
|
135
|
+
if registry_config.local?
|
|
136
|
+
[ "--driver-opt", "network=host" ]
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
121
140
|
def platform_options(arches)
|
|
122
141
|
argumentize "--platform", arches.map { |arch| "linux/#{arch}" }.join(",") if arches.any?
|
|
123
142
|
end
|
|
@@ -8,14 +8,14 @@ class Kamal::Commands::Builder::Hybrid < Kamal::Commands::Builder::Remote
|
|
|
8
8
|
|
|
9
9
|
private
|
|
10
10
|
def builder_name
|
|
11
|
-
"kamal-hybrid-#{driver}-#{
|
|
11
|
+
"kamal-hybrid-#{driver}-#{remote_builder_name_suffix}"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def create_local_buildx
|
|
15
|
-
docker :buildx, :create, *platform_options(local_arches), "--name", builder_name, "--driver=#{driver}"
|
|
15
|
+
docker :buildx, :create, *platform_options(local_arches), "--name", builder_name, "--driver=#{driver}", *driver_options
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def append_remote_buildx
|
|
19
|
-
docker :buildx, :create, *platform_options(remote_arches), "--append", "--name", builder_name, remote_context_name
|
|
19
|
+
docker :buildx, :create, *platform_options(remote_arches), "--append", "--name", builder_name, *driver_options, remote_context_name
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
|
|
2
2
|
def create
|
|
3
|
-
|
|
3
|
+
return if docker_driver?
|
|
4
|
+
|
|
5
|
+
docker :buildx, :create, "--name", builder_name, "--driver=#{driver}", *driver_options
|
|
4
6
|
end
|
|
5
7
|
|
|
6
8
|
def remove
|
|
@@ -9,6 +11,10 @@ class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
|
|
|
9
11
|
|
|
10
12
|
private
|
|
11
13
|
def builder_name
|
|
12
|
-
|
|
14
|
+
if registry_config.local?
|
|
15
|
+
"kamal-local-registry-#{driver}"
|
|
16
|
+
else
|
|
17
|
+
"kamal-local-#{driver}"
|
|
18
|
+
end
|
|
13
19
|
end
|
|
14
20
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class Kamal::Commands::Builder::Pack < Kamal::Commands::Builder::Base
|
|
2
|
-
def push(export_action = "registry")
|
|
2
|
+
def push(export_action = "registry", tag_as_dirty: false, no_cache: false)
|
|
3
3
|
combine \
|
|
4
|
-
build,
|
|
4
|
+
build(tag_as_dirty: tag_as_dirty, no_cache: no_cache),
|
|
5
5
|
export(export_action)
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -13,15 +13,15 @@ class Kamal::Commands::Builder::Pack < Kamal::Commands::Builder::Base
|
|
|
13
13
|
alias_method :inspect_builder, :info
|
|
14
14
|
|
|
15
15
|
private
|
|
16
|
-
def build
|
|
16
|
+
def build(tag_as_dirty: false, no_cache: false)
|
|
17
17
|
pack(:build,
|
|
18
18
|
config.repository,
|
|
19
19
|
"--platform", platform,
|
|
20
20
|
"--creation-time", "now",
|
|
21
21
|
"--builder", pack_builder,
|
|
22
22
|
buildpacks,
|
|
23
|
-
|
|
24
|
-
"-
|
|
23
|
+
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
|
24
|
+
*([ "--clear-cache" ] if no_cache),
|
|
25
25
|
"--env", "BP_IMAGE_LABELS=service=#{config.service}",
|
|
26
26
|
*argumentize("--env", args),
|
|
27
27
|
*argumentize("--env", secrets, sensitive: true),
|
|
@@ -19,20 +19,32 @@ class Kamal::Commands::Builder::Remote < Kamal::Commands::Builder::Base
|
|
|
19
19
|
|
|
20
20
|
def inspect_builder
|
|
21
21
|
combine \
|
|
22
|
-
combine
|
|
22
|
+
combine(inspect_buildx, inspect_remote_context),
|
|
23
23
|
[ "(echo no compatible builder && exit 1)" ],
|
|
24
24
|
by: "||"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
def login_to_registry_locally?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def push_env
|
|
32
|
+
{ "BUILDKIT_NO_CLIENT_TOKEN" => "1" }
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
private
|
|
28
36
|
def builder_name
|
|
29
|
-
"kamal-remote-#{
|
|
37
|
+
"kamal-remote-#{remote_builder_name_suffix}"
|
|
30
38
|
end
|
|
31
39
|
|
|
32
40
|
def remote_context_name
|
|
33
41
|
"#{builder_name}-context"
|
|
34
42
|
end
|
|
35
43
|
|
|
44
|
+
def remote_builder_name_suffix
|
|
45
|
+
"#{remote.gsub(/[^a-z0-9_-]/, "-")}#{registry_config.local? ? "-local-registry" : "" }"
|
|
46
|
+
end
|
|
47
|
+
|
|
36
48
|
def inspect_buildx
|
|
37
49
|
pipe \
|
|
38
50
|
docker(:buildx, :inspect, builder_name),
|
|
@@ -54,7 +66,7 @@ class Kamal::Commands::Builder::Remote < Kamal::Commands::Builder::Base
|
|
|
54
66
|
end
|
|
55
67
|
|
|
56
68
|
def create_buildx
|
|
57
|
-
docker :buildx, :create, "--name", builder_name, remote_context_name
|
|
69
|
+
docker :buildx, :create, "--name", builder_name, *driver_options, remote_context_name
|
|
58
70
|
end
|
|
59
71
|
|
|
60
72
|
def remove_buildx
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
require "active_support/core_ext/string/filters"
|
|
2
2
|
|
|
3
3
|
class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
4
|
-
delegate
|
|
5
|
-
|
|
4
|
+
delegate \
|
|
5
|
+
:create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder,
|
|
6
|
+
:validate_image, :first_mirror, :login_to_registry_locally?, :push_env,
|
|
7
|
+
to: :target
|
|
8
|
+
|
|
9
|
+
delegate \
|
|
10
|
+
:local?, :remote?, :pack?, :cloud?,
|
|
11
|
+
to: "config.builder"
|
|
6
12
|
|
|
7
13
|
include Clone
|
|
8
14
|
|
|
@@ -16,7 +16,23 @@ class Kamal::Commands::Docker < Kamal::Commands::Base
|
|
|
16
16
|
|
|
17
17
|
# Do we have superuser access to install Docker and start system services?
|
|
18
18
|
def superuser?
|
|
19
|
-
[ '[ "${EUID:-$(id -u)}" -eq 0 ] ||
|
|
19
|
+
[ '[ "${EUID:-$(id -u)}" -eq 0 ] || sudo -nl usermod >/dev/null' ]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def root?
|
|
23
|
+
[ '[ "${EUID:-$(id -u)}" -eq 0 ]' ]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def in_docker_group?
|
|
27
|
+
[ 'id -nG "${USER:-$(id -un)}" | grep -qw docker' ]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_to_docker_group
|
|
31
|
+
[ 'sudo -n usermod -aG docker "${USER:-$(id -un)}"' ]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def refresh_session
|
|
35
|
+
[ "kill -HUP $PPID" ]
|
|
20
36
|
end
|
|
21
37
|
|
|
22
38
|
def create_network
|
data/lib/kamal/commands/proxy.rb
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
class Kamal::Commands::Proxy < Kamal::Commands::Base
|
|
2
2
|
delegate :argumentize, :optionize, to: Kamal::Utils
|
|
3
|
+
attr_reader :proxy_run_config
|
|
4
|
+
|
|
5
|
+
def initialize(config, host:)
|
|
6
|
+
super(config)
|
|
7
|
+
@proxy_run_config = config.proxy_run(host)
|
|
8
|
+
end
|
|
3
9
|
|
|
4
10
|
def run
|
|
5
|
-
|
|
11
|
+
if proxy_run_config
|
|
12
|
+
docker \
|
|
13
|
+
:run,
|
|
14
|
+
"--name", container_name,
|
|
15
|
+
"--network", "kamal",
|
|
16
|
+
"--detach",
|
|
17
|
+
"--restart", "unless-stopped",
|
|
18
|
+
"--volume", "kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy",
|
|
19
|
+
*proxy_run_config.docker_options_args,
|
|
20
|
+
*proxy_run_config.image,
|
|
21
|
+
*proxy_run_config.run_command
|
|
22
|
+
else
|
|
23
|
+
pipe boot_config, xargs(docker_run)
|
|
24
|
+
end
|
|
6
25
|
end
|
|
7
26
|
|
|
8
27
|
def start
|
|
@@ -18,7 +37,7 @@ class Kamal::Commands::Proxy < Kamal::Commands::Base
|
|
|
18
37
|
end
|
|
19
38
|
|
|
20
39
|
def info
|
|
21
|
-
docker :ps, "--filter", "name=^#{container_name}$"
|
|
40
|
+
docker :ps, "--filter", "'name=^#{container_name}$'"
|
|
22
41
|
end
|
|
23
42
|
|
|
24
43
|
def version
|
|
@@ -82,7 +101,7 @@ class Kamal::Commands::Proxy < Kamal::Commands::Base
|
|
|
82
101
|
end
|
|
83
102
|
|
|
84
103
|
def read_image_version
|
|
85
|
-
read_file(config.proxy_boot.image_version_file, default: Kamal::Configuration::Proxy::
|
|
104
|
+
read_file(config.proxy_boot.image_version_file, default: Kamal::Configuration::Proxy::Run::MINIMUM_VERSION)
|
|
86
105
|
end
|
|
87
106
|
|
|
88
107
|
def read_run_command
|
|
@@ -2,6 +2,8 @@ class Kamal::Commands::Registry < Kamal::Commands::Base
|
|
|
2
2
|
def login(registry_config: nil)
|
|
3
3
|
registry_config ||= config.registry
|
|
4
4
|
|
|
5
|
+
return if registry_config.local?
|
|
6
|
+
|
|
5
7
|
docker :login,
|
|
6
8
|
registry_config.server,
|
|
7
9
|
"-u", sensitive(Kamal::Utils.escape_shell_value(registry_config.username)),
|
|
@@ -13,4 +15,24 @@ class Kamal::Commands::Registry < Kamal::Commands::Base
|
|
|
13
15
|
|
|
14
16
|
docker :logout, registry_config.server
|
|
15
17
|
end
|
|
18
|
+
|
|
19
|
+
def setup(registry_config: nil)
|
|
20
|
+
registry_config ||= config.registry
|
|
21
|
+
|
|
22
|
+
combine \
|
|
23
|
+
docker(:start, "kamal-docker-registry"),
|
|
24
|
+
docker(:run, "--detach", "-p", "127.0.0.1:#{registry_config.local_port}:5000", "--name", "kamal-docker-registry", "registry:3"),
|
|
25
|
+
by: "||"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def remove
|
|
29
|
+
combine \
|
|
30
|
+
docker(:stop, "kamal-docker-registry"),
|
|
31
|
+
docker(:rm, "kamal-docker-registry"),
|
|
32
|
+
by: "&&"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def local?
|
|
36
|
+
config.registry.local?
|
|
37
|
+
end
|
|
16
38
|
end
|
|
@@ -74,25 +74,31 @@ class Kamal::Configuration::Accessory
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def files
|
|
77
|
-
accessory_config["files"]&.to_h do |
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
accessory_config["files"]&.to_h do |config|
|
|
78
|
+
parse_path_config(config, default_mode: "755") do |local, remote|
|
|
79
|
+
{
|
|
80
|
+
key: expand_local_file(local),
|
|
81
|
+
host_path: expand_remote_file(remote),
|
|
82
|
+
container_path: remote
|
|
83
|
+
}
|
|
84
|
+
end
|
|
80
85
|
end || {}
|
|
81
86
|
end
|
|
82
87
|
|
|
83
88
|
def directories
|
|
84
|
-
accessory_config["directories"]&.to_h do |
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
accessory_config["directories"]&.to_h do |config|
|
|
90
|
+
parse_path_config(config, default_mode: nil) do |local, remote|
|
|
91
|
+
{
|
|
92
|
+
key: expand_host_path(local),
|
|
93
|
+
host_path: expand_host_path_for_volume(local),
|
|
94
|
+
container_path: remote
|
|
95
|
+
}
|
|
96
|
+
end
|
|
87
97
|
end || {}
|
|
88
98
|
end
|
|
89
99
|
|
|
90
|
-
def volumes
|
|
91
|
-
specific_volumes + remote_files_as_volumes + remote_directories_as_volumes
|
|
92
|
-
end
|
|
93
|
-
|
|
94
100
|
def volume_args
|
|
95
|
-
argumentize
|
|
101
|
+
argumentize("--volume", specific_volumes) + (path_volumes(files) + path_volumes(directories)).flat_map(&:docker_args)
|
|
96
102
|
end
|
|
97
103
|
|
|
98
104
|
def option_args
|
|
@@ -142,17 +148,17 @@ class Kamal::Configuration::Accessory
|
|
|
142
148
|
|
|
143
149
|
def expand_local_file(local_file)
|
|
144
150
|
if local_file.end_with?("erb")
|
|
145
|
-
|
|
151
|
+
with_env_loaded { read_dynamic_file(local_file) }
|
|
146
152
|
else
|
|
147
153
|
Pathname.new(File.expand_path(local_file)).to_s
|
|
148
154
|
end
|
|
149
155
|
end
|
|
150
156
|
|
|
151
|
-
def
|
|
152
|
-
env.
|
|
157
|
+
def with_env_loaded
|
|
158
|
+
env.to_h.each { |k, v| ENV[k] = v }
|
|
153
159
|
yield
|
|
154
160
|
ensure
|
|
155
|
-
env.
|
|
161
|
+
env.to_h.each { |k, v| ENV.delete(k) }
|
|
156
162
|
end
|
|
157
163
|
|
|
158
164
|
def read_dynamic_file(local_file)
|
|
@@ -167,24 +173,49 @@ class Kamal::Configuration::Accessory
|
|
|
167
173
|
accessory_config["volumes"] || []
|
|
168
174
|
end
|
|
169
175
|
|
|
170
|
-
def
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
176
|
+
def path_volumes(paths)
|
|
177
|
+
paths.map do |local, config|
|
|
178
|
+
Kamal::Configuration::Volume.new \
|
|
179
|
+
host_path: config[:host_path],
|
|
180
|
+
container_path: config[:container_path],
|
|
181
|
+
options: config[:options]
|
|
182
|
+
end
|
|
175
183
|
end
|
|
176
184
|
|
|
177
|
-
def
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
def parse_path_config(config, default_mode:)
|
|
186
|
+
if config.is_a?(Hash)
|
|
187
|
+
local, remote = config["local"], config["remote"]
|
|
188
|
+
expanded = yield(local, remote)
|
|
189
|
+
[
|
|
190
|
+
expanded[:key],
|
|
191
|
+
expanded.except(:key).merge(
|
|
192
|
+
options: config["options"],
|
|
193
|
+
mode: config["mode"] || default_mode,
|
|
194
|
+
owner: config["owner"]
|
|
195
|
+
)
|
|
196
|
+
]
|
|
197
|
+
else
|
|
198
|
+
local, remote, options = config.split(":", 3)
|
|
199
|
+
expanded = yield(local, remote)
|
|
200
|
+
[
|
|
201
|
+
expanded[:key],
|
|
202
|
+
expanded.except(:key).merge(
|
|
203
|
+
options: options,
|
|
204
|
+
mode: default_mode,
|
|
205
|
+
owner: nil
|
|
206
|
+
)
|
|
207
|
+
]
|
|
208
|
+
end
|
|
182
209
|
end
|
|
183
210
|
|
|
184
211
|
def expand_host_path(host_path)
|
|
185
212
|
absolute_path?(host_path) ? host_path : File.join(service_data_directory, host_path)
|
|
186
213
|
end
|
|
187
214
|
|
|
215
|
+
def expand_host_path_for_volume(host_path)
|
|
216
|
+
absolute_path?(host_path) ? host_path : File.join(service_name, host_path)
|
|
217
|
+
end
|
|
218
|
+
|
|
188
219
|
def absolute_path?(path)
|
|
189
220
|
Pathname.new(path).absolute?
|
|
190
221
|
end
|
|
@@ -177,8 +177,15 @@ class Kamal::Configuration::Builder
|
|
|
177
177
|
[ server, cache_image ].compact.join("/")
|
|
178
178
|
end
|
|
179
179
|
|
|
180
|
+
def cache_options
|
|
181
|
+
builder_config["cache"]&.fetch("options", nil)
|
|
182
|
+
end
|
|
183
|
+
|
|
180
184
|
def cache_from_config_for_gha
|
|
181
|
-
|
|
185
|
+
individual_options = cache_options&.split(",") || []
|
|
186
|
+
allowed_options = individual_options.select { |option| option =~ /^(url|url_v2|token|scope|timeout)=/ }
|
|
187
|
+
|
|
188
|
+
[ "type=gha", *allowed_options ].compact.join(",")
|
|
182
189
|
end
|
|
183
190
|
|
|
184
191
|
def cache_from_config_for_registry
|
|
@@ -186,11 +193,11 @@ class Kamal::Configuration::Builder
|
|
|
186
193
|
end
|
|
187
194
|
|
|
188
195
|
def cache_to_config_for_gha
|
|
189
|
-
[ "type=gha",
|
|
196
|
+
[ "type=gha", cache_options ].compact.join(",")
|
|
190
197
|
end
|
|
191
198
|
|
|
192
199
|
def cache_to_config_for_registry
|
|
193
|
-
[ "type=registry", "ref=#{cache_image_ref}",
|
|
200
|
+
[ "type=registry", "ref=#{cache_image_ref}", cache_options ].compact.join(",")
|
|
194
201
|
end
|
|
195
202
|
|
|
196
203
|
def repo_basename
|
|
@@ -90,22 +90,54 @@ accessories:
|
|
|
90
90
|
# Copying files
|
|
91
91
|
#
|
|
92
92
|
# You can specify files to mount into the container.
|
|
93
|
-
# The format is `local:remote`, where `local` is the path to the file on the local machine
|
|
94
|
-
# and `remote` is the path to the file in the container.
|
|
95
93
|
#
|
|
96
94
|
# They will be uploaded from the local repo to the host and then mounted.
|
|
97
|
-
#
|
|
98
95
|
# ERB files will be evaluated before being copied.
|
|
96
|
+
#
|
|
97
|
+
# You can use the string format: `local:remote` or `local:remote:options`
|
|
98
|
+
# where the options can be `ro` for read-only or `z`/`Z` for SELinux labels
|
|
99
99
|
files:
|
|
100
100
|
- config/my.cnf.erb:/etc/mysql/my.cnf
|
|
101
|
-
- config/myoptions.cnf:/etc/mysql/myoptions.cnf
|
|
101
|
+
- config/myoptions.cnf:/etc/mysql/myoptions.cnf:ro
|
|
102
|
+
- config/certs:/etc/mysql/certs:ro,Z
|
|
103
|
+
#
|
|
104
|
+
# Or you can use the hash format for custom mode and ownership.
|
|
105
|
+
#
|
|
106
|
+
# Note: Setting `owner` requires root access:
|
|
107
|
+
files:
|
|
108
|
+
- local: config/secret.key
|
|
109
|
+
remote: /etc/mysql/secret.key
|
|
110
|
+
mode: "0600"
|
|
111
|
+
owner: "mysql:mysql"
|
|
112
|
+
- local: config/ca-cert.pem
|
|
113
|
+
remote: /etc/mysql/certs/ca-cert.pem
|
|
114
|
+
mode: "0644"
|
|
115
|
+
owner: "1000:1000"
|
|
116
|
+
options: "Z"
|
|
102
117
|
|
|
103
118
|
# Directories
|
|
104
119
|
#
|
|
105
120
|
# You can specify directories to mount into the container. They will be created on the host
|
|
106
|
-
# before being mounted
|
|
121
|
+
# before being mounted.
|
|
122
|
+
#
|
|
123
|
+
# You can use the string format: `local:remote` or `local:remote:options`
|
|
124
|
+
# where the options can be `ro` for read-only or `z`/`Z` for SELinux labels
|
|
107
125
|
directories:
|
|
108
126
|
- mysql-logs:/var/log/mysql
|
|
127
|
+
- mysql-data:/var/lib/mysql:z
|
|
128
|
+
#
|
|
129
|
+
# Or you can use the hash format for custom mode and ownership.
|
|
130
|
+
#
|
|
131
|
+
# Note: Setting `owner` requires root access:
|
|
132
|
+
directories:
|
|
133
|
+
- local: mysql-data
|
|
134
|
+
remote: /var/lib/mysql
|
|
135
|
+
mode: "0750"
|
|
136
|
+
owner: "mysql:mysql"
|
|
137
|
+
- local: mysql-logs
|
|
138
|
+
remote: /var/log/mysql
|
|
139
|
+
mode: "0755"
|
|
140
|
+
options: "z"
|
|
109
141
|
|
|
110
142
|
# Volumes
|
|
111
143
|
#
|
|
@@ -4,16 +4,18 @@
|
|
|
4
4
|
#
|
|
5
5
|
# Kamal’s default is to boot new containers on all hosts in parallel. However, you can control this with the boot configuration.
|
|
6
6
|
|
|
7
|
-
# Fixed group sizes
|
|
8
|
-
#
|
|
9
|
-
# Here, we boot 2 hosts at a time with a 10-second gap between each group:
|
|
10
7
|
boot:
|
|
11
|
-
limit: 2
|
|
12
|
-
wait: 10
|
|
13
8
|
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# Here, we boot 25% of the hosts at a time with a 2-second gap between each group:
|
|
17
|
-
boot:
|
|
9
|
+
# The number or percentage of hosts to boot at a time.
|
|
10
|
+
# This can be an integer (e.g., 3) or a percentage string (e.g., 25%).
|
|
18
11
|
limit: 25%
|
|
19
|
-
|
|
12
|
+
|
|
13
|
+
# The number of seconds to wait between booting each group of hosts.
|
|
14
|
+
wait: 10
|
|
15
|
+
|
|
16
|
+
# Whether to boot roles in parallel on a host.
|
|
17
|
+
#
|
|
18
|
+
# If a host has multiple roles, control whether they are booted in parallel or sequentially on that host.
|
|
19
|
+
#
|
|
20
|
+
# Defaults to false.
|
|
21
|
+
parallel_roles: true
|