kamal 1.8.3 → 2.0.0.beta1
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 +44 -20
- data/lib/kamal/cli/alias/command.rb +9 -0
- data/lib/kamal/cli/app/boot.rb +22 -16
- data/lib/kamal/cli/app.rb +40 -5
- data/lib/kamal/cli/base.rb +19 -51
- data/lib/kamal/cli/build.rb +12 -13
- 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 +54 -51
- data/lib/kamal/cli/proxy.rb +224 -0
- data/lib/kamal/cli/prune.rb +0 -1
- data/lib/kamal/cli/secrets.rb +36 -0
- data/lib/kamal/cli/server.rb +2 -3
- data/lib/kamal/cli/templates/deploy.yml +4 -21
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/secrets +16 -0
- data/lib/kamal/cli.rb +1 -0
- data/lib/kamal/commander/specifics.rb +3 -3
- data/lib/kamal/commander.rb +24 -8
- data/lib/kamal/commands/accessory.rb +7 -7
- data/lib/kamal/commands/app/assets.rb +8 -8
- data/lib/kamal/commands/app/proxy.rb +16 -0
- data/lib/kamal/commands/app.rb +7 -15
- data/lib/kamal/commands/auditor.rb +6 -3
- data/lib/kamal/commands/base.rb +8 -0
- data/lib/kamal/commands/builder/base.rb +26 -13
- data/lib/kamal/commands/builder/hybrid.rb +21 -0
- data/lib/kamal/commands/builder/local.rb +14 -0
- data/lib/kamal/commands/builder/remote.rb +63 -0
- data/lib/kamal/commands/builder.rb +13 -29
- data/lib/kamal/commands/docker.rb +4 -0
- data/lib/kamal/commands/hook.rb +5 -2
- data/lib/kamal/commands/lock.rb +2 -6
- data/lib/kamal/commands/proxy.rb +77 -0
- data/lib/kamal/commands/prune.rb +1 -9
- data/lib/kamal/commands/server.rb +11 -1
- data/lib/kamal/configuration/accessory.rb +14 -2
- data/lib/kamal/configuration/alias.rb +15 -0
- data/lib/kamal/configuration/builder.rb +52 -18
- data/lib/kamal/configuration/docs/alias.yml +26 -0
- data/lib/kamal/configuration/docs/builder.yml +26 -23
- data/lib/kamal/configuration/docs/configuration.yml +22 -16
- data/lib/kamal/configuration/docs/env.yml +10 -11
- data/lib/kamal/configuration/docs/proxy.yml +100 -0
- data/lib/kamal/configuration/docs/registry.yml +4 -2
- data/lib/kamal/configuration/docs/role.yml +3 -5
- data/lib/kamal/configuration/env/tag.rb +4 -3
- data/lib/kamal/configuration/env.rb +10 -17
- data/lib/kamal/configuration/proxy.rb +66 -0
- data/lib/kamal/configuration/registry.rb +3 -2
- data/lib/kamal/configuration/role.rb +63 -94
- data/lib/kamal/configuration/validator/alias.rb +15 -0
- data/lib/kamal/configuration/validator/builder.rb +4 -0
- data/lib/kamal/configuration/validator/proxy.rb +11 -0
- data/lib/kamal/configuration/validator.rb +42 -24
- data/lib/kamal/configuration.rb +91 -33
- data/lib/kamal/env_file.rb +4 -0
- data/lib/kamal/secrets/adapters/base.rb +18 -0
- data/lib/kamal/secrets/adapters/bitwarden.rb +64 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +30 -0
- data/lib/kamal/secrets/adapters/one_password.rb +61 -0
- data/lib/kamal/secrets/adapters/test.rb +10 -0
- data/lib/kamal/secrets/adapters.rb +14 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +32 -0
- data/lib/kamal/secrets.rb +37 -0
- data/lib/kamal/sshkit_with_ext.rb +1 -0
- data/lib/kamal/utils.rb +28 -0
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +3 -1
- metadata +32 -23
- 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/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
- /data/lib/kamal/cli/templates/sample_hooks/{pre-traefik-reboot.sample → pre-proxy-reboot.sample} +0 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
class Kamal::Secrets::Adapters::LastPass < Kamal::Secrets::Adapters::Base
|
2
|
+
private
|
3
|
+
def login(account)
|
4
|
+
unless loggedin?(account)
|
5
|
+
`lpass login #{account.shellescape}`
|
6
|
+
raise RuntimeError, "Failed to login to 1Password" unless $?.success?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def loggedin?(account)
|
11
|
+
`lpass status --color never`.strip == "Logged in as #{account}."
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch_secrets(secrets, account:, session:)
|
15
|
+
items = `lpass show #{secrets.map(&:shellescape).join(" ")} --json`
|
16
|
+
raise RuntimeError, "Could not read #{secrets} from 1Password" unless $?.success?
|
17
|
+
|
18
|
+
items = JSON.parse(items)
|
19
|
+
|
20
|
+
{}.tap do |results|
|
21
|
+
items.each do |item|
|
22
|
+
results[item["fullname"]] = item["password"]
|
23
|
+
end
|
24
|
+
|
25
|
+
if (missing_items = secrets - results.keys).any?
|
26
|
+
raise RuntimeError, "Could not find #{missing_items.join(", ")} in LassPass"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Kamal::Secrets::Adapters::OnePassword < Kamal::Secrets::Adapters::Base
|
2
|
+
delegate :optionize, to: Kamal::Utils
|
3
|
+
|
4
|
+
private
|
5
|
+
def login(account)
|
6
|
+
unless loggedin?(account)
|
7
|
+
`op signin #{to_options(account: account, force: true, raw: true)}`.tap do
|
8
|
+
raise RuntimeError, "Failed to login to 1Password" unless $?.success?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def loggedin?(account)
|
14
|
+
`op account get --account #{account.shellescape} 2> /dev/null`
|
15
|
+
$?.success?
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_secrets(secrets, account:, session:)
|
19
|
+
{}.tap do |results|
|
20
|
+
vaults_items_fields(secrets).map do |vault, items|
|
21
|
+
items.each do |item, fields|
|
22
|
+
fields_json = JSON.parse(op_item_get(vault, item, fields, account: account, session: session))
|
23
|
+
fields_json = [ fields_json ] if fields.one?
|
24
|
+
|
25
|
+
fields_json.each do |field_json|
|
26
|
+
# The reference is in the form `op://vault/item/field[/field]`
|
27
|
+
field = field_json["reference"].delete_prefix("op://").delete_suffix("/password")
|
28
|
+
results[field] = field_json["value"]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_options(**options)
|
36
|
+
optionize(options.compact).join(" ")
|
37
|
+
end
|
38
|
+
|
39
|
+
def vaults_items_fields(secrets)
|
40
|
+
{}.tap do |vaults|
|
41
|
+
secrets.each do |secret|
|
42
|
+
secret = secret.delete_prefix("op://")
|
43
|
+
vault, item, *fields = secret.split("/")
|
44
|
+
fields << "password" if fields.empty?
|
45
|
+
|
46
|
+
vaults[vault] ||= {}
|
47
|
+
vaults[vault][item] ||= []
|
48
|
+
vaults[vault][item] << fields.join(".")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def op_item_get(vault, item, fields, account:, session:)
|
54
|
+
labels = fields.map { |field| "label=#{field}" }.join(",")
|
55
|
+
options = to_options(vault: vault, fields: labels, format: "json", account: account, session: session.presence)
|
56
|
+
|
57
|
+
`op item get #{item.shellescape} #{options}`.tap do
|
58
|
+
raise RuntimeError, "Could not read #{fields.join(", ")} from #{item} in the #{vault} 1Password vault" unless $?.success?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "active_support/core_ext/string/inflections"
|
2
|
+
module Kamal::Secrets::Adapters
|
3
|
+
def self.lookup(name)
|
4
|
+
name = "one_password" if name.downcase == "1password"
|
5
|
+
name = "last_pass" if name.downcase == "lastpass"
|
6
|
+
adapter_class(name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.adapter_class(name)
|
10
|
+
Object.const_get("Kamal::Secrets::Adapters::#{name.camelize}").new
|
11
|
+
rescue NameError => e
|
12
|
+
raise RuntimeError, "Unknown secrets adapter: #{name}"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Kamal::Secrets::Dotenv::InlineCommandSubstitution
|
2
|
+
class << self
|
3
|
+
def install!
|
4
|
+
::Dotenv::Parser.substitutions.map! { |sub| sub == ::Dotenv::Substitutions::Command ? self : sub }
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(value, _env, overwrite: false)
|
8
|
+
# Process interpolated shell commands
|
9
|
+
value.gsub(Dotenv::Substitutions::Command.singleton_class::INTERPOLATED_SHELL_COMMAND) do |*|
|
10
|
+
# Eliminate opening and closing parentheses
|
11
|
+
command = $LAST_MATCH_INFO[:cmd][1..-2]
|
12
|
+
|
13
|
+
if $LAST_MATCH_INFO[:backslash]
|
14
|
+
# Command is escaped, don't replace it.
|
15
|
+
$LAST_MATCH_INFO[0][1..]
|
16
|
+
else
|
17
|
+
if command =~ /\A\s*kamal\s*secrets\s+/
|
18
|
+
# Inline the command
|
19
|
+
inline_secrets_command(command)
|
20
|
+
else
|
21
|
+
# Execute the command and return the value
|
22
|
+
`#{command}`.chomp
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def inline_secrets_command(command)
|
29
|
+
Kamal::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "dotenv"
|
2
|
+
|
3
|
+
class Kamal::Secrets
|
4
|
+
attr_reader :secrets_files
|
5
|
+
|
6
|
+
Kamal::Secrets::Dotenv::InlineCommandSubstitution.install!
|
7
|
+
|
8
|
+
def initialize(destination: nil)
|
9
|
+
@secrets_files = \
|
10
|
+
[ ".kamal/secrets-common", ".kamal/secrets#{(".#{destination}" if destination)}" ].select { |f| File.exist?(f) }
|
11
|
+
@mutex = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
# Fetching secrets may ask the user for input, so ensure only one thread does that
|
16
|
+
@mutex.synchronize do
|
17
|
+
secrets.fetch(key)
|
18
|
+
end
|
19
|
+
rescue KeyError
|
20
|
+
if secrets_files
|
21
|
+
raise Kamal::ConfigurationError, "Secret '#{key}' not found in #{secrets_files.join(", ")}"
|
22
|
+
else
|
23
|
+
raise Kamal::ConfigurationError, "Secret '#{key}' not found, no secret files provided"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_h
|
28
|
+
secrets
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def secrets
|
33
|
+
@secrets ||= secrets_files.inject({}) do |secrets, secrets_file|
|
34
|
+
secrets.merge!(::Dotenv.parse(secrets_file))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/kamal/utils.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "active_support/core_ext/object/try"
|
2
|
+
|
1
3
|
module Kamal::Utils
|
2
4
|
extend self
|
3
5
|
|
@@ -54,6 +56,12 @@ module Kamal::Utils
|
|
54
56
|
|
55
57
|
# Escape a value to make it safe for shell use.
|
56
58
|
def escape_shell_value(value)
|
59
|
+
value.to_s.scan(/[\x00-\x7F]+|[^\x00-\x7F]+/) \
|
60
|
+
.map { |part| part.ascii_only? ? escape_ascii_shell_value(part) : part }
|
61
|
+
.join
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape_ascii_shell_value(value)
|
57
65
|
value.to_s.dump
|
58
66
|
.gsub(/`/, '\\\\`')
|
59
67
|
.gsub(DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX, '\$')
|
@@ -77,4 +85,24 @@ module Kamal::Utils
|
|
77
85
|
def stable_sort!(elements, &block)
|
78
86
|
elements.sort_by!.with_index { |element, index| [ block.call(element), index ] }
|
79
87
|
end
|
88
|
+
|
89
|
+
def join_commands(commands)
|
90
|
+
commands.map(&:strip).join(" ")
|
91
|
+
end
|
92
|
+
|
93
|
+
def docker_arch
|
94
|
+
arch = `docker info --format '{{.Architecture}}'`.strip
|
95
|
+
case arch
|
96
|
+
when /aarch64/
|
97
|
+
"arm64"
|
98
|
+
when /x86_64/
|
99
|
+
"amd64"
|
100
|
+
else
|
101
|
+
arch
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def older_version?(version, other_version)
|
106
|
+
Gem::Version.new(version.delete_prefix("v")) < Gem::Version.new(other_version.delete_prefix("v"))
|
107
|
+
end
|
80
108
|
end
|
data/lib/kamal/version.rb
CHANGED
data/lib/kamal.rb
CHANGED
@@ -5,8 +5,10 @@ end
|
|
5
5
|
require "active_support"
|
6
6
|
require "zeitwerk"
|
7
7
|
require "yaml"
|
8
|
+
require "tmpdir"
|
9
|
+
require "pathname"
|
8
10
|
|
9
11
|
loader = Zeitwerk::Loader.for_gem
|
10
12
|
loader.ignore(File.join(__dir__, "kamal", "sshkit_with_ext.rb"))
|
11
13
|
loader.setup
|
12
|
-
loader.
|
14
|
+
loader.eager_load_namespace(Kamal::Cli) # We need all commands loaded.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kamal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -64,28 +64,28 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '1.
|
67
|
+
version: '1.3'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '1.
|
74
|
+
version: '1.3'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: dotenv
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
81
|
+
version: '3.1'
|
82
82
|
type: :runtime
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
88
|
+
version: '3.1'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: zeitwerk
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,31 +211,32 @@ files:
|
|
211
211
|
- lib/kamal.rb
|
212
212
|
- lib/kamal/cli.rb
|
213
213
|
- lib/kamal/cli/accessory.rb
|
214
|
+
- lib/kamal/cli/alias/command.rb
|
214
215
|
- lib/kamal/cli/app.rb
|
215
216
|
- lib/kamal/cli/app/boot.rb
|
216
217
|
- lib/kamal/cli/app/prepare_assets.rb
|
217
218
|
- lib/kamal/cli/base.rb
|
218
219
|
- lib/kamal/cli/build.rb
|
219
220
|
- lib/kamal/cli/build/clone.rb
|
220
|
-
- lib/kamal/cli/env.rb
|
221
221
|
- lib/kamal/cli/healthcheck/barrier.rb
|
222
222
|
- lib/kamal/cli/healthcheck/error.rb
|
223
223
|
- lib/kamal/cli/healthcheck/poller.rb
|
224
224
|
- lib/kamal/cli/lock.rb
|
225
225
|
- lib/kamal/cli/main.rb
|
226
|
+
- lib/kamal/cli/proxy.rb
|
226
227
|
- lib/kamal/cli/prune.rb
|
227
228
|
- lib/kamal/cli/registry.rb
|
229
|
+
- lib/kamal/cli/secrets.rb
|
228
230
|
- lib/kamal/cli/server.rb
|
229
231
|
- lib/kamal/cli/templates/deploy.yml
|
230
232
|
- lib/kamal/cli/templates/sample_hooks/docker-setup.sample
|
231
233
|
- lib/kamal/cli/templates/sample_hooks/post-deploy.sample
|
232
|
-
- lib/kamal/cli/templates/sample_hooks/post-
|
234
|
+
- lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample
|
233
235
|
- lib/kamal/cli/templates/sample_hooks/pre-build.sample
|
234
236
|
- lib/kamal/cli/templates/sample_hooks/pre-connect.sample
|
235
237
|
- lib/kamal/cli/templates/sample_hooks/pre-deploy.sample
|
236
|
-
- lib/kamal/cli/templates/sample_hooks/pre-
|
237
|
-
- lib/kamal/cli/templates/
|
238
|
-
- lib/kamal/cli/traefik.rb
|
238
|
+
- lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample
|
239
|
+
- lib/kamal/cli/templates/secrets
|
239
240
|
- lib/kamal/commander.rb
|
240
241
|
- lib/kamal/commander/specifics.rb
|
241
242
|
- lib/kamal/commands.rb
|
@@ -243,66 +244,74 @@ files:
|
|
243
244
|
- lib/kamal/commands/app.rb
|
244
245
|
- lib/kamal/commands/app/assets.rb
|
245
246
|
- lib/kamal/commands/app/containers.rb
|
246
|
-
- lib/kamal/commands/app/cord.rb
|
247
247
|
- lib/kamal/commands/app/execution.rb
|
248
248
|
- lib/kamal/commands/app/images.rb
|
249
249
|
- lib/kamal/commands/app/logging.rb
|
250
|
+
- lib/kamal/commands/app/proxy.rb
|
250
251
|
- lib/kamal/commands/auditor.rb
|
251
252
|
- lib/kamal/commands/base.rb
|
252
253
|
- lib/kamal/commands/builder.rb
|
253
254
|
- lib/kamal/commands/builder/base.rb
|
254
255
|
- lib/kamal/commands/builder/clone.rb
|
255
|
-
- lib/kamal/commands/builder/
|
256
|
-
- lib/kamal/commands/builder/
|
257
|
-
- lib/kamal/commands/builder/
|
258
|
-
- lib/kamal/commands/builder/native/cached.rb
|
259
|
-
- lib/kamal/commands/builder/native/remote.rb
|
256
|
+
- lib/kamal/commands/builder/hybrid.rb
|
257
|
+
- lib/kamal/commands/builder/local.rb
|
258
|
+
- lib/kamal/commands/builder/remote.rb
|
260
259
|
- lib/kamal/commands/docker.rb
|
261
260
|
- lib/kamal/commands/hook.rb
|
262
261
|
- lib/kamal/commands/lock.rb
|
262
|
+
- lib/kamal/commands/proxy.rb
|
263
263
|
- lib/kamal/commands/prune.rb
|
264
264
|
- lib/kamal/commands/registry.rb
|
265
265
|
- lib/kamal/commands/server.rb
|
266
|
-
- lib/kamal/commands/traefik.rb
|
267
266
|
- lib/kamal/configuration.rb
|
268
267
|
- lib/kamal/configuration/accessory.rb
|
268
|
+
- lib/kamal/configuration/alias.rb
|
269
269
|
- lib/kamal/configuration/boot.rb
|
270
270
|
- lib/kamal/configuration/builder.rb
|
271
271
|
- lib/kamal/configuration/docs/accessory.yml
|
272
|
+
- lib/kamal/configuration/docs/alias.yml
|
272
273
|
- lib/kamal/configuration/docs/boot.yml
|
273
274
|
- lib/kamal/configuration/docs/builder.yml
|
274
275
|
- lib/kamal/configuration/docs/configuration.yml
|
275
276
|
- lib/kamal/configuration/docs/env.yml
|
276
|
-
- lib/kamal/configuration/docs/healthcheck.yml
|
277
277
|
- lib/kamal/configuration/docs/logging.yml
|
278
|
+
- lib/kamal/configuration/docs/proxy.yml
|
278
279
|
- lib/kamal/configuration/docs/registry.yml
|
279
280
|
- lib/kamal/configuration/docs/role.yml
|
280
281
|
- lib/kamal/configuration/docs/servers.yml
|
281
282
|
- lib/kamal/configuration/docs/ssh.yml
|
282
283
|
- lib/kamal/configuration/docs/sshkit.yml
|
283
|
-
- lib/kamal/configuration/docs/traefik.yml
|
284
284
|
- lib/kamal/configuration/env.rb
|
285
285
|
- lib/kamal/configuration/env/tag.rb
|
286
|
-
- lib/kamal/configuration/healthcheck.rb
|
287
286
|
- lib/kamal/configuration/logging.rb
|
287
|
+
- lib/kamal/configuration/proxy.rb
|
288
288
|
- lib/kamal/configuration/registry.rb
|
289
289
|
- lib/kamal/configuration/role.rb
|
290
290
|
- lib/kamal/configuration/servers.rb
|
291
291
|
- lib/kamal/configuration/ssh.rb
|
292
292
|
- lib/kamal/configuration/sshkit.rb
|
293
|
-
- lib/kamal/configuration/traefik.rb
|
294
293
|
- lib/kamal/configuration/validation.rb
|
295
294
|
- lib/kamal/configuration/validator.rb
|
296
295
|
- lib/kamal/configuration/validator/accessory.rb
|
296
|
+
- lib/kamal/configuration/validator/alias.rb
|
297
297
|
- lib/kamal/configuration/validator/builder.rb
|
298
298
|
- lib/kamal/configuration/validator/configuration.rb
|
299
299
|
- lib/kamal/configuration/validator/env.rb
|
300
|
+
- lib/kamal/configuration/validator/proxy.rb
|
300
301
|
- lib/kamal/configuration/validator/registry.rb
|
301
302
|
- lib/kamal/configuration/validator/role.rb
|
302
303
|
- lib/kamal/configuration/validator/servers.rb
|
303
304
|
- lib/kamal/configuration/volume.rb
|
304
305
|
- lib/kamal/env_file.rb
|
305
306
|
- lib/kamal/git.rb
|
307
|
+
- lib/kamal/secrets.rb
|
308
|
+
- lib/kamal/secrets/adapters.rb
|
309
|
+
- lib/kamal/secrets/adapters/base.rb
|
310
|
+
- lib/kamal/secrets/adapters/bitwarden.rb
|
311
|
+
- lib/kamal/secrets/adapters/last_pass.rb
|
312
|
+
- lib/kamal/secrets/adapters/one_password.rb
|
313
|
+
- lib/kamal/secrets/adapters/test.rb
|
314
|
+
- lib/kamal/secrets/dotenv/inline_command_substitution.rb
|
306
315
|
- lib/kamal/sshkit_with_ext.rb
|
307
316
|
- lib/kamal/tags.rb
|
308
317
|
- lib/kamal/utils.rb
|
@@ -327,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
327
336
|
- !ruby/object:Gem::Version
|
328
337
|
version: '0'
|
329
338
|
requirements: []
|
330
|
-
rubygems_version: 3.5.
|
339
|
+
rubygems_version: 3.5.16
|
331
340
|
signing_key:
|
332
341
|
specification_version: 4
|
333
342
|
summary: Deploy web apps in containers to servers running Docker with zero downtime.
|
data/lib/kamal/cli/env.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require "tempfile"
|
2
|
-
|
3
|
-
class Kamal::Cli::Env < Kamal::Cli::Base
|
4
|
-
desc "push", "Push the env file to the remote hosts"
|
5
|
-
def push
|
6
|
-
with_lock do
|
7
|
-
on(KAMAL.hosts) do
|
8
|
-
execute *KAMAL.auditor.record("Pushed env files"), verbosity: :debug
|
9
|
-
|
10
|
-
KAMAL.roles_on(host).each do |role|
|
11
|
-
execute *KAMAL.app(role: role, host: host).make_env_directory
|
12
|
-
upload! role.env(host).secrets_io, role.env(host).secrets_file, mode: 400
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
on(KAMAL.traefik_hosts) do
|
17
|
-
execute *KAMAL.traefik.make_env_directory
|
18
|
-
upload! KAMAL.traefik.env.secrets_io, KAMAL.traefik.env.secrets_file, mode: 400
|
19
|
-
end
|
20
|
-
|
21
|
-
on(KAMAL.accessory_hosts) do
|
22
|
-
KAMAL.accessories_on(host).each do |accessory|
|
23
|
-
accessory_config = KAMAL.config.accessory(accessory)
|
24
|
-
execute *KAMAL.accessory(accessory).make_env_directory
|
25
|
-
upload! accessory_config.env.secrets_io, accessory_config.env.secrets_file, mode: 400
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
desc "delete", "Delete the env file from the remote hosts"
|
32
|
-
def delete
|
33
|
-
with_lock do
|
34
|
-
on(KAMAL.hosts) do
|
35
|
-
execute *KAMAL.auditor.record("Deleted env files"), verbosity: :debug
|
36
|
-
|
37
|
-
KAMAL.roles_on(host).each do |role|
|
38
|
-
execute *KAMAL.app(role: role, host: host).remove_env_file
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
on(KAMAL.traefik_hosts) do
|
43
|
-
execute *KAMAL.traefik.remove_env_file
|
44
|
-
end
|
45
|
-
|
46
|
-
on(KAMAL.accessory_hosts) do
|
47
|
-
KAMAL.accessories_on(host).each do |accessory|
|
48
|
-
accessory_config = KAMAL.config.accessory(accessory)
|
49
|
-
execute *KAMAL.accessory(accessory).remove_env_file
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/lib/kamal/cli/traefik.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
class Kamal::Cli::Traefik < Kamal::Cli::Base
|
2
|
-
desc "boot", "Boot Traefik on servers"
|
3
|
-
def boot
|
4
|
-
with_lock do
|
5
|
-
on(KAMAL.traefik_hosts) do
|
6
|
-
execute *KAMAL.registry.login
|
7
|
-
execute *KAMAL.traefik.start_or_run
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
desc "reboot", "Reboot Traefik on servers (stop container, remove container, start new container)"
|
13
|
-
option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel"
|
14
|
-
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
15
|
-
def reboot
|
16
|
-
confirming "This will cause a brief outage on each host. Are you sure?" do
|
17
|
-
with_lock do
|
18
|
-
host_groups = options[:rolling] ? KAMAL.traefik_hosts : [ KAMAL.traefik_hosts ]
|
19
|
-
host_groups.each do |hosts|
|
20
|
-
host_list = Array(hosts).join(",")
|
21
|
-
run_hook "pre-traefik-reboot", hosts: host_list
|
22
|
-
on(hosts) do
|
23
|
-
execute *KAMAL.auditor.record("Rebooted traefik"), verbosity: :debug
|
24
|
-
execute *KAMAL.registry.login
|
25
|
-
execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
|
26
|
-
execute *KAMAL.traefik.remove_container
|
27
|
-
execute *KAMAL.traefik.run
|
28
|
-
end
|
29
|
-
run_hook "post-traefik-reboot", hosts: host_list
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
desc "start", "Start existing Traefik container on servers"
|
36
|
-
def start
|
37
|
-
with_lock do
|
38
|
-
on(KAMAL.traefik_hosts) do
|
39
|
-
execute *KAMAL.auditor.record("Started traefik"), verbosity: :debug
|
40
|
-
execute *KAMAL.traefik.start
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
desc "stop", "Stop existing Traefik container on servers"
|
46
|
-
def stop
|
47
|
-
with_lock do
|
48
|
-
on(KAMAL.traefik_hosts) do
|
49
|
-
execute *KAMAL.auditor.record("Stopped traefik"), verbosity: :debug
|
50
|
-
execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
desc "restart", "Restart existing Traefik container on servers"
|
56
|
-
def restart
|
57
|
-
with_lock do
|
58
|
-
stop
|
59
|
-
start
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
desc "details", "Show details about Traefik container from servers"
|
64
|
-
def details
|
65
|
-
on(KAMAL.traefik_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.traefik.info), type: "Traefik" }
|
66
|
-
end
|
67
|
-
|
68
|
-
desc "logs", "Show log lines from Traefik on servers"
|
69
|
-
option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)"
|
70
|
-
option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server"
|
71
|
-
option :grep, aliases: "-g", desc: "Show lines with grep match only (use this to fetch specific requests by id)"
|
72
|
-
option :grep_options, aliases: "-o", desc: "Additional options supplied to grep"
|
73
|
-
option :follow, aliases: "-f", desc: "Follow logs on primary server (or specific host set by --hosts)"
|
74
|
-
def logs
|
75
|
-
grep = options[:grep]
|
76
|
-
grep_options = options[:grep_options]
|
77
|
-
|
78
|
-
if options[:follow]
|
79
|
-
run_locally do
|
80
|
-
info "Following logs on #{KAMAL.primary_host}..."
|
81
|
-
info KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
|
82
|
-
exec KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
|
83
|
-
end
|
84
|
-
else
|
85
|
-
since = options[:since]
|
86
|
-
lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
|
87
|
-
|
88
|
-
on(KAMAL.traefik_hosts) do |host|
|
89
|
-
puts_by_host host, capture(*KAMAL.traefik.logs(since: since, lines: lines, grep: grep, grep_options: grep_options)), type: "Traefik"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
desc "remove", "Remove Traefik container and image from servers"
|
95
|
-
def remove
|
96
|
-
with_lock do
|
97
|
-
stop
|
98
|
-
remove_container
|
99
|
-
remove_image
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
desc "remove_container", "Remove Traefik container from servers", hide: true
|
104
|
-
def remove_container
|
105
|
-
with_lock do
|
106
|
-
on(KAMAL.traefik_hosts) do
|
107
|
-
execute *KAMAL.auditor.record("Removed traefik container"), verbosity: :debug
|
108
|
-
execute *KAMAL.traefik.remove_container
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
desc "remove_image", "Remove Traefik image from servers", hide: true
|
114
|
-
def remove_image
|
115
|
-
with_lock do
|
116
|
-
on(KAMAL.traefik_hosts) do
|
117
|
-
execute *KAMAL.auditor.record("Removed traefik image"), verbosity: :debug
|
118
|
-
execute *KAMAL.traefik.remove_image
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Kamal::Commands::App::Cord
|
2
|
-
def cord(version:)
|
3
|
-
pipe \
|
4
|
-
docker(:inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", container_name(version)),
|
5
|
-
[ :awk, "'$2 == \"#{role.cord_volume.container_path}\" {print $1}'" ]
|
6
|
-
end
|
7
|
-
|
8
|
-
def tie_cord(cord)
|
9
|
-
create_empty_file(cord)
|
10
|
-
end
|
11
|
-
|
12
|
-
def cut_cord(cord)
|
13
|
-
remove_directory(cord)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
def create_empty_file(file)
|
18
|
-
chain \
|
19
|
-
make_directory_for(file),
|
20
|
-
[ :touch, file ]
|
21
|
-
end
|
22
|
-
end
|