Make the secrets commands inline aware

Rather than redirecting the global $stdout, which is not never clever in
a threaded program, we'll make the secrets commands aware they are
being inlined, so they return the value instead of printing it.

Additionally we no longer need to interrupt the parent process on error
as we've inlined the command - exit 1 is enough.
This commit is contained in:
Donal McBreen
2024-09-10 10:24:14 +01:00
parent 5aa3d1aeb0
commit 06f4caa866
4 changed files with 26 additions and 32 deletions

View File

@@ -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