Split env into separate secrets/clear envs
Split each env file in two on the deploy hosts, one for secrets and one for clear values. This will allow us to update them independently.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
require "tempfile"
|
||||
|
||||
class Kamal::Cli::Env < Kamal::Cli::Base
|
||||
desc "push", "Push the env file to the remote hosts"
|
||||
desc "push", "Push the env files to the remote hosts"
|
||||
def push
|
||||
mutating do
|
||||
on(KAMAL.hosts) do
|
||||
@@ -10,26 +10,29 @@ class Kamal::Cli::Env < Kamal::Cli::Base
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
role_config = KAMAL.config.role(role)
|
||||
execute *KAMAL.app(role: role).make_env_directory
|
||||
upload! StringIO.new(role_config.env_file), role_config.host_env_file_path, mode: 400
|
||||
upload! StringIO.new(role_config.env_file.secret), role_config.host_secret_env_file_path, mode: 400
|
||||
upload! StringIO.new(role_config.env_file.clear), role_config.host_clear_env_file_path, mode: 400
|
||||
end
|
||||
end
|
||||
|
||||
on(KAMAL.traefik_hosts) do
|
||||
execute *KAMAL.traefik.make_env_directory
|
||||
upload! StringIO.new(KAMAL.traefik.env_file), KAMAL.traefik.host_env_file_path, mode: 400
|
||||
upload! StringIO.new(KAMAL.traefik.env_file.secret), KAMAL.traefik.host_secret_env_file_path, mode: 400
|
||||
upload! StringIO.new(KAMAL.traefik.env_file.clear), KAMAL.traefik.host_clear_env_file_path, mode: 400
|
||||
end
|
||||
|
||||
on(KAMAL.accessory_hosts) do
|
||||
KAMAL.accessories_on(host).each do |accessory|
|
||||
accessory_config = KAMAL.config.accessory(accessory)
|
||||
execute *KAMAL.accessory(accessory).make_env_directory
|
||||
upload! StringIO.new(accessory_config.env_file), accessory_config.host_env_file_path, mode: 400
|
||||
upload! StringIO.new(accessory_config.env_file.secret), accessory_config.host_secret_env_file_path, mode: 400
|
||||
upload! StringIO.new(accessory_config.env_file.clear), accessory_config.host_clear_env_file_path, mode: 400
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "delete", "Delete the env file from the remote hosts"
|
||||
desc "delete", "Delete the env files from the remote hosts"
|
||||
def delete
|
||||
mutating do
|
||||
on(KAMAL.hosts) do
|
||||
@@ -37,18 +40,18 @@ class Kamal::Cli::Env < Kamal::Cli::Base
|
||||
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
role_config = KAMAL.config.role(role)
|
||||
execute *KAMAL.app(role: role).remove_env_file
|
||||
execute *KAMAL.app(role: role).remove_env_files
|
||||
end
|
||||
end
|
||||
|
||||
on(KAMAL.traefik_hosts) do
|
||||
execute *KAMAL.traefik.remove_env_file
|
||||
execute *KAMAL.traefik.remove_env_files
|
||||
end
|
||||
|
||||
on(KAMAL.accessory_hosts) do
|
||||
KAMAL.accessories_on(host).each do |accessory|
|
||||
accessory_config = KAMAL.config.accessory(accessory)
|
||||
execute *KAMAL.accessory(accessory).remove_env_file
|
||||
execute *KAMAL.accessory(accessory).remove_env_files
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,8 +102,8 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
||||
make_directory accessory_config.host_env_directory
|
||||
end
|
||||
|
||||
def remove_env_file
|
||||
[:rm, "-f", accessory_config.host_env_file_path]
|
||||
def remove_env_files
|
||||
[:rm, "-f", File.join(accessory_config.host_env_directory, "#{accessory_config.service_name}*.env")]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -72,8 +72,8 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
make_directory role_config.host_env_directory
|
||||
end
|
||||
|
||||
def remove_env_file
|
||||
[ :rm, "-f", role_config.host_env_file_path ]
|
||||
def remove_env_files
|
||||
[ :rm, "-f", File.join(role_config.host_env_directory, "#{role_config.container_prefix}*.env") ]
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -72,19 +72,23 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
||||
end
|
||||
|
||||
def env_file
|
||||
Kamal::EnvFile.new(config.traefik.fetch("env", {}))
|
||||
Kamal::EnvFiles.new(config.traefik.fetch("env", {}))
|
||||
end
|
||||
|
||||
def host_env_file_path
|
||||
File.join host_env_directory, "traefik.env"
|
||||
def host_clear_env_file_path
|
||||
File.join host_env_directory, "traefik-clear.env"
|
||||
end
|
||||
|
||||
def host_secret_env_file_path
|
||||
File.join host_env_directory, "traefik-secret.env"
|
||||
end
|
||||
|
||||
def make_env_directory
|
||||
make_directory(host_env_directory)
|
||||
end
|
||||
|
||||
def remove_env_file
|
||||
[:rm, "-f", host_env_file_path]
|
||||
def remove_env_files
|
||||
[:rm, "-f", File.join(host_env_directory, "traefik*.env")]
|
||||
end
|
||||
|
||||
private
|
||||
@@ -97,7 +101,10 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
||||
end
|
||||
|
||||
def env_args
|
||||
argumentize "--env-file", host_env_file_path
|
||||
[
|
||||
*argumentize("--env-file", host_secret_env_file_path),
|
||||
*argumentize("--env-file", host_clear_env_file_path)
|
||||
]
|
||||
end
|
||||
|
||||
def host_env_directory
|
||||
|
||||
@@ -46,19 +46,26 @@ class Kamal::Configuration::Accessory
|
||||
end
|
||||
|
||||
def env_file
|
||||
Kamal::EnvFile.new(env)
|
||||
Kamal::EnvFiles.new(env)
|
||||
end
|
||||
|
||||
def host_env_directory
|
||||
File.join config.host_env_directory, "accessories"
|
||||
end
|
||||
|
||||
def host_env_file_path
|
||||
File.join host_env_directory, "#{service_name}.env"
|
||||
def host_clear_env_file_path
|
||||
File.join host_env_directory, "#{service_name}-clear.env"
|
||||
end
|
||||
|
||||
def host_secret_env_file_path
|
||||
File.join host_env_directory, "#{service_name}-secret.env"
|
||||
end
|
||||
|
||||
def env_args
|
||||
argumentize "--env-file", host_env_file_path
|
||||
[
|
||||
*argumentize("--env-file", host_secret_env_file_path),
|
||||
*argumentize("--env-file", host_clear_env_file_path)
|
||||
]
|
||||
end
|
||||
|
||||
def files
|
||||
|
||||
@@ -46,19 +46,26 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
|
||||
def env_file
|
||||
Kamal::EnvFile.new(env)
|
||||
Kamal::EnvFiles.new(env)
|
||||
end
|
||||
|
||||
def host_env_directory
|
||||
File.join config.host_env_directory, "roles"
|
||||
end
|
||||
|
||||
def host_env_file_path
|
||||
File.join host_env_directory, "#{[config.service, name, config.destination].compact.join("-")}.env"
|
||||
def host_clear_env_file_path
|
||||
host_env_file_path(:clear)
|
||||
end
|
||||
|
||||
def host_secret_env_file_path
|
||||
host_env_file_path(:secret)
|
||||
end
|
||||
|
||||
def env_args
|
||||
argumentize "--env-file", host_env_file_path
|
||||
[
|
||||
*argumentize("--env-file", host_secret_env_file_path),
|
||||
*argumentize("--env-file", host_clear_env_file_path)
|
||||
]
|
||||
end
|
||||
|
||||
def asset_volume_args
|
||||
@@ -243,6 +250,10 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
end
|
||||
|
||||
def host_env_file_path(env_type)
|
||||
File.join host_env_directory, "#{[container_prefix, env_type].compact.join("-")}.env"
|
||||
end
|
||||
|
||||
def http_health_check(port:, path:)
|
||||
"curl -f #{URI.join("http://localhost:#{port}", path)} || exit 1" if path.present? || port.present?
|
||||
end
|
||||
|
||||
@@ -1,32 +1,25 @@
|
||||
# Encode an env hash as a string where secret values have been looked up and all values escaped for Docker.
|
||||
class Kamal::EnvFile
|
||||
class Kamal::EnvFiles
|
||||
def initialize(env)
|
||||
@env = env
|
||||
end
|
||||
|
||||
def to_s
|
||||
env_file = StringIO.new.tap do |contents|
|
||||
if (secrets = @env["secret"]).present?
|
||||
@env.fetch("secret", @env)&.each do |key|
|
||||
contents << docker_env_file_line(key, ENV.fetch(key))
|
||||
end
|
||||
|
||||
@env["clear"]&.each do |key, value|
|
||||
contents << docker_env_file_line(key, value)
|
||||
end
|
||||
else
|
||||
@env.fetch("clear", @env)&.each do |key, value|
|
||||
contents << docker_env_file_line(key, value)
|
||||
end
|
||||
end
|
||||
end.string
|
||||
|
||||
# Ensure the file has some contents to avoid the SSHKIT empty file warning
|
||||
env_file.presence || "\n"
|
||||
def secret
|
||||
env_file do
|
||||
@env["secret"]&.to_h { |key| [ key, ENV.fetch(key) ] }
|
||||
end
|
||||
end
|
||||
|
||||
def clear
|
||||
env_file do
|
||||
if (secrets = @env["secret"]).present?
|
||||
@env["clear"]
|
||||
else
|
||||
@env.fetch("clear", @env)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias to_str to_s
|
||||
|
||||
private
|
||||
def docker_env_file_line(key, value)
|
||||
"#{key.to_s}=#{escape_docker_env_file_value(value)}\n"
|
||||
@@ -38,4 +31,14 @@ class Kamal::EnvFile
|
||||
# so remove leading and trailing ones and unescape any others
|
||||
value.to_s.dump[1..-2].gsub(/\\"/, "\"")
|
||||
end
|
||||
|
||||
def env_file(&block)
|
||||
StringIO.new.tap do |contents|
|
||||
block.call&.each do |key, value|
|
||||
contents << docker_env_file_line(key, value)
|
||||
end
|
||||
# Ensure the file has some contents to avoid the SSHKit empty file warning
|
||||
contents << "\n" if contents.length == 0
|
||||
end.string
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user