kamal 1.4.0 → 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 +3 -2
- 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 +20 -61
- data/lib/kamal/cli/base.rb +21 -7
- data/lib/kamal/cli/env.rb +3 -3
- data/lib/kamal/cli/main.rb +1 -1
- data/lib/kamal/cli/templates/deploy.yml +1 -1
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +0 -0
- data/lib/kamal/cli/traefik.rb +15 -12
- 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 +4 -4
- data/lib/kamal/commands/app/cord.rb +2 -2
- data/lib/kamal/commands/app/execution.rb +8 -6
- data/lib/kamal/commands/app/images.rb +1 -1
- data/lib/kamal/commands/app.rb +29 -8
- data/lib/kamal/commands/auditor.rb +1 -1
- data/lib/kamal/commands/base.rb +5 -1
- data/lib/kamal/commands/builder/base.rb +14 -4
- data/lib/kamal/commands/builder/multiarch.rb +9 -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/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 +2 -2
- data/lib/kamal/commands/server.rb +1 -1
- data/lib/kamal/commands/traefik.rb +8 -14
- data/lib/kamal/configuration/accessory.rb +9 -19
- data/lib/kamal/configuration/boot.rb +1 -1
- data/lib/kamal/configuration/builder.rb +7 -3
- data/lib/kamal/configuration/env.rb +40 -0
- data/lib/kamal/configuration/role.rb +12 -42
- data/lib/kamal/configuration.rb +20 -8
- data/lib/kamal/env_file.rb +12 -15
- data/lib/kamal/utils.rb +7 -3
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +1 -1
- metadata +6 -2
data/lib/kamal/commands/app.rb
CHANGED
@@ -15,7 +15,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
15
15
|
"--detach",
|
16
16
|
"--restart unless-stopped",
|
17
17
|
"--name", container_name,
|
18
|
-
*(["--hostname", hostname] if hostname),
|
18
|
+
*([ "--hostname", hostname ] if hostname),
|
19
19
|
"-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
20
20
|
"-e", "KAMAL_VERSION=\"#{config.version}\"",
|
21
21
|
*role.env_args,
|
@@ -49,7 +49,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
49
49
|
|
50
50
|
|
51
51
|
def current_running_container_id
|
52
|
-
|
52
|
+
current_running_container(format: "--quiet")
|
53
53
|
end
|
54
54
|
|
55
55
|
def container_id_for_version(version, only_running: false)
|
@@ -57,22 +57,24 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def current_running_version
|
60
|
-
|
60
|
+
pipe \
|
61
|
+
current_running_container(format: "--format '{{.Names}}'"),
|
62
|
+
extract_version_from_name
|
61
63
|
end
|
62
64
|
|
63
65
|
def list_versions(*docker_args, statuses: nil)
|
64
66
|
pipe \
|
65
67
|
docker(:ps, *filter_args(statuses: statuses), *docker_args, "--format", '"{{.Names}}"'),
|
66
|
-
|
68
|
+
extract_version_from_name
|
67
69
|
end
|
68
70
|
|
69
71
|
|
70
72
|
def make_env_directory
|
71
|
-
make_directory role.
|
73
|
+
make_directory role.env.secrets_directory
|
72
74
|
end
|
73
75
|
|
74
76
|
def remove_env_file
|
75
|
-
[ :rm, "-f", role.
|
77
|
+
[ :rm, "-f", role.env.secrets_file ]
|
76
78
|
end
|
77
79
|
|
78
80
|
|
@@ -81,12 +83,31 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
81
83
|
[ role.container_prefix, version || config.version ].compact.join("-")
|
82
84
|
end
|
83
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)
|
102
|
+
end
|
103
|
+
|
84
104
|
def filter_args(statuses: nil)
|
85
105
|
argumentize "--filter", filters(statuses: statuses)
|
86
106
|
end
|
87
107
|
|
88
|
-
def
|
89
|
-
|
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)
|
90
111
|
end
|
91
112
|
|
92
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
@@ -71,13 +71,17 @@ module Kamal::Commands
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def shell(command)
|
74
|
-
[ :sh, "-c", "'#{command.flatten.join(" ").gsub("'", "'
|
74
|
+
[ :sh, "-c", "'#{command.flatten.join(" ").gsub("'", "'\\\\''")}'" ]
|
75
75
|
end
|
76
76
|
|
77
77
|
def docker(*args)
|
78
78
|
args.compact.unshift :docker
|
79
79
|
end
|
80
80
|
|
81
|
+
def git(*args)
|
82
|
+
args.compact.unshift :git
|
83
|
+
end
|
84
|
+
|
81
85
|
def tags(**details)
|
82
86
|
Kamal::Tags.from_config(config, **details)
|
83
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, :ssh, 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,6 +13,16 @@ 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
27
|
[ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_ssh ]
|
18
28
|
end
|
@@ -25,7 +35,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
25
35
|
pipe \
|
26
36
|
docker(:inspect, "-f", "'{{ .Config.Labels.service }}'", config.absolute_image),
|
27
37
|
any(
|
28
|
-
[:grep, "-x", config.service],
|
38
|
+
[ :grep, "-x", config.service ],
|
29
39
|
"(echo \"Image #{config.absolute_image} is missing the 'service' label\" && exit 1)"
|
30
40
|
)
|
31
41
|
end
|
@@ -38,8 +48,8 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
38
48
|
|
39
49
|
def build_cache
|
40
50
|
if cache_to && cache_from
|
41
|
-
["--cache-to", cache_to,
|
42
|
-
"--cache-from", cache_from]
|
51
|
+
[ "--cache-to", cache_to,
|
52
|
+
"--cache-from", cache_from ]
|
43
53
|
end
|
44
54
|
end
|
45
55
|
|
@@ -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", platform_names,
|
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),
|
@@ -34,4 +25,13 @@ class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base
|
|
34
25
|
"linux/amd64,linux/arm64"
|
35
26
|
end
|
36
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
|
37
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
|
data/lib/kamal/commands/hook.rb
CHANGED
data/lib/kamal/commands/lock.rb
CHANGED
@@ -5,14 +5,14 @@ require "base64"
|
|
5
5
|
class Kamal::Commands::Lock < Kamal::Commands::Base
|
6
6
|
def acquire(message, version)
|
7
7
|
combine \
|
8
|
-
[:mkdir, lock_dir],
|
8
|
+
[ :mkdir, lock_dir ],
|
9
9
|
write_lock_details(message, version)
|
10
10
|
end
|
11
11
|
|
12
12
|
def release
|
13
13
|
combine \
|
14
|
-
[:rm, lock_details_file],
|
15
|
-
[:rm, "-r", lock_dir]
|
14
|
+
[ :rm, lock_details_file ],
|
15
|
+
[ :rm, "-r", lock_dir ]
|
16
16
|
end
|
17
17
|
|
18
18
|
def status
|
@@ -21,31 +21,41 @@ class Kamal::Commands::Lock < Kamal::Commands::Base
|
|
21
21
|
read_lock_details
|
22
22
|
end
|
23
23
|
|
24
|
+
def ensure_locks_directory
|
25
|
+
[ :mkdir, "-p", locks_dir ]
|
26
|
+
end
|
27
|
+
|
24
28
|
private
|
25
29
|
def write_lock_details(message, version)
|
26
30
|
write \
|
27
|
-
[:echo, "\"#{Base64.encode64(lock_details(message, version))}\""],
|
31
|
+
[ :echo, "\"#{Base64.encode64(lock_details(message, version))}\"" ],
|
28
32
|
lock_details_file
|
29
33
|
end
|
30
34
|
|
31
35
|
def read_lock_details
|
32
36
|
pipe \
|
33
|
-
[:cat, lock_details_file],
|
34
|
-
[:base64, "-d"]
|
37
|
+
[ :cat, lock_details_file ],
|
38
|
+
[ :base64, "-d" ]
|
35
39
|
end
|
36
40
|
|
37
41
|
def stat_lock_dir
|
38
42
|
write \
|
39
|
-
[:stat, lock_dir],
|
43
|
+
[ :stat, lock_dir ],
|
40
44
|
"/dev/null"
|
41
45
|
end
|
42
46
|
|
47
|
+
def locks_dir
|
48
|
+
File.join(config.run_directory, "locks")
|
49
|
+
end
|
50
|
+
|
43
51
|
def lock_dir
|
44
|
-
|
52
|
+
dir_name = [ config.service, config.destination ].compact.join("-")
|
53
|
+
|
54
|
+
File.join(locks_dir, dir_name)
|
45
55
|
end
|
46
56
|
|
47
57
|
def lock_details_file
|
48
|
-
|
58
|
+
File.join(lock_dir, "details")
|
49
59
|
end
|
50
60
|
|
51
61
|
def lock_details(message, version)
|
data/lib/kamal/commands/prune.rb
CHANGED
@@ -26,7 +26,7 @@ class Kamal::Commands::Prune < Kamal::Commands::Base
|
|
26
26
|
|
27
27
|
private
|
28
28
|
def stopped_containers_filters
|
29
|
-
[ "created", "exited", "dead" ].flat_map { |status| ["--filter", "status=#{status}"] }
|
29
|
+
[ "created", "exited", "dead" ].flat_map { |status| [ "--filter", "status=#{status}" ] }
|
30
30
|
end
|
31
31
|
|
32
32
|
def active_image_list
|
@@ -43,4 +43,4 @@ class Kamal::Commands::Prune < Kamal::Commands::Base
|
|
43
43
|
def healthcheck_service_filter
|
44
44
|
[ "--filter", "label=service=#{config.healthcheck_service}" ]
|
45
45
|
end
|
46
|
-
|
46
|
+
end
|
@@ -4,7 +4,7 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
|
4
4
|
DEFAULT_IMAGE = "traefik:v2.10"
|
5
5
|
CONTAINER_PORT = 80
|
6
6
|
DEFAULT_ARGS = {
|
7
|
-
|
7
|
+
"log.level" => "DEBUG"
|
8
8
|
}
|
9
9
|
DEFAULT_LABELS = {
|
10
10
|
# These ensure we serve a 502 rather than a 404 if no containers are available
|
@@ -71,20 +71,18 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
|
71
71
|
"#{host_port}:#{CONTAINER_PORT}"
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
75
|
-
Kamal::
|
76
|
-
|
77
|
-
|
78
|
-
def host_env_file_path
|
79
|
-
File.join host_env_directory, "traefik.env"
|
74
|
+
def env
|
75
|
+
Kamal::Configuration::Env.from_config \
|
76
|
+
config: config.traefik.fetch("env", {}),
|
77
|
+
secrets_file: File.join(config.host_env_directory, "traefik", "traefik.env")
|
80
78
|
end
|
81
79
|
|
82
80
|
def make_env_directory
|
83
|
-
make_directory(
|
81
|
+
make_directory(env.secrets_directory)
|
84
82
|
end
|
85
83
|
|
86
84
|
def remove_env_file
|
87
|
-
[:rm, "-f",
|
85
|
+
[ :rm, "-f", env.secrets_file ]
|
88
86
|
end
|
89
87
|
|
90
88
|
private
|
@@ -97,11 +95,7 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
|
97
95
|
end
|
98
96
|
|
99
97
|
def env_args
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
def host_env_directory
|
104
|
-
File.join config.host_env_directory, "traefik"
|
98
|
+
env.args
|
105
99
|
end
|
106
100
|
|
107
101
|
def labels
|
@@ -16,7 +16,7 @@ class Kamal::Configuration::Accessory
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def hosts
|
19
|
-
if (specifics.keys & ["host", "hosts", "roles"]).size != 1
|
19
|
+
if (specifics.keys & [ "host", "hosts", "roles" ]).size != 1
|
20
20
|
raise ArgumentError, "Specify one of `host`, `hosts` or `roles` for accessory `#{name}`"
|
21
21
|
end
|
22
22
|
|
@@ -42,23 +42,13 @@ class Kamal::Configuration::Accessory
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def env
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def env_file
|
49
|
-
Kamal::EnvFile.new(env)
|
50
|
-
end
|
51
|
-
|
52
|
-
def host_env_directory
|
53
|
-
File.join config.host_env_directory, "accessories"
|
54
|
-
end
|
55
|
-
|
56
|
-
def host_env_file_path
|
57
|
-
File.join host_env_directory, "#{service_name}.env"
|
45
|
+
Kamal::Configuration::Env.from_config \
|
46
|
+
config: specifics.fetch("env", {}),
|
47
|
+
secrets_file: File.join(config.host_env_directory, "accessories", "#{service_name}.env")
|
58
48
|
end
|
59
49
|
|
60
50
|
def env_args
|
61
|
-
|
51
|
+
env.args
|
62
52
|
end
|
63
53
|
|
64
54
|
def files
|
@@ -111,10 +101,10 @@ class Kamal::Configuration::Accessory
|
|
111
101
|
end
|
112
102
|
|
113
103
|
def with_clear_env_loaded
|
114
|
-
|
104
|
+
env.clear.each { |k, v| ENV[k] = v }
|
115
105
|
yield
|
116
106
|
ensure
|
117
|
-
|
107
|
+
env.clear.each { |k, v| ENV.delete(k) }
|
118
108
|
end
|
119
109
|
|
120
110
|
def read_dynamic_file(local_file)
|
@@ -144,7 +134,7 @@ class Kamal::Configuration::Accessory
|
|
144
134
|
end
|
145
135
|
|
146
136
|
def expand_host_path(host_path)
|
147
|
-
absolute_path?(host_path) ? host_path :
|
137
|
+
absolute_path?(host_path) ? host_path : File.join(service_data_directory, host_path)
|
148
138
|
end
|
149
139
|
|
150
140
|
def absolute_path?(path)
|
@@ -159,7 +149,7 @@ class Kamal::Configuration::Accessory
|
|
159
149
|
if specifics.key?("host")
|
160
150
|
host = specifics["host"]
|
161
151
|
if host
|
162
|
-
[host]
|
152
|
+
[ host ]
|
163
153
|
else
|
164
154
|
raise ArgumentError, "Missing host for accessory `#{name}`"
|
165
155
|
end
|
@@ -40,7 +40,7 @@ class Kamal::Configuration::Builder
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def context
|
43
|
-
@options["context"] || "."
|
43
|
+
@options["context"] || (git_archive? ? "-" : ".")
|
44
44
|
end
|
45
45
|
|
46
46
|
def local_arch
|
@@ -85,10 +85,14 @@ class Kamal::Configuration::Builder
|
|
85
85
|
@options["ssh"]
|
86
86
|
end
|
87
87
|
|
88
|
+
def git_archive?
|
89
|
+
Kamal::Git.used? && @options["context"].nil?
|
90
|
+
end
|
91
|
+
|
88
92
|
private
|
89
93
|
def valid?
|
90
94
|
if @options["cache"] && @options["cache"]["type"]
|
91
|
-
raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless ["gha", "registry"].include?(@options["cache"]["type"])
|
95
|
+
raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless [ "gha", "registry" ].include?(@options["cache"]["type"])
|
92
96
|
end
|
93
97
|
end
|
94
98
|
|
@@ -109,7 +113,7 @@ class Kamal::Configuration::Builder
|
|
109
113
|
end
|
110
114
|
|
111
115
|
def cache_to_config_for_gha
|
112
|
-
[ "type=gha", @options["cache"]&.fetch("options", nil)].compact.join(",")
|
116
|
+
[ "type=gha", @options["cache"]&.fetch("options", nil) ].compact.join(",")
|
113
117
|
end
|
114
118
|
|
115
119
|
def cache_to_config_for_registry
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Kamal::Configuration::Env
|
2
|
+
attr_reader :secrets_keys, :clear, :secrets_file
|
3
|
+
delegate :argumentize, to: Kamal::Utils
|
4
|
+
|
5
|
+
def self.from_config(config:, secrets_file: nil)
|
6
|
+
secrets_keys = config.fetch("secret", [])
|
7
|
+
clear = config.fetch("clear", config.key?("secret") ? {} : config)
|
8
|
+
|
9
|
+
new clear: clear, secrets_keys: secrets_keys, secrets_file: secrets_file
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(clear:, secrets_keys:, secrets_file:)
|
13
|
+
@clear = clear
|
14
|
+
@secrets_keys = secrets_keys
|
15
|
+
@secrets_file = secrets_file
|
16
|
+
end
|
17
|
+
|
18
|
+
def args
|
19
|
+
[ "--env-file", secrets_file, *argumentize("--env", clear) ]
|
20
|
+
end
|
21
|
+
|
22
|
+
def secrets_io
|
23
|
+
StringIO.new(Kamal::EnvFile.new(secrets).to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
def secrets
|
27
|
+
@secrets ||= secrets_keys.to_h { |key| [ key, ENV.fetch(key) ] }
|
28
|
+
end
|
29
|
+
|
30
|
+
def secrets_directory
|
31
|
+
File.dirname(secrets_file)
|
32
|
+
end
|
33
|
+
|
34
|
+
def merge(other)
|
35
|
+
self.class.new \
|
36
|
+
clear: @clear.merge(other.clear),
|
37
|
+
secrets_keys: @secrets_keys | other.secrets_keys,
|
38
|
+
secrets_file: secrets_file
|
39
|
+
end
|
40
|
+
end
|
@@ -51,27 +51,11 @@ class Kamal::Configuration::Role
|
|
51
51
|
|
52
52
|
|
53
53
|
def env
|
54
|
-
|
55
|
-
merged_env_with_secrets
|
56
|
-
else
|
57
|
-
merged_env
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def env_file
|
62
|
-
Kamal::EnvFile.new(env)
|
63
|
-
end
|
64
|
-
|
65
|
-
def host_env_directory
|
66
|
-
File.join config.host_env_directory, "roles"
|
67
|
-
end
|
68
|
-
|
69
|
-
def host_env_file_path
|
70
|
-
File.join host_env_directory, "#{[config.service, name, config.destination].compact.join("-")}.env"
|
54
|
+
@env ||= base_env.merge(specialized_env)
|
71
55
|
end
|
72
56
|
|
73
57
|
def env_args
|
74
|
-
|
58
|
+
env.args
|
75
59
|
end
|
76
60
|
|
77
61
|
def asset_volume_args
|
@@ -123,13 +107,13 @@ class Kamal::Configuration::Role
|
|
123
107
|
end
|
124
108
|
|
125
109
|
def cord_host_directory
|
126
|
-
File.join config.run_directory_as_docker_volume, "cords", [container_prefix, config.run_id].join("-")
|
110
|
+
File.join config.run_directory_as_docker_volume, "cords", [ container_prefix, config.run_id ].join("-")
|
127
111
|
end
|
128
112
|
|
129
113
|
def cord_volume
|
130
114
|
if (cord = health_check_options["cord"])
|
131
115
|
@cord_volume ||= Kamal::Configuration::Volume.new \
|
132
|
-
host_path: File.join(config.run_directory, "cords", [container_prefix, config.run_id].join("-")),
|
116
|
+
host_path: File.join(config.run_directory, "cords", [ container_prefix, config.run_id ].join("-")),
|
133
117
|
container_path: cord
|
134
118
|
end
|
135
119
|
end
|
@@ -192,11 +176,7 @@ class Kamal::Configuration::Role
|
|
192
176
|
end
|
193
177
|
|
194
178
|
def default_labels
|
195
|
-
|
196
|
-
{ "service" => config.service, "role" => name, "destination" => config.destination }
|
197
|
-
else
|
198
|
-
{ "service" => config.service, "role" => name }
|
199
|
-
end
|
179
|
+
{ "service" => config.service, "role" => name, "destination" => config.destination }
|
200
180
|
end
|
201
181
|
|
202
182
|
def traefik_labels
|
@@ -217,7 +197,7 @@ class Kamal::Configuration::Role
|
|
217
197
|
end
|
218
198
|
|
219
199
|
def traefik_service
|
220
|
-
|
200
|
+
container_prefix
|
221
201
|
end
|
222
202
|
|
223
203
|
def custom_labels
|
@@ -229,31 +209,21 @@ class Kamal::Configuration::Role
|
|
229
209
|
|
230
210
|
def specializations
|
231
211
|
if config.servers.is_a?(Array) || config.servers[name].is_a?(Array)
|
232
|
-
{
|
212
|
+
{}
|
233
213
|
else
|
234
214
|
config.servers[name].except("hosts")
|
235
215
|
end
|
236
216
|
end
|
237
217
|
|
238
218
|
def specialized_env
|
239
|
-
specializations
|
240
|
-
end
|
241
|
-
|
242
|
-
def merged_env
|
243
|
-
config.env&.merge(specialized_env) || {}
|
219
|
+
Kamal::Configuration::Env.from_config config: specializations.fetch("env", {})
|
244
220
|
end
|
245
221
|
|
246
222
|
# Secrets are stored in an array, which won't merge by default, so have to do it by hand.
|
247
|
-
def
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
# If there's no secret/clear split, everything is clear
|
252
|
-
clear_app_env = config.env["secret"] ? Array(config.env["clear"]) : Array(config.env["clear"] || config.env)
|
253
|
-
clear_role_env = specialized_env["secret"] ? Array(specialized_env["clear"]) : Array(specialized_env["clear"] || specialized_env)
|
254
|
-
|
255
|
-
new_env["clear"] = clear_app_env.to_h.merge(clear_role_env.to_h)
|
256
|
-
end
|
223
|
+
def base_env
|
224
|
+
Kamal::Configuration::Env.from_config \
|
225
|
+
config: config.env,
|
226
|
+
secrets_file: File.join(config.host_env_directory, "roles", "#{container_prefix}.env")
|
257
227
|
end
|
258
228
|
|
259
229
|
def http_health_check(port:, path:)
|