Skip to content

Instantly share code, notes, and snippets.

@lawrencejones
Created January 12, 2018 13:52
Show Gist options
  • Save lawrencejones/79f707a507a87ff5395d78ef2dde9978 to your computer and use it in GitHub Desktop.
Save lawrencejones/79f707a507a87ff5395d78ef2dde9978 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require "tempfile"
require "open3"
require "shellwords"
require "yaml"
require "base64"
require "active_support/core_ext/hash"
def print_usage
puts <<-USAGE
Desc: Edit a kube secret resource, automatically handling base64
Usage: edit-secret <ctx> <namespace> <release-name>
Examples...
edit-secret prd production sentry
USAGE
end
class Kubectl
def initialize(context, namespace)
@context = context
@namespace = namespace
end
def connect!
output, status = exec("get", "pods")
return true if status.success?
STDERR.puts(output)
raise "failed to connect to kube!"
end
def get(resource:, name:)
output, status = exec("get", "-o", "yaml", resource, name)
return YAML.load(output) if status.success?
raise "failed to access #{resource} named #{name}!"
end
def apply(content)
output, status = exec("apply", "-f", "-", stdin_data: content)
return output if status.success?
STDERR.puts(output)
raise "failed to apply resource!"
end
# returns output, status
def exec(*args, stdin_data: nil)
Open3.capture2e(
Shellwords.join([
"kubectl",
"--context", @context,
"--namespace", @namespace,
*args,
]),
stdin_data: stdin_data,
)
end
end
def edit_yaml(value)
tmp = Tempfile.new
tmp.write(value.to_yaml)
tmp.close
# Open the secret values for editing
Kernel.system("#{ENV.fetch("EDITOR", "vim")} #{tmp.path}")
updated_content = File.read(tmp.path)
if updated_content == value.to_yaml
puts("No changes made, exiting")
exit 0
end
tmp.unlink
YAML.load(updated_content)
end
def deep_transform(hash, &block)
hash.transform_values do |value|
value.is_a?(Hash) ? deep_transform(value, &block) : block.call("#{value}")
end
end
context, namespace, release = ARGV
unless context && namespace && release
print_usage
exit
end
kubectl = Kubectl.new(context, namespace).tap(&:connect!)
secret = kubectl.get(resource: "secret", name: "values-#{release}")
secret.fetch('metadata').delete('creationTimestamp')
secret_data = secret.fetch('data', {})
decoded = deep_transform(secret_data, &Base64.method(:strict_decode64))
encoded = deep_transform(edit_yaml(decoded), &Base64.method(:strict_encode64))
kubectl.apply(secret.merge('data' => encoded).to_yaml)
puts("Saved new secret values")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment