Host specific env with tags
Allow hosts to be tagged so we can have host specific env variables.
We might want host specific env variables for things like datacenter
specific tags or testing GC settings on a specific host.
Right now you either need to set up a separate role, or have the app
be host aware.
Now you can define tag env variables and assign those to hosts.
For example:
```
servers:
- 1.1.1.1
- 1.1.1.2: tag1
- 1.1.1.2: tag2
- 1.1.1.3: [ tag1, tag2 ]
env_tags:
tag1:
ENV1: value1
tag2:
ENV2: value2
```
The tag env supports the full env format, allowing you to set secret and
clear values.
This commit is contained in:
@@ -37,7 +37,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug
|
||||
execute *KAMAL.app(role: role).start, raise_on_non_zero_exit: false
|
||||
execute *KAMAL.app(role: role, host: host).start, raise_on_non_zero_exit: false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -51,7 +51,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug
|
||||
execute *KAMAL.app(role: role).stop, raise_on_non_zero_exit: false
|
||||
execute *KAMAL.app(role: role, host: host).stop, raise_on_non_zero_exit: false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -64,7 +64,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
roles = KAMAL.roles_on(host)
|
||||
|
||||
roles.each do |role|
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role).info)
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).info)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -80,7 +80,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
say "Get current version of running container...", :magenta unless options[:version]
|
||||
using_version(options[:version] || current_running_version) do |version|
|
||||
say "Launching interactive command with version #{version} via SSH from existing container on #{KAMAL.primary_host}...", :magenta
|
||||
run_locally { exec KAMAL.app(role: KAMAL.primary_role).execute_in_existing_container_over_ssh(cmd, host: KAMAL.primary_host, env: env) }
|
||||
run_locally { exec KAMAL.app(role: KAMAL.primary_role, host: KAMAL.primary_host).execute_in_existing_container_over_ssh(cmd, env: env) }
|
||||
end
|
||||
|
||||
when options[:interactive]
|
||||
@@ -88,7 +88,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
using_version(version_or_latest) do |version|
|
||||
say "Launching interactive command with version #{version} via SSH from new container on #{KAMAL.primary_host}...", :magenta
|
||||
run_locally do
|
||||
exec KAMAL.app(role: KAMAL.primary_role).execute_in_new_container_over_ssh(cmd, host: KAMAL.primary_host, env: env)
|
||||
exec KAMAL.app(role: KAMAL.primary_role, host: KAMAL.primary_host).execute_in_new_container_over_ssh(cmd, env: env)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,7 +102,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}", role: role), verbosity: :debug
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role).execute_in_existing_container(cmd, env: env))
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_existing_container(cmd, env: env))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -116,7 +116,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role).execute_in_new_container(cmd, env: env))
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).execute_in_new_container(cmd, env: env))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -140,13 +140,14 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
roles = KAMAL.roles_on(host)
|
||||
|
||||
roles.each do |role|
|
||||
versions = capture_with_info(*KAMAL.app(role: role).list_versions, raise_on_non_zero_exit: false).split("\n")
|
||||
versions -= [ capture_with_info(*KAMAL.app(role: role).current_running_version, raise_on_non_zero_exit: false).strip ]
|
||||
app = KAMAL.app(role: role, host: host)
|
||||
versions = capture_with_info(*app.list_versions, raise_on_non_zero_exit: false).split("\n")
|
||||
versions -= [ capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip ]
|
||||
|
||||
versions.each do |version|
|
||||
if stop
|
||||
puts_by_host host, "Stopping stale container for role #{role} with version #{version}"
|
||||
execute *KAMAL.app(role: role).stop(version: version), raise_on_non_zero_exit: false
|
||||
execute *app.stop(version: version), raise_on_non_zero_exit: false
|
||||
else
|
||||
puts_by_host host, "Detected stale container for role #{role} with version #{version} (use `kamal app stale_containers --stop` to stop)"
|
||||
end
|
||||
@@ -180,8 +181,9 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
KAMAL.specific_roles ||= [ "web" ]
|
||||
role = KAMAL.roles_on(KAMAL.primary_host).first
|
||||
|
||||
info KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
||||
exec KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
||||
app = KAMAL.app(role: role, host: host)
|
||||
info app.follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
||||
exec app.follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
||||
end
|
||||
else
|
||||
lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
|
||||
@@ -191,7 +193,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
begin
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role).logs(since: since, lines: lines, grep: grep))
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).logs(since: since, lines: lines, grep: grep))
|
||||
rescue SSHKit::Command::Failed
|
||||
puts_by_host host, "Nothing found"
|
||||
end
|
||||
@@ -217,7 +219,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Removed app container with version #{version}", role: role), verbosity: :debug
|
||||
execute *KAMAL.app(role: role).remove_container(version: version)
|
||||
execute *KAMAL.app(role: role, host: host).remove_container(version: version)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -231,7 +233,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
|
||||
roles.each do |role|
|
||||
execute *KAMAL.auditor.record("Removed all app containers", role: role), verbosity: :debug
|
||||
execute *KAMAL.app(role: role).remove_containers
|
||||
execute *KAMAL.app(role: role, host: host).remove_containers
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -251,7 +253,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
def version
|
||||
on(KAMAL.hosts) do |host|
|
||||
role = KAMAL.roles_on(host).first
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role).current_running_version).strip
|
||||
puts_by_host host, capture_with_info(*KAMAL.app(role: role, host: host).current_running_version).strip
|
||||
end
|
||||
end
|
||||
|
||||
@@ -274,7 +276,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
version = nil
|
||||
on(host) do
|
||||
role = KAMAL.roles_on(host).first
|
||||
version = capture_with_info(*KAMAL.app(role: role).current_running_version).strip
|
||||
version = capture_with_info(*KAMAL.app(role: role, host: host).current_running_version).strip
|
||||
end
|
||||
version.presence
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ class Kamal::Cli::App::Boot
|
||||
|
||||
private
|
||||
def app
|
||||
@app ||= KAMAL.app(role: role)
|
||||
@app ||= KAMAL.app(role: role, host: host)
|
||||
end
|
||||
|
||||
def auditor
|
||||
|
||||
@@ -19,6 +19,6 @@ class Kamal::Cli::App::PrepareAssets
|
||||
|
||||
private
|
||||
def app
|
||||
@app ||= KAMAL.app(role: role)
|
||||
@app ||= KAMAL.app(role: role, host: host)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,8 +8,8 @@ class Kamal::Cli::Env < Kamal::Cli::Base
|
||||
execute *KAMAL.auditor.record("Pushed env files"), verbosity: :debug
|
||||
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
execute *KAMAL.app(role: role).make_env_directory
|
||||
upload! role.env.secrets_io, role.env.secrets_file, mode: 400
|
||||
execute *KAMAL.app(role: role, host: host).make_env_directory
|
||||
upload! role.env(host).secrets_io, role.env(host).secrets_file, mode: 400
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ class Kamal::Cli::Env < Kamal::Cli::Base
|
||||
execute *KAMAL.auditor.record("Deleted env files"), verbosity: :debug
|
||||
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
execute *KAMAL.app(role: role).remove_env_file
|
||||
execute *KAMAL.app(role: role, host: host).remove_env_file
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
||||
begin
|
||||
on(KAMAL.hosts) do
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
container_id = capture_with_info(*KAMAL.app(role: role).container_id_for_version(version))
|
||||
container_id = capture_with_info(*KAMAL.app(role: role, host: host).container_id_for_version(version))
|
||||
raise "Container not found" unless container_id.present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,8 +65,8 @@ class Kamal::Commander
|
||||
end
|
||||
|
||||
|
||||
def app(role: nil)
|
||||
Kamal::Commands::App.new(config, role: role)
|
||||
def app(role: nil, host: nil)
|
||||
Kamal::Commands::App.new(config, role: role, host: host)
|
||||
end
|
||||
|
||||
def accessory(name)
|
||||
|
||||
@@ -3,11 +3,12 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
|
||||
ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
|
||||
|
||||
attr_reader :role, :role
|
||||
attr_reader :role, :host
|
||||
|
||||
def initialize(config, role: nil)
|
||||
def initialize(config, role: nil, host: nil)
|
||||
super(config)
|
||||
@role = role
|
||||
@host = host
|
||||
end
|
||||
|
||||
def run(hostname: nil)
|
||||
@@ -18,7 +19,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
*([ "--hostname", hostname ] if hostname),
|
||||
"-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
||||
"-e", "KAMAL_VERSION=\"#{config.version}\"",
|
||||
*role.env_args,
|
||||
*role.env_args(host),
|
||||
*role.health_check_args,
|
||||
*role.logging_args,
|
||||
*config.volume_args,
|
||||
@@ -70,11 +71,11 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
|
||||
|
||||
def make_env_directory
|
||||
make_directory role.env.secrets_directory
|
||||
make_directory role.env(host).secrets_directory
|
||||
end
|
||||
|
||||
def remove_env_file
|
||||
[ :rm, "-f", role.env.secrets_file ]
|
||||
[ :rm, "-f", role.env(host).secrets_file ]
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ module Kamal::Commands::App::Execution
|
||||
docker :run,
|
||||
("-it" if interactive),
|
||||
"--rm",
|
||||
*role&.env_args,
|
||||
*role&.env_args(host),
|
||||
*argumentize("--env", env),
|
||||
*config.volume_args,
|
||||
*role&.option_args,
|
||||
@@ -19,11 +19,11 @@ module Kamal::Commands::App::Execution
|
||||
*command
|
||||
end
|
||||
|
||||
def execute_in_existing_container_over_ssh(*command, host:, env:)
|
||||
def execute_in_existing_container_over_ssh(*command, env:)
|
||||
run_over_ssh execute_in_existing_container(*command, interactive: true, env: env), host: host
|
||||
end
|
||||
|
||||
def execute_in_new_container_over_ssh(*command, host:, env:)
|
||||
def execute_in_new_container_over_ssh(*command, env:)
|
||||
run_over_ssh execute_in_new_container(*command, interactive: true, env: env), host: host
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Kamal::Commands::Healthcheck < Kamal::Commands::Base
|
||||
"--publish", "#{exposed_port}:#{config.healthcheck["port"]}",
|
||||
"--label", "service=#{config.healthcheck_service}",
|
||||
"-e", "KAMAL_CONTAINER_NAME=\"#{config.healthcheck_service}\"",
|
||||
*primary.env_args,
|
||||
*primary.env_args(config.primary_host),
|
||||
*primary.health_check_args(cord: false),
|
||||
*config.volume_args,
|
||||
*primary.option_args,
|
||||
|
||||
@@ -233,6 +233,14 @@ class Kamal::Configuration
|
||||
raw_config.env || {}
|
||||
end
|
||||
|
||||
def env_tags
|
||||
raw_config.env_tags.collect { |name, config| Kamal::Configuration::Env::Tag.new(name, config: config) }
|
||||
end
|
||||
|
||||
def env_tag(name)
|
||||
env_tags.detect { |t| t.name == name.to_s }
|
||||
end
|
||||
|
||||
|
||||
def valid?
|
||||
ensure_destination_if_required && ensure_required_keys_present && ensure_valid_kamal_version && ensure_retain_containers_valid && ensure_valid_service_name
|
||||
|
||||
12
lib/kamal/configuration/env/tag.rb
vendored
Normal file
12
lib/kamal/configuration/env/tag.rb
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
class Kamal::Configuration::Env::Tag
|
||||
attr_reader :name, :config
|
||||
|
||||
def initialize(name, config:)
|
||||
@name = name
|
||||
@config = config
|
||||
end
|
||||
|
||||
def env
|
||||
Kamal::Configuration::Env.from_config(config: config)
|
||||
end
|
||||
end
|
||||
@@ -7,6 +7,7 @@ class Kamal::Configuration::Role
|
||||
|
||||
def initialize(name, config:)
|
||||
@name, @config = name.inquiry, config
|
||||
@tagged_hosts ||= extract_tagged_hosts_from_config
|
||||
end
|
||||
|
||||
def primary_host
|
||||
@@ -14,7 +15,11 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
|
||||
def hosts
|
||||
@hosts ||= extract_hosts_from_config
|
||||
tagged_hosts.keys
|
||||
end
|
||||
|
||||
def env_tags(host)
|
||||
tagged_hosts.fetch(host).collect { |tag| config.env_tag(tag) }
|
||||
end
|
||||
|
||||
def cmd
|
||||
@@ -50,12 +55,13 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
|
||||
|
||||
def env
|
||||
@env ||= base_env.merge(specialized_env)
|
||||
def env(host)
|
||||
@envs ||= {}
|
||||
@envs[host] ||= [ base_env, specialized_env, *env_tags(host).map(&:env) ].reduce(:merge)
|
||||
end
|
||||
|
||||
def env_args
|
||||
env.args
|
||||
def env_args(host)
|
||||
env(host).args
|
||||
end
|
||||
|
||||
def asset_volume_args
|
||||
@@ -164,7 +170,24 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
|
||||
private
|
||||
attr_accessor :config
|
||||
attr_accessor :config, :tagged_hosts
|
||||
|
||||
def extract_tagged_hosts_from_config
|
||||
{}.tap do |tagged_hosts|
|
||||
extract_hosts_from_config.map do |host_config|
|
||||
if host_config.is_a?(Hash)
|
||||
raise ArgumentError, "Multiple hosts found: #{host_config.inspect}" unless host_config.size == 1
|
||||
|
||||
host, tags = host_config.first
|
||||
tagged_hosts[host] = Array(tags)
|
||||
elsif host_config.is_a?(String) || host_config.is_a?(Symbol)
|
||||
tagged_hosts[host_config] = []
|
||||
else
|
||||
raise ArgumentError, "Invalid host config: #{host_config.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_hosts_from_config
|
||||
if config.servers.is_a?(Array)
|
||||
|
||||
Reference in New Issue
Block a user