Merge pull request #928 from basecamp/kamal-secrets-inline-aware
Make the secrets commands inline aware
This commit is contained in:
@@ -3,26 +3,26 @@ class Kamal::Cli::Secrets < Kamal::Cli::Base
|
||||
option :adapter, type: :string, aliases: "-a", required: true, desc: "Which vault adapter to use"
|
||||
option :account, type: :string, required: true, desc: "The account identifier or username"
|
||||
option :from, type: :string, required: false, desc: "A vault or folder to fetch the secrets from"
|
||||
option :inline, type: :boolean, required: false, hidden: true
|
||||
def fetch(*secrets)
|
||||
results = adapter(options[:adapter]).fetch(secrets, **options.slice(:account, :from).symbolize_keys)
|
||||
puts JSON.dump(results).shellescape
|
||||
rescue => e
|
||||
handle_error(e)
|
||||
handle_output(inline: options[:inline]) do
|
||||
results = adapter(options[:adapter]).fetch(secrets, **options.slice(:account, :from).symbolize_keys)
|
||||
JSON.dump(results).shellescape
|
||||
end
|
||||
end
|
||||
|
||||
desc "extract", "Extract a single secret from the results of a fetch call"
|
||||
option :inline, type: :boolean, required: false, hidden: true
|
||||
def extract(name, secrets)
|
||||
parsed_secrets = JSON.parse(secrets)
|
||||
handle_output(inline: options[:inline]) do
|
||||
parsed_secrets = JSON.parse(secrets)
|
||||
|
||||
if (value = parsed_secrets[name]).nil?
|
||||
value = parsed_secrets.find { |k, v| k.end_with?("/#{name}") }&.last
|
||||
value = parsed_secrets[name] || parsed_secrets.find { |k, v| k.end_with?("/#{name}") }&.last
|
||||
|
||||
raise "Could not find secret #{name}" if value.nil?
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
raise "Could not find secret #{name}" if value.nil?
|
||||
|
||||
puts value
|
||||
rescue => e
|
||||
handle_error(e)
|
||||
end
|
||||
|
||||
private
|
||||
@@ -30,11 +30,18 @@ class Kamal::Cli::Secrets < Kamal::Cli::Base
|
||||
Kamal::Secrets::Adapters.lookup(adapter)
|
||||
end
|
||||
|
||||
def handle_output(inline: nil)
|
||||
yield.tap do |output|
|
||||
puts output unless inline
|
||||
end
|
||||
rescue => e
|
||||
handle_error(e)
|
||||
end
|
||||
|
||||
def handle_error(e)
|
||||
$stderr.puts " \e[31mERROR (#{e.class}): #{e.message}\e[0m"
|
||||
$stderr.puts e.backtrace if ENV["VERBOSE"]
|
||||
|
||||
Process.kill("INT", Process.ppid) if ENV["KAMAL_SECRETS_INT_PARENT"]
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,17 +30,9 @@ class Kamal::Secrets
|
||||
|
||||
def parse_secrets
|
||||
if secrets_file
|
||||
interrupting_parent_on_error { ::Dotenv.parse(secrets_file) }
|
||||
::Dotenv.parse(secrets_file)
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def interrupting_parent_on_error
|
||||
# Make any `kamal secrets` calls in dotenv interpolation interrupt this process if there are errors
|
||||
ENV["KAMAL_SECRETS_INT_PARENT"] = "1"
|
||||
yield
|
||||
ensure
|
||||
ENV.delete("KAMAL_SECRETS_INT_PARENT")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ class Kamal::Secrets::Dotenv::InlineCommandSubstitution
|
||||
else
|
||||
if command =~ /\A\s*kamal\s*secrets\s+/
|
||||
# Inline the command
|
||||
capture_stdout { Kamal::Cli::Main.start(command.shellsplit[1..]) }.chomp
|
||||
inline_secrets_command(command)
|
||||
else
|
||||
# Execute the command and return the value
|
||||
`#{command}`.chomp
|
||||
@@ -25,13 +25,8 @@ class Kamal::Secrets::Dotenv::InlineCommandSubstitution
|
||||
end
|
||||
end
|
||||
|
||||
def capture_stdout
|
||||
old_stdout = $stdout
|
||||
$stdout = StringIO.new
|
||||
yield
|
||||
$stdout.string
|
||||
ensure
|
||||
$stdout = old_stdout
|
||||
def inline_secrets_command(command)
|
||||
Kamal::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ require "test_helper"
|
||||
|
||||
class SecretsInlineCommandSubstitution < SecretAdapterTestCase
|
||||
test "inlines kamal secrets commands" do
|
||||
Kamal::Cli::Main.expects(:start).with { |command| puts "results"; command == [ "secrets", "fetch", "..." ] }
|
||||
Kamal::Cli::Main.expects(:start).with { |command| command == [ "secrets", "fetch", "...", "--inline" ] }.returns("results")
|
||||
substituted = Kamal::Secrets::Dotenv::InlineCommandSubstitution.call("FOO=$(kamal secrets fetch ...)", nil, overwrite: false)
|
||||
assert_equal "FOO=results", substituted
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user