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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/kamal/cli/accessory.rb +92 -38
- data/lib/kamal/cli/alias/command.rb +10 -0
- data/lib/kamal/cli/app/{prepare_assets.rb → assets.rb} +1 -1
- data/lib/kamal/cli/app/boot.rb +23 -16
- data/lib/kamal/cli/app/error_pages.rb +33 -0
- data/lib/kamal/cli/app/ssl_certificates.rb +28 -0
- data/lib/kamal/cli/app.rb +132 -30
- data/lib/kamal/cli/base.rb +57 -53
- data/lib/kamal/cli/build.rb +81 -38
- data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
- data/lib/kamal/cli/healthcheck/poller.rb +18 -39
- data/lib/kamal/cli/lock.rb +2 -3
- data/lib/kamal/cli/main.rb +60 -59
- data/lib/kamal/cli/proxy.rb +290 -0
- data/lib/kamal/cli/prune.rb +0 -1
- data/lib/kamal/cli/registry.rb +2 -0
- data/lib/kamal/cli/secrets.rb +49 -0
- data/lib/kamal/cli/server.rb +6 -5
- data/lib/kamal/cli/templates/deploy.yml +53 -53
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +2 -12
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-build.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/pre-connect.sample +1 -1
- data/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample +19 -6
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/secrets +17 -0
- data/lib/kamal/cli.rb +2 -0
- data/lib/kamal/commander/specifics.rb +19 -6
- data/lib/kamal/commander.rb +39 -32
- data/lib/kamal/commands/accessory/proxy.rb +16 -0
- data/lib/kamal/commands/accessory.rb +19 -19
- data/lib/kamal/commands/app/assets.rb +10 -10
- data/lib/kamal/commands/app/containers.rb +2 -2
- data/lib/kamal/commands/app/error_pages.rb +9 -0
- data/lib/kamal/commands/app/execution.rb +7 -4
- data/lib/kamal/commands/app/images.rb +1 -1
- data/lib/kamal/commands/app/logging.rb +16 -6
- data/lib/kamal/commands/app/proxy.rb +32 -0
- data/lib/kamal/commands/app.rb +25 -24
- data/lib/kamal/commands/auditor.rb +12 -3
- data/lib/kamal/commands/base.rb +54 -8
- data/lib/kamal/commands/builder/base.rb +46 -16
- data/lib/kamal/commands/builder/clone.rb +16 -14
- data/lib/kamal/commands/builder/cloud.rb +22 -0
- data/lib/kamal/commands/builder/hybrid.rb +21 -0
- data/lib/kamal/commands/builder/local.rb +14 -0
- data/lib/kamal/commands/builder/pack.rb +46 -0
- data/lib/kamal/commands/builder/remote.rb +63 -0
- data/lib/kamal/commands/builder.rb +21 -45
- data/lib/kamal/commands/docker.rb +4 -0
- data/lib/kamal/commands/hook.rb +8 -2
- data/lib/kamal/commands/lock.rb +2 -6
- data/lib/kamal/commands/proxy.rb +127 -0
- data/lib/kamal/commands/prune.rb +1 -9
- data/lib/kamal/commands/registry.rb +9 -7
- data/lib/kamal/commands/server.rb +11 -1
- data/lib/kamal/configuration/accessory.rb +89 -12
- data/lib/kamal/configuration/alias.rb +15 -0
- data/lib/kamal/configuration/builder.rb +73 -15
- data/lib/kamal/configuration/docs/accessory.yml +53 -15
- data/lib/kamal/configuration/docs/alias.yml +26 -0
- data/lib/kamal/configuration/docs/boot.yml +3 -3
- data/lib/kamal/configuration/docs/builder.yml +63 -38
- data/lib/kamal/configuration/docs/configuration.yml +62 -46
- data/lib/kamal/configuration/docs/env.yml +61 -17
- data/lib/kamal/configuration/docs/logging.yml +3 -3
- data/lib/kamal/configuration/docs/proxy.yml +168 -0
- data/lib/kamal/configuration/docs/registry.yml +20 -13
- data/lib/kamal/configuration/docs/role.yml +14 -13
- data/lib/kamal/configuration/docs/servers.yml +2 -2
- data/lib/kamal/configuration/docs/ssh.yml +23 -19
- data/lib/kamal/configuration/docs/sshkit.yml +4 -4
- data/lib/kamal/configuration/env/tag.rb +4 -3
- data/lib/kamal/configuration/env.rb +19 -17
- data/lib/kamal/configuration/proxy/boot.rb +129 -0
- data/lib/kamal/configuration/proxy.rb +124 -0
- data/lib/kamal/configuration/registry.rb +7 -6
- data/lib/kamal/configuration/role.rb +69 -98
- data/lib/kamal/configuration/servers.rb +8 -1
- data/lib/kamal/configuration/validator/accessory.rb +6 -2
- data/lib/kamal/configuration/validator/alias.rb +15 -0
- data/lib/kamal/configuration/validator/builder.rb +6 -0
- data/lib/kamal/configuration/validator/proxy.rb +25 -0
- data/lib/kamal/configuration/validator/role.rb +3 -1
- data/lib/kamal/configuration/validator/servers.rb +1 -1
- data/lib/kamal/configuration/validator.rb +62 -24
- data/lib/kamal/configuration.rb +96 -50
- data/lib/kamal/docker.rb +30 -0
- data/lib/kamal/env_file.rb +7 -1
- data/lib/kamal/git.rb +10 -0
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +51 -0
- data/lib/kamal/secrets/adapters/base.rb +33 -0
- data/lib/kamal/secrets/adapters/bitwarden.rb +81 -0
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +66 -0
- data/lib/kamal/secrets/adapters/doppler.rb +57 -0
- data/lib/kamal/secrets/adapters/enpass.rb +71 -0
- data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +40 -0
- data/lib/kamal/secrets/adapters/one_password.rb +104 -0
- data/lib/kamal/secrets/adapters/passbolt.rb +130 -0
- data/lib/kamal/secrets/adapters/test.rb +14 -0
- data/lib/kamal/secrets/adapters.rb +16 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +33 -0
- data/lib/kamal/secrets.rb +42 -0
- data/lib/kamal/sshkit_with_ext.rb +1 -0
- data/lib/kamal/utils.rb +30 -0
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +3 -1
- metadata +63 -36
- data/lib/kamal/cli/env.rb +0 -54
- data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-traefik-reboot.sample +0 -3
- data/lib/kamal/cli/templates/template.env +0 -2
- data/lib/kamal/cli/traefik.rb +0 -122
- data/lib/kamal/commands/app/cord.rb +0 -22
- data/lib/kamal/commands/builder/multiarch/remote.rb +0 -65
- data/lib/kamal/commands/builder/multiarch.rb +0 -41
- data/lib/kamal/commands/builder/native/cached.rb +0 -25
- data/lib/kamal/commands/builder/native/remote.rb +0 -67
- data/lib/kamal/commands/builder/native.rb +0 -20
- data/lib/kamal/commands/traefik.rb +0 -85
- data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
- data/lib/kamal/configuration/docs/traefik.yml +0 -62
- data/lib/kamal/configuration/healthcheck.rb +0 -63
- data/lib/kamal/configuration/traefik.rb +0 -60
@@ -11,19 +11,23 @@ class Kamal::Commander::Specifics
|
|
11
11
|
@primary_role = primary_or_first_role(roles_on(primary_host))
|
12
12
|
|
13
13
|
stable_sort!(roles) { |role| role == primary_role ? 0 : 1 }
|
14
|
-
|
14
|
+
sort_primary_role_hosts_first!(hosts)
|
15
15
|
end
|
16
16
|
|
17
17
|
def roles_on(host)
|
18
18
|
roles.select { |role| role.hosts.include?(host.to_s) }
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
config.
|
21
|
+
def app_hosts
|
22
|
+
@app_hosts ||= sort_primary_role_hosts_first!(config.app_hosts & specified_hosts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def proxy_hosts
|
26
|
+
config.proxy_hosts & specified_hosts
|
23
27
|
end
|
24
28
|
|
25
29
|
def accessory_hosts
|
26
|
-
|
30
|
+
config.accessories.flat_map(&:hosts) & specified_hosts
|
27
31
|
end
|
28
32
|
|
29
33
|
private
|
@@ -43,7 +47,16 @@ class Kamal::Commander::Specifics
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def specified_hosts
|
46
|
-
|
47
|
-
|
50
|
+
specified_hosts = specific_hosts || config.all_hosts
|
51
|
+
|
52
|
+
if (specific_role_hosts = specific_roles&.flat_map(&:hosts)).present?
|
53
|
+
specified_hosts.select { |host| specific_role_hosts.include?(host) }
|
54
|
+
else
|
55
|
+
specified_hosts
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def sort_primary_role_hosts_first!(hosts)
|
60
|
+
stable_sort!(hosts) { |host| roles_on(host).any? { |role| role == primary_role } ? 0 : 1 }
|
48
61
|
end
|
49
62
|
end
|
data/lib/kamal/commander.rb
CHANGED
@@ -1,15 +1,23 @@
|
|
1
1
|
require "active_support/core_ext/enumerable"
|
2
2
|
require "active_support/core_ext/module/delegation"
|
3
|
+
require "active_support/core_ext/object/blank"
|
3
4
|
|
4
5
|
class Kamal::Commander
|
5
6
|
attr_accessor :verbosity, :holding_lock, :connected
|
6
|
-
|
7
|
+
attr_reader :specific_roles, :specific_hosts
|
8
|
+
delegate :hosts, :roles, :primary_host, :primary_role, :roles_on, :app_hosts, :proxy_hosts, :accessory_hosts, to: :specifics
|
7
9
|
|
8
10
|
def initialize
|
11
|
+
reset
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
9
15
|
self.verbosity = :info
|
10
|
-
self.holding_lock =
|
16
|
+
self.holding_lock = ENV["KAMAL_LOCK"] == "true"
|
11
17
|
self.connected = false
|
12
|
-
@specifics = nil
|
18
|
+
@specifics = @specific_roles = @specific_hosts = nil
|
19
|
+
@config = @config_kwargs = nil
|
20
|
+
@commands = {}
|
13
21
|
end
|
14
22
|
|
15
23
|
def config
|
@@ -23,11 +31,17 @@ class Kamal::Commander
|
|
23
31
|
@config, @config_kwargs = nil, kwargs
|
24
32
|
end
|
25
33
|
|
26
|
-
|
34
|
+
def configured?
|
35
|
+
@config || @config_kwargs
|
36
|
+
end
|
27
37
|
|
28
38
|
def specific_primary!
|
29
39
|
@specifics = nil
|
30
|
-
|
40
|
+
if specific_roles.present?
|
41
|
+
self.specific_hosts = [ specific_roles.first.primary_host ]
|
42
|
+
else
|
43
|
+
self.specific_hosts = [ config.primary_host ]
|
44
|
+
end
|
31
45
|
end
|
32
46
|
|
33
47
|
def specific_roles=(role_names)
|
@@ -56,15 +70,17 @@ class Kamal::Commander
|
|
56
70
|
end
|
57
71
|
end
|
58
72
|
|
59
|
-
def
|
60
|
-
|
73
|
+
def with_specific_hosts(hosts)
|
74
|
+
original_hosts, self.specific_hosts = specific_hosts, hosts
|
75
|
+
yield
|
76
|
+
ensure
|
77
|
+
self.specific_hosts = original_hosts
|
61
78
|
end
|
62
79
|
|
63
|
-
def
|
64
|
-
config.accessories
|
80
|
+
def accessory_names
|
81
|
+
config.accessories&.collect(&:name) || []
|
65
82
|
end
|
66
83
|
|
67
|
-
|
68
84
|
def app(role: nil, host: nil)
|
69
85
|
Kamal::Commands::App.new(config, role: role, host: host)
|
70
86
|
end
|
@@ -78,42 +94,41 @@ class Kamal::Commander
|
|
78
94
|
end
|
79
95
|
|
80
96
|
def builder
|
81
|
-
@builder ||= Kamal::Commands::Builder.new(config)
|
97
|
+
@commands[:builder] ||= Kamal::Commands::Builder.new(config)
|
82
98
|
end
|
83
99
|
|
84
100
|
def docker
|
85
|
-
@docker ||= Kamal::Commands::Docker.new(config)
|
86
|
-
end
|
87
|
-
|
88
|
-
def healthcheck
|
89
|
-
@healthcheck ||= Kamal::Commands::Healthcheck.new(config)
|
101
|
+
@commands[:docker] ||= Kamal::Commands::Docker.new(config)
|
90
102
|
end
|
91
103
|
|
92
104
|
def hook
|
93
|
-
@hook ||= Kamal::Commands::Hook.new(config)
|
105
|
+
@commands[:hook] ||= Kamal::Commands::Hook.new(config)
|
94
106
|
end
|
95
107
|
|
96
108
|
def lock
|
97
|
-
@lock ||= Kamal::Commands::Lock.new(config)
|
109
|
+
@commands[:lock] ||= Kamal::Commands::Lock.new(config)
|
110
|
+
end
|
111
|
+
|
112
|
+
def proxy
|
113
|
+
@commands[:proxy] ||= Kamal::Commands::Proxy.new(config)
|
98
114
|
end
|
99
115
|
|
100
116
|
def prune
|
101
|
-
@prune ||= Kamal::Commands::Prune.new(config)
|
117
|
+
@commands[:prune] ||= Kamal::Commands::Prune.new(config)
|
102
118
|
end
|
103
119
|
|
104
120
|
def registry
|
105
|
-
@registry ||= Kamal::Commands::Registry.new(config)
|
121
|
+
@commands[:registry] ||= Kamal::Commands::Registry.new(config)
|
106
122
|
end
|
107
123
|
|
108
124
|
def server
|
109
|
-
@server ||= Kamal::Commands::Server.new(config)
|
125
|
+
@commands[:server] ||= Kamal::Commands::Server.new(config)
|
110
126
|
end
|
111
127
|
|
112
|
-
def
|
113
|
-
|
128
|
+
def alias(name)
|
129
|
+
config.aliases[name]
|
114
130
|
end
|
115
131
|
|
116
|
-
|
117
132
|
def with_verbosity(level)
|
118
133
|
old_level = self.verbosity
|
119
134
|
|
@@ -126,14 +141,6 @@ class Kamal::Commander
|
|
126
141
|
SSHKit.config.output_verbosity = old_level
|
127
142
|
end
|
128
143
|
|
129
|
-
def boot_strategy
|
130
|
-
if config.boot.limit.present?
|
131
|
-
{ in: :groups, limit: config.boot.limit, wait: config.boot.wait }
|
132
|
-
else
|
133
|
-
{}
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
144
|
def holding_lock?
|
138
145
|
self.holding_lock
|
139
146
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kamal::Commands::Accessory::Proxy
|
2
|
+
delegate :container_name, to: :"config.proxy_boot", prefix: :proxy
|
3
|
+
|
4
|
+
def deploy(target:)
|
5
|
+
proxy_exec :deploy, service_name, *proxy.deploy_command_args(target: target)
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove
|
9
|
+
proxy_exec :remove, service_name
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def proxy_exec(*command)
|
14
|
+
docker :exec, proxy_container_name, "kamal-proxy", *command
|
15
|
+
end
|
16
|
+
end
|
@@ -1,20 +1,26 @@
|
|
1
1
|
class Kamal::Commands::Accessory < Kamal::Commands::Base
|
2
|
+
include Proxy
|
3
|
+
|
2
4
|
attr_reader :accessory_config
|
3
5
|
delegate :service_name, :image, :hosts, :port, :files, :directories, :cmd,
|
4
|
-
:publish_args, :env_args, :volume_args, :label_args, :option_args,
|
6
|
+
:network_args, :publish_args, :env_args, :volume_args, :label_args, :option_args,
|
7
|
+
:secrets_io, :secrets_path, :env_directory, :proxy, :running_proxy?, :registry,
|
8
|
+
to: :accessory_config
|
5
9
|
|
6
10
|
def initialize(config, name:)
|
7
11
|
super(config)
|
8
12
|
@accessory_config = config.accessory(name)
|
9
13
|
end
|
10
14
|
|
11
|
-
def run
|
15
|
+
def run(host: nil)
|
12
16
|
docker :run,
|
13
17
|
"--name", service_name,
|
14
18
|
"--detach",
|
15
19
|
"--restart", "unless-stopped",
|
20
|
+
*network_args,
|
16
21
|
*config.logging_args,
|
17
22
|
*publish_args,
|
23
|
+
*([ "--env", "KAMAL_HOST=\"#{host}\"" ] if host),
|
18
24
|
*env_args,
|
19
25
|
*volume_args,
|
20
26
|
*label_args,
|
@@ -31,36 +37,35 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
31
37
|
docker :container, :stop, service_name
|
32
38
|
end
|
33
39
|
|
34
|
-
def info
|
35
|
-
docker :ps, *service_filter
|
40
|
+
def info(all: false, quiet: false)
|
41
|
+
docker :ps, *("-a" if all), *("-q" if quiet), *service_filter
|
36
42
|
end
|
37
43
|
|
38
|
-
|
39
|
-
def logs(since: nil, lines: nil, grep: nil, grep_options: nil)
|
44
|
+
def logs(timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
|
40
45
|
pipe \
|
41
|
-
docker(:logs, service_name, (" --since #{since}" if since), (" --tail #{lines}" if lines), "--timestamps", "2>&1"),
|
46
|
+
docker(:logs, service_name, (" --since #{since}" if since), (" --tail #{lines}" if lines), ("--timestamps" if timestamps), "2>&1"),
|
42
47
|
("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
|
43
48
|
end
|
44
49
|
|
45
|
-
def follow_logs(grep: nil, grep_options: nil)
|
50
|
+
def follow_logs(timestamps: true, grep: nil, grep_options: nil)
|
46
51
|
run_over_ssh \
|
47
52
|
pipe \
|
48
|
-
docker(:logs, service_name, "--timestamps", "--tail", "10", "--follow", "2>&1"),
|
53
|
+
docker(:logs, service_name, ("--timestamps" if timestamps), "--tail", "10", "--follow", "2>&1"),
|
49
54
|
(%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
|
50
55
|
end
|
51
56
|
|
52
|
-
|
53
57
|
def execute_in_existing_container(*command, interactive: false)
|
54
58
|
docker :exec,
|
55
|
-
(
|
59
|
+
(docker_interactive_args if interactive),
|
56
60
|
service_name,
|
57
61
|
*command
|
58
62
|
end
|
59
63
|
|
60
64
|
def execute_in_new_container(*command, interactive: false)
|
61
65
|
docker :run,
|
62
|
-
(
|
66
|
+
(docker_interactive_args if interactive),
|
63
67
|
"--rm",
|
68
|
+
*network_args,
|
64
69
|
*env_args,
|
65
70
|
*volume_args,
|
66
71
|
image,
|
@@ -79,7 +84,6 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
79
84
|
super command, host: hosts.first
|
80
85
|
end
|
81
86
|
|
82
|
-
|
83
87
|
def ensure_local_file_present(local_file)
|
84
88
|
if !local_file.is_a?(StringIO) && !Pathname.new(local_file).exist?
|
85
89
|
raise "Missing file: #{local_file}"
|
@@ -98,12 +102,8 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
98
102
|
docker :image, :rm, "--force", image
|
99
103
|
end
|
100
104
|
|
101
|
-
def
|
102
|
-
make_directory
|
103
|
-
end
|
104
|
-
|
105
|
-
def remove_env_file
|
106
|
-
[ :rm, "-f", accessory_config.env.secrets_file ]
|
105
|
+
def ensure_env_directory
|
106
|
+
make_directory env_directory
|
107
107
|
end
|
108
108
|
|
109
109
|
private
|
@@ -3,18 +3,18 @@ module Kamal::Commands::App::Assets
|
|
3
3
|
asset_container = "#{role.container_prefix}-assets"
|
4
4
|
|
5
5
|
combine \
|
6
|
-
make_directory(role.
|
7
|
-
[ *docker(:
|
8
|
-
docker(:
|
9
|
-
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.
|
10
|
-
docker(:
|
6
|
+
make_directory(role.asset_extracted_directory),
|
7
|
+
[ *docker(:container, :rm, asset_container, "2> /dev/null"), "|| true" ],
|
8
|
+
docker(:container, :create, "--name", asset_container, config.absolute_image),
|
9
|
+
docker(:container, :cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_directory),
|
10
|
+
docker(:container, :rm, asset_container),
|
11
11
|
by: "&&"
|
12
12
|
end
|
13
13
|
|
14
14
|
def sync_asset_volumes(old_version: nil)
|
15
|
-
new_extracted_path, new_volume_path = role.
|
15
|
+
new_extracted_path, new_volume_path = role.asset_extracted_directory(config.version), role.asset_volume.host_path
|
16
16
|
if old_version.present?
|
17
|
-
old_extracted_path, old_volume_path = role.
|
17
|
+
old_extracted_path, old_volume_path = role.asset_extracted_directory(old_version), role.asset_volume(old_version).host_path
|
18
18
|
end
|
19
19
|
|
20
20
|
commands = [ make_directory(new_volume_path), copy_contents(new_extracted_path, new_volume_path) ]
|
@@ -29,8 +29,8 @@ module Kamal::Commands::App::Assets
|
|
29
29
|
|
30
30
|
def clean_up_assets
|
31
31
|
chain \
|
32
|
-
find_and_remove_older_siblings(role.
|
33
|
-
find_and_remove_older_siblings(role.
|
32
|
+
find_and_remove_older_siblings(role.asset_extracted_directory),
|
33
|
+
find_and_remove_older_siblings(role.asset_volume_directory)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
@@ -39,7 +39,7 @@ module Kamal::Commands::App::Assets
|
|
39
39
|
:find,
|
40
40
|
Pathname.new(path).dirname.to_s,
|
41
41
|
"-maxdepth 1",
|
42
|
-
"-name", "'#{role.
|
42
|
+
"-name", "'#{role.name}-*'",
|
43
43
|
"!", "-name", Pathname.new(path).basename.to_s,
|
44
44
|
"-exec rm -rf \"{}\" +"
|
45
45
|
]
|
@@ -2,7 +2,7 @@ module Kamal::Commands::App::Containers
|
|
2
2
|
DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
|
3
3
|
|
4
4
|
def list_containers
|
5
|
-
docker :container, :ls, "--all", *
|
5
|
+
docker :container, :ls, "--all", *container_filter_args
|
6
6
|
end
|
7
7
|
|
8
8
|
def list_container_names
|
@@ -20,7 +20,7 @@ module Kamal::Commands::App::Containers
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def remove_containers
|
23
|
-
docker :container, :prune, "--force", *
|
23
|
+
docker :container, :prune, "--force", *container_filter_args
|
24
24
|
end
|
25
25
|
|
26
26
|
def container_health_log(version:)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Kamal::Commands::App::ErrorPages
|
2
|
+
def create_error_pages_directory
|
3
|
+
make_directory(config.proxy_boot.error_pages_directory)
|
4
|
+
end
|
5
|
+
|
6
|
+
def clean_up_error_pages
|
7
|
+
[ :find, config.proxy_boot.error_pages_directory, "-mindepth", "1", "-maxdepth", "1", "!", "-name", KAMAL.config.version, "-exec", "rm", "-rf", "{} +" ]
|
8
|
+
end
|
9
|
+
end
|
@@ -1,18 +1,21 @@
|
|
1
1
|
module Kamal::Commands::App::Execution
|
2
2
|
def execute_in_existing_container(*command, interactive: false, env:)
|
3
3
|
docker :exec,
|
4
|
-
(
|
4
|
+
(docker_interactive_args if interactive),
|
5
5
|
*argumentize("--env", env),
|
6
6
|
container_name,
|
7
7
|
*command
|
8
8
|
end
|
9
9
|
|
10
|
-
def execute_in_new_container(*command, interactive: false, env:)
|
10
|
+
def execute_in_new_container(*command, interactive: false, detach: false, env:)
|
11
11
|
docker :run,
|
12
|
-
(
|
13
|
-
"--
|
12
|
+
(docker_interactive_args if interactive),
|
13
|
+
("--detach" if detach),
|
14
|
+
("--rm" unless detach),
|
15
|
+
"--network", "kamal",
|
14
16
|
*role&.env_args(host),
|
15
17
|
*argumentize("--env", env),
|
18
|
+
*role.logging_args,
|
16
19
|
*config.volume_args,
|
17
20
|
*role&.option_args,
|
18
21
|
config.absolute_image,
|
@@ -1,18 +1,28 @@
|
|
1
1
|
module Kamal::Commands::App::Logging
|
2
|
-
def logs(
|
2
|
+
def logs(container_id: nil, timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
|
3
3
|
pipe \
|
4
|
-
|
5
|
-
"xargs docker logs#{" --since #{since}" if since}#{" --tail #{lines}" if lines} 2>&1",
|
4
|
+
container_id_command(container_id),
|
5
|
+
"xargs docker logs#{" --timestamps" if timestamps}#{" --since #{since}" if since}#{" --tail #{lines}" if lines} 2>&1",
|
6
6
|
("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
|
7
7
|
end
|
8
8
|
|
9
|
-
def follow_logs(host:, lines: nil, grep: nil, grep_options: nil)
|
9
|
+
def follow_logs(host:, container_id: nil, timestamps: true, lines: nil, grep: nil, grep_options: nil)
|
10
10
|
run_over_ssh \
|
11
11
|
pipe(
|
12
|
-
|
13
|
-
"xargs docker logs --timestamps#{" --tail #{lines}" if lines} --follow 2>&1",
|
12
|
+
container_id_command(container_id),
|
13
|
+
"xargs docker logs#{" --timestamps" if timestamps}#{" --tail #{lines}" if lines} --follow 2>&1",
|
14
14
|
(%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
|
15
15
|
),
|
16
16
|
host: host
|
17
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def container_id_command(container_id)
|
22
|
+
case container_id
|
23
|
+
when Array then container_id
|
24
|
+
when String, Symbol then "echo #{container_id}"
|
25
|
+
else current_running_container_id
|
26
|
+
end
|
27
|
+
end
|
18
28
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Kamal::Commands::App::Proxy
|
2
|
+
delegate :container_name, to: :"config.proxy_boot", prefix: :proxy
|
3
|
+
|
4
|
+
def deploy(target:)
|
5
|
+
proxy_exec :deploy, role.container_prefix, *role.proxy.deploy_command_args(target: target)
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove
|
9
|
+
proxy_exec :remove, role.container_prefix
|
10
|
+
end
|
11
|
+
|
12
|
+
def live
|
13
|
+
proxy_exec :resume, role.container_prefix
|
14
|
+
end
|
15
|
+
|
16
|
+
def maintenance(**options)
|
17
|
+
proxy_exec :stop, role.container_prefix, *role.proxy.stop_command_args(**options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove_proxy_app_directory
|
21
|
+
remove_directory config.proxy_boot.app_directory
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_ssl_directory
|
25
|
+
make_directory(File.join(config.proxy_boot.tls_directory, role.name))
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def proxy_exec(*command)
|
30
|
+
docker :exec, proxy_container_name, "kamal-proxy", *command
|
31
|
+
end
|
32
|
+
end
|
data/lib/kamal/commands/app.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
class Kamal::Commands::App < Kamal::Commands::Base
|
2
|
-
include Assets, Containers,
|
2
|
+
include Assets, Containers, ErrorPages, Execution, Images, Logging, Proxy
|
3
3
|
|
4
4
|
ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
|
5
5
|
|
6
6
|
attr_reader :role, :host
|
7
7
|
|
8
|
+
delegate :container_name, to: :role
|
9
|
+
|
8
10
|
def initialize(config, role: nil, host: nil)
|
9
11
|
super(config)
|
10
12
|
@role = role
|
@@ -16,11 +18,12 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
16
18
|
"--detach",
|
17
19
|
"--restart unless-stopped",
|
18
20
|
"--name", container_name,
|
21
|
+
"--network", "kamal",
|
19
22
|
*([ "--hostname", hostname ] if hostname),
|
20
|
-
"
|
21
|
-
"
|
23
|
+
"--env", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
24
|
+
"--env", "KAMAL_VERSION=\"#{config.version}\"",
|
25
|
+
"--env", "KAMAL_HOST=\"#{host}\"",
|
22
26
|
*role.env_args(host),
|
23
|
-
*role.health_check_args,
|
24
27
|
*role.logging_args,
|
25
28
|
*config.volume_args,
|
26
29
|
*role.asset_volume_args,
|
@@ -41,11 +44,11 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
41
44
|
def stop(version: nil)
|
42
45
|
pipe \
|
43
46
|
version ? container_id_for_version(version) : current_running_container_id,
|
44
|
-
xargs(
|
47
|
+
xargs(docker(:stop, *role.stop_args))
|
45
48
|
end
|
46
49
|
|
47
50
|
def info
|
48
|
-
docker :ps, *
|
51
|
+
docker :ps, *container_filter_args
|
49
52
|
end
|
50
53
|
|
51
54
|
|
@@ -65,25 +68,15 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
65
68
|
|
66
69
|
def list_versions(*docker_args, statuses: nil)
|
67
70
|
pipe \
|
68
|
-
docker(:ps, *
|
71
|
+
docker(:ps, *container_filter_args(statuses: statuses), *docker_args, "--format", '"{{.Names}}"'),
|
69
72
|
extract_version_from_name
|
70
73
|
end
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
make_directory role.env(host).secrets_directory
|
75
|
-
end
|
76
|
-
|
77
|
-
def remove_env_file
|
78
|
-
[ :rm, "-f", role.env(host).secrets_file ]
|
75
|
+
def ensure_env_directory
|
76
|
+
make_directory role.env_directory
|
79
77
|
end
|
80
78
|
|
81
|
-
|
82
79
|
private
|
83
|
-
def container_name(version = nil)
|
84
|
-
[ role.container_prefix, version || config.version ].compact.join("-")
|
85
|
-
end
|
86
|
-
|
87
80
|
def latest_image_id
|
88
81
|
docker :image, :ls, *argumentize("--filter", "reference=#{config.latest_image}"), "--format", "'{{.ID}}'"
|
89
82
|
end
|
@@ -99,11 +92,15 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
99
92
|
end
|
100
93
|
|
101
94
|
def latest_container(format:, filters: nil)
|
102
|
-
docker :ps, "--latest", *format, *
|
95
|
+
docker :ps, "--latest", *format, *container_filter_args(statuses: ACTIVE_DOCKER_STATUSES), argumentize("--filter", filters)
|
96
|
+
end
|
97
|
+
|
98
|
+
def container_filter_args(statuses: nil)
|
99
|
+
argumentize "--filter", container_filters(statuses: statuses)
|
103
100
|
end
|
104
101
|
|
105
|
-
def
|
106
|
-
argumentize "--filter",
|
102
|
+
def image_filter_args
|
103
|
+
argumentize "--filter", image_filters
|
107
104
|
end
|
108
105
|
|
109
106
|
def extract_version_from_name
|
@@ -111,13 +108,17 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
111
108
|
%(while read line; do echo ${line##{role.container_prefix}-}; done)
|
112
109
|
end
|
113
110
|
|
114
|
-
def
|
111
|
+
def container_filters(statuses: nil)
|
115
112
|
[ "label=service=#{config.service}" ].tap do |filters|
|
116
|
-
filters << "label=destination=#{config.destination}"
|
113
|
+
filters << "label=destination=#{config.destination}"
|
117
114
|
filters << "label=role=#{role}" if role
|
118
115
|
statuses&.each do |status|
|
119
116
|
filters << "status=#{status}"
|
120
117
|
end
|
121
118
|
end
|
122
119
|
end
|
120
|
+
|
121
|
+
def image_filters
|
122
|
+
[ "label=service=#{config.service}" ]
|
123
|
+
end
|
123
124
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class Kamal::Commands::Auditor < Kamal::Commands::Base
|
2
2
|
attr_reader :details
|
3
|
+
delegate :escape_shell_value, to: Kamal::Utils
|
3
4
|
|
4
5
|
def initialize(config, **details)
|
5
6
|
super(config)
|
@@ -8,9 +9,9 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
|
|
8
9
|
|
9
10
|
# Runs remotely
|
10
11
|
def record(line, **details)
|
11
|
-
|
12
|
-
|
13
|
-
audit_log_file
|
12
|
+
combine \
|
13
|
+
make_run_directory,
|
14
|
+
append([ :echo, escape_shell_value(audit_line(line, **details)) ], audit_log_file)
|
14
15
|
end
|
15
16
|
|
16
17
|
def reveal
|
@@ -27,4 +28,12 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
|
|
27
28
|
def audit_tags(**details)
|
28
29
|
tags(**self.details, **details)
|
29
30
|
end
|
31
|
+
|
32
|
+
def make_run_directory
|
33
|
+
[ :mkdir, "-p", config.run_directory ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def audit_line(line, **details)
|
37
|
+
"#{audit_tags(**details).except(:version, :service_version, :service)} #{line}"
|
38
|
+
end
|
30
39
|
end
|