kamal 1.7.2 → 1.8.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/base.rb +27 -5
- data/lib/kamal/cli/build.rb +32 -5
- data/lib/kamal/cli/main.rb +4 -2
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +9 -3
- data/lib/kamal/commands/auditor.rb +1 -1
- data/lib/kamal/commands/builder/base.rb +4 -0
- data/lib/kamal/commands/builder.rb +1 -1
- data/lib/kamal/configuration/docs/ssh.yml +20 -0
- data/lib/kamal/configuration/ssh.rb +13 -1
- data/lib/kamal/configuration/validator.rb +2 -2
- data/lib/kamal/git.rb +4 -0
- data/lib/kamal/tags.rb +3 -2
- data/lib/kamal/version.rb +1 -1
- metadata +4 -25
- data/lib/kamal/configuration/validator/alias.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cf788692b64036e48979bd965c6cc205442f308173c921f1b7e7f3d53e9f279
|
4
|
+
data.tar.gz: c81142cad28e8fdfab7ae68259569f1754791952993c323cbc46760252a8b42c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b461f6c47a6b77d3cd35aff8198dc85e8db8b840a14ffd492127042d5acb3cd2603578f59eba9629726dfd918cddceed978b7554b00045a5fe64a0ec656b6d44
|
7
|
+
data.tar.gz: 1d446485c62f5285c82d92a49f3b8b821fefd7695ac651bc5e8531a16e8c1739bd4c20e4ff4012a4a42b8c73f0d681cfd64a9f6b90da791ab27df97679ae2d0b
|
data/lib/kamal/cli/base.rb
CHANGED
@@ -25,12 +25,17 @@ module Kamal::Cli
|
|
25
25
|
def initialize(*)
|
26
26
|
super
|
27
27
|
@original_env = ENV.to_h.dup
|
28
|
-
|
28
|
+
load_env
|
29
29
|
initialize_commander(options_with_subcommand_class_options)
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
33
|
-
def
|
33
|
+
def reload_env
|
34
|
+
reset_env
|
35
|
+
load_env
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_env
|
34
39
|
if destination = options[:destination]
|
35
40
|
Dotenv.load(".env.#{destination}", ".env")
|
36
41
|
else
|
@@ -38,10 +43,27 @@ module Kamal::Cli
|
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
41
|
-
def
|
46
|
+
def reset_env
|
47
|
+
replace_env @original_env
|
48
|
+
end
|
49
|
+
|
50
|
+
def replace_env(env)
|
42
51
|
ENV.clear
|
43
|
-
ENV.update(
|
44
|
-
|
52
|
+
ENV.update(env)
|
53
|
+
end
|
54
|
+
|
55
|
+
def with_original_env
|
56
|
+
keeping_current_env do
|
57
|
+
reset_env
|
58
|
+
yield
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def keeping_current_env
|
63
|
+
current_env = ENV.to_h.dup
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
replace_env(current_env)
|
45
67
|
end
|
46
68
|
|
47
69
|
def options_with_subcommand_class_options
|
data/lib/kamal/cli/build.rb
CHANGED
@@ -59,11 +59,14 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
59
59
|
|
60
60
|
desc "pull", "Pull app image from registry onto servers"
|
61
61
|
def pull
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
if (first_hosts = mirror_hosts).any?
|
63
|
+
# Pull on a single host per mirror first to seed them
|
64
|
+
say "Pulling image on #{first_hosts.join(", ")} to seed the #{"mirror".pluralize(first_hosts.count)}...", :magenta
|
65
|
+
pull_on_hosts(first_hosts)
|
66
|
+
say "Pulling image on remaining hosts...", :magenta
|
67
|
+
pull_on_hosts(KAMAL.hosts - first_hosts)
|
68
|
+
else
|
69
|
+
pull_on_hosts(KAMAL.hosts)
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
@@ -131,4 +134,28 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
131
134
|
end
|
132
135
|
end
|
133
136
|
end
|
137
|
+
|
138
|
+
def mirror_hosts
|
139
|
+
if KAMAL.hosts.many?
|
140
|
+
mirror_hosts = Concurrent::Hash.new
|
141
|
+
on(KAMAL.hosts) do |host|
|
142
|
+
first_mirror = capture_with_info(*KAMAL.builder.first_mirror).strip.presence
|
143
|
+
mirror_hosts[first_mirror] ||= host if first_mirror
|
144
|
+
rescue SSHKit::Command::Failed => e
|
145
|
+
raise unless e.message =~ /error calling index: reflect: slice index out of range/
|
146
|
+
end
|
147
|
+
mirror_hosts.values
|
148
|
+
else
|
149
|
+
[]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def pull_on_hosts(hosts)
|
154
|
+
on(hosts) do
|
155
|
+
execute *KAMAL.auditor.record("Pulled image with version #{KAMAL.config.version}"), verbosity: :debug
|
156
|
+
execute *KAMAL.builder.clean, raise_on_non_zero_exit: false
|
157
|
+
execute *KAMAL.builder.pull
|
158
|
+
execute *KAMAL.builder.validate_image
|
159
|
+
end
|
160
|
+
end
|
134
161
|
end
|
data/lib/kamal/cli/main.rb
CHANGED
@@ -191,10 +191,12 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
191
191
|
end
|
192
192
|
|
193
193
|
if Pathname.new(File.expand_path(env_template_path)).exist?
|
194
|
-
|
194
|
+
# Ensure existing env doesn't pollute template evaluation
|
195
|
+
content = with_original_env { ERB.new(File.read(env_template_path), trim_mode: "-").result }
|
196
|
+
File.write(env_path, content, perm: 0600)
|
195
197
|
|
196
198
|
unless options[:skip_push]
|
197
|
-
|
199
|
+
reload_env
|
198
200
|
invoke "kamal:cli:env:push", options
|
199
201
|
end
|
200
202
|
else
|
@@ -1,7 +1,13 @@
|
|
1
|
-
#!/bin/
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# A sample docker-setup hook
|
4
4
|
#
|
5
|
-
# Sets up a Docker network which can then be used by the application’s containers
|
5
|
+
# Sets up a Docker network on defined hosts which can then be used by the application’s containers
|
6
6
|
|
7
|
-
|
7
|
+
hosts = ENV["KAMAL_HOSTS"].split(",")
|
8
|
+
|
9
|
+
hosts.each do |ip|
|
10
|
+
destination = "root@#{ip}"
|
11
|
+
puts "Creating a Docker network \"kamal\" on #{destination}"
|
12
|
+
`ssh #{destination} docker network create kamal`
|
13
|
+
end
|
@@ -9,7 +9,7 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
|
|
9
9
|
# Runs remotely
|
10
10
|
def record(line, **details)
|
11
11
|
append \
|
12
|
-
[ :echo, audit_tags(**details).except(:version, :service_version).to_s, line ],
|
12
|
+
[ :echo, audit_tags(**details).except(:version, :service_version, :service).to_s, line ],
|
13
13
|
audit_log_file
|
14
14
|
end
|
15
15
|
|
@@ -40,6 +40,10 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
40
40
|
[]
|
41
41
|
end
|
42
42
|
|
43
|
+
def first_mirror
|
44
|
+
docker(:info, "--format '{{index .RegistryConfig.Mirrors 0}}'")
|
45
|
+
end
|
46
|
+
|
43
47
|
private
|
44
48
|
def build_tags
|
45
49
|
[ "-t", config.absolute_image, "-t", config.latest_image ]
|
@@ -2,7 +2,7 @@ require "active_support/core_ext/string/filters"
|
|
2
2
|
|
3
3
|
class Kamal::Commands::Builder < Kamal::Commands::Base
|
4
4
|
delegate :create, :remove, :push, :clean, :pull, :info, :context_hosts, :config_context_hosts, :validate_image,
|
5
|
-
|
5
|
+
:first_mirror, to: :target
|
6
6
|
|
7
7
|
include Clone
|
8
8
|
|
@@ -44,3 +44,23 @@ ssh:
|
|
44
44
|
# Defaults to `fatal`. Set this to debug if you are having
|
45
45
|
# SSH connection issues.
|
46
46
|
log_level: debug
|
47
|
+
|
48
|
+
# Keys Only
|
49
|
+
#
|
50
|
+
# Set to true to use only private keys from keys and key_data parameters,
|
51
|
+
# even if ssh-agent offers more identities. This option is intended for
|
52
|
+
# situations where ssh-agent offers many different identites or you have
|
53
|
+
# a need to overwrite all identites and force a single one.
|
54
|
+
keys_only: false
|
55
|
+
|
56
|
+
# Keys
|
57
|
+
#
|
58
|
+
# An array of file names of private keys to use for publickey
|
59
|
+
# and hostbased authentication
|
60
|
+
keys: [ "~/.ssh/id.pem" ]
|
61
|
+
|
62
|
+
# Key Data
|
63
|
+
#
|
64
|
+
# An array of strings, with each element of the array being
|
65
|
+
# a raw private key in PEM format.
|
66
|
+
key_data: [ "-----BEGIN OPENSSH PRIVATE KEY-----" ]
|
@@ -26,8 +26,20 @@ class Kamal::Configuration::Ssh
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def keys_only
|
30
|
+
ssh_config["keys_only"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def keys
|
34
|
+
ssh_config["keys"]
|
35
|
+
end
|
36
|
+
|
37
|
+
def key_data
|
38
|
+
ssh_config["key_data"]
|
39
|
+
end
|
40
|
+
|
29
41
|
def options
|
30
|
-
{ user: user, port: port, proxy: proxy, logger: logger, keepalive: true, keepalive_interval: 30 }.compact
|
42
|
+
{ user: user, port: port, proxy: proxy, logger: logger, keepalive: true, keepalive_interval: 30, keys_only: keys_only, keys: keys, key_data: key_data }.compact
|
31
43
|
end
|
32
44
|
|
33
45
|
def to_h
|
@@ -31,9 +31,9 @@ class Kamal::Configuration::Validator
|
|
31
31
|
validate_array_of! value, example_value.first.class
|
32
32
|
elsif example_value.is_a?(Hash)
|
33
33
|
case key.to_s
|
34
|
-
when "options"
|
34
|
+
when "options", "args"
|
35
35
|
validate_type! value, Hash
|
36
|
-
when "
|
36
|
+
when "labels"
|
37
37
|
validate_hash_of! value, example_value.first[1].class
|
38
38
|
else
|
39
39
|
validate_against_example! value, example_value
|
data/lib/kamal/git.rb
CHANGED
data/lib/kamal/tags.rb
CHANGED
@@ -10,10 +10,11 @@ class Kamal::Tags
|
|
10
10
|
|
11
11
|
def default_tags(config)
|
12
12
|
{ recorded_at: Time.now.utc.iso8601,
|
13
|
-
performer: `whoami`.chomp,
|
13
|
+
performer: Kamal::Git.email.presence || `whoami`.chomp,
|
14
14
|
destination: config.destination,
|
15
15
|
version: config.version,
|
16
|
-
service_version: service_version(config)
|
16
|
+
service_version: service_version(config),
|
17
|
+
service: config.service }
|
17
18
|
end
|
18
19
|
|
19
20
|
def service_version(config)
|
data/lib/kamal/version.rb
CHANGED
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: 1.
|
4
|
+
version: 1.8.0
|
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-
|
11
|
+
date: 2024-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.23.0
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: '2.0'
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 1.
|
43
|
+
version: 1.23.0
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '2.0'
|
@@ -114,26 +114,6 @@ dependencies:
|
|
114
114
|
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '1.2'
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
name: x25519
|
119
|
-
requirement: !ruby/object:Gem::Requirement
|
120
|
-
requirements:
|
121
|
-
- - "~>"
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: '1.0'
|
124
|
-
- - ">="
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
version: 1.0.10
|
127
|
-
type: :runtime
|
128
|
-
prerelease: false
|
129
|
-
version_requirements: !ruby/object:Gem::Requirement
|
130
|
-
requirements:
|
131
|
-
- - "~>"
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: '1.0'
|
134
|
-
- - ">="
|
135
|
-
- !ruby/object:Gem::Version
|
136
|
-
version: 1.0.10
|
137
117
|
- !ruby/object:Gem::Dependency
|
138
118
|
name: bcrypt_pbkdf
|
139
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -314,7 +294,6 @@ files:
|
|
314
294
|
- lib/kamal/configuration/validation.rb
|
315
295
|
- lib/kamal/configuration/validator.rb
|
316
296
|
- lib/kamal/configuration/validator/accessory.rb
|
317
|
-
- lib/kamal/configuration/validator/alias.rb
|
318
297
|
- lib/kamal/configuration/validator/builder.rb
|
319
298
|
- lib/kamal/configuration/validator/env.rb
|
320
299
|
- lib/kamal/configuration/validator/registry.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class Kamal::Configuration::Validator::Alias < Kamal::Configuration::Validator
|
2
|
-
def validate!
|
3
|
-
super
|
4
|
-
|
5
|
-
name = context.delete_prefix("aliases/")
|
6
|
-
|
7
|
-
if name !~ /\A[a-z0-9_-]+\z/
|
8
|
-
error "Invalid alias name: '#{name}'. Must only contain lowercase letters, alphanumeric, hyphens and underscores."
|
9
|
-
end
|
10
|
-
|
11
|
-
if Kamal::Cli::Main.original_commands.include?(name)
|
12
|
-
error "Alias '#{name}' conflicts with a built-in command."
|
13
|
-
end
|
14
|
-
|
15
|
-
if config["command"].empty?
|
16
|
-
error "Alias '#{name}': command is required."
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|