Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support stdin #415

Merged
merged 18 commits into from
Mar 5, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ offical compatibility chart below.

Refer to `kubernetes-deploy --help` for the authoritative set of options.

- `--template-dir=DIR`: Used to set the deploy directory. Set `$ENVIRONMENT` instead to use `config/deploy/$ENVIRONMENT`.
- `--template-dir=DIR`: Used to set the deploy directory. Set `$ENVIRONMENT` instead to use `config/deploy/$ENVIRONMENT`. This flag also supports reading from STDIN. You can do this by using `--template-dir=-`. Example: `cat templates_from_stdin/*.yml | kubernetes-deploy ns ctx --template-dir=-`.
- `--bindings=BINDINGS`: Makes additional variables available to your ERB templates. For example, `kubernetes-deploy my-app cluster1 --bindings=color=blue,size=large` will expose `color` and `size`.
- `--no-prune`: Skips pruning of resources that are no longer in your Kubernetes template set. Not recommended, as it allows your namespace to accumulate cruft that is not reflected in your deploy directory.
- `--max-watch-seconds=seconds`: Raise a timeout error if it takes longer than _seconds_ for any
Expand Down Expand Up @@ -491,7 +491,7 @@ kubernetes-render --template-dir=./path/to/template/dir this-template.yaml.erb t

*Options:*

- `--template-dir=DIR`: Used to set the directory to interpret template names relative to. This is often the same directory passed as `--template-dir` when running `kubernetes-deploy` to actually deploy templates. Set `$ENVIRONMENT` instead to use `config/deploy/$ENVIRONMENT`.
- `--template-dir=DIR`: Used to set the directory to interpret template names relative to. This is often the same directory passed as `--template-dir` when running `kubernetes-deploy` to actually deploy templates. Set `$ENVIRONMENT` instead to use `config/deploy/$ENVIRONMENT`. This flag also supports reading from STDIN. You can do this by using `--template-dir=-`.
- `--bindings=BINDINGS`: Makes additional variables available to your ERB templates. For example, `kubernetes-render --bindings=color=blue,size=large some-template.yaml.erb` will expose `color` and `size` to `some-template.yaml.erb`.


Expand Down
40 changes: 23 additions & 17 deletions exe/kubernetes-deploy
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ ARGV.options do |opts|
prot_ns = KubernetesDeploy::DeployTask::PROTECTED_NAMESPACES.join(', ')
opts.on("--allow-protected-ns", "Enable deploys to #{prot_ns}; requires --no-prune") { allow_protected_ns = true }
opts.on("--no-prune", "Disable deletion of resources that do not appear in the template dir") { prune = false }
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT)") { |v| template_dir = v }
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT).") do |d|
template_dir = d
end
opts.on("--verbose-log-prefix", "Add [context][namespace] to the log prefix") { verbose_log_prefix = true }
opts.on("--max-watch-seconds=seconds",
"Timeout error is raised if it takes longer than the specified number of seconds") do |t|
Expand All @@ -42,27 +44,31 @@ end

namespace = ARGV[0]
context = ARGV[1]
template_dir = KubernetesDeploy::OptionsHelper.default_and_check_template_dir(template_dir)
logger = KubernetesDeploy::FormattedLogger.build(namespace, context, verbose_prefix: verbose_log_prefix)

runner = KubernetesDeploy::DeployTask.new(
namespace: namespace,
context: context,
current_sha: ENV["REVISION"],
template_dir: template_dir,
bindings: bindings,
logger: logger,
max_watch_seconds: max_watch_seconds
)

begin
runner.run!(
verify_result: !skip_wait,
allow_protected_ns: allow_protected_ns,
prune: prune
)
KubernetesDeploy::OptionsHelper.with_validated_template_dir(template_dir) do |dir|
runner = KubernetesDeploy::DeployTask.new(
namespace: namespace,
context: context,
current_sha: ENV["REVISION"],
template_dir: dir,
bindings: bindings,
logger: logger,
max_watch_seconds: max_watch_seconds
)

runner.run!(
verify_result: !skip_wait,
allow_protected_ns: allow_protected_ns,
prune: prune
)
end
rescue KubernetesDeploy::DeploymentTimeoutError
exit(70)
rescue KubernetesDeploy::FatalDeploymentError
exit(1)
rescue KubernetesDeploy::OptionsHelper::OptionsError => e
logger.error(e.message)
exit(1)
end
27 changes: 18 additions & 9 deletions exe/kubernetes-render
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,29 @@ ARGV.options do |opts|
parser = KubernetesDeploy::BindingsParser.new
opts.on("--bindings=BINDINGS", "Expose additional variables to ERB templates " \
"(format: k1=v1,k2=v2, JSON string or file (JSON or YAML) path prefixed by '@')") { |b| parser.add(b) }
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT)") { |v| template_dir = v }
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT)." ) do |d|
template_dir << d
end
opts.parse!
bindings = parser.parse
end

templates = ARGV
logger = KubernetesDeploy::FormattedLogger.build(verbose_prefix: false)

runner = KubernetesDeploy::RenderTask.new(
logger: logger,
current_sha: ENV["REVISION"],
template_dir: template_dir,
bindings: bindings,
)
begin
KubernetesDeploy::OptionsHelper.with_validated_template_dir(template_dir) do |dir|
runner = KubernetesDeploy::RenderTask.new(
logger: logger,
current_sha: ENV["REVISION"],
template_dir: dir,
bindings: bindings,
)

success = runner.run(STDOUT, templates)
exit(1) unless success
success = runner.run(STDOUT, templates)
exit(1) unless success
end
rescue KubernetesDeploy::OptionsHelper::OptionsError => e
logger.error(e.message)
exit(1)
end
41 changes: 32 additions & 9 deletions lib/kubernetes-deploy/options_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,42 @@

module KubernetesDeploy
module OptionsHelper
def self.default_and_check_template_dir(template_dir)
if !template_dir && ENV.key?("ENVIRONMENT")
template_dir = "config/deploy/#{ENV['ENVIRONMENT']}"
class OptionsError < StandardError; end

STDIN_TEMP_FILE = "from_stdin.yml.erb"
class << self
def with_validated_template_dir(template_dir)
if template_dir == '-'
Dir.mktmpdir("kubernetes-deploy") do |dir|
template_dir_from_stdin(temp_dir: dir)
yield dir
end
else
yield default_template_dir(template_dir)
end
end

if !template_dir || template_dir.empty?
puts "Template directory is unknown. " \
"Either specify --template-dir argument or set $ENVIRONMENT to use config/deploy/$ENVIRONMENT " \
+ "as a default path."
exit(1)
private

def default_template_dir(template_dir)
if ENV.key?("ENVIRONMENT")
template_dir = File.join("config", "deploy", ENV['ENVIRONMENT'])
end

if !template_dir || template_dir.empty?
raise OptionsError, "Template directory is unknown. " \
"Either specify --template-dir argument or set $ENVIRONMENT to use config/deploy/$ENVIRONMENT " \
"as a default path."
end

template_dir
end

template_dir
def template_dir_from_stdin(temp_dir:)
File.open(File.join(temp_dir, STDIN_TEMP_FILE), 'w+') { |f| f.print($stdin.read) }
rescue IOError, Errno::ENOENT => e
raise OptionsError, e.message
end
end
end
end
63 changes: 63 additions & 0 deletions test/unit/kubernetes-deploy/options_helper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true
require 'test_helper'
require 'tempfile'

class OptionsHelperTest < KubernetesDeploy::TestCase
include EnvTestHelper
def test_with_template_dir
KubernetesDeploy::OptionsHelper.with_validated_template_dir(fixture_path('hello-cloud')) do |template_dir|
assert_equal(fixture_path('hello-cloud'), template_dir)
end
end

def test_template_dir_with_default_env_var
with_env("ENVIRONMENT", "test") do
KubernetesDeploy::OptionsHelper.with_validated_template_dir(nil) do |template_dir|
assert_equal(template_dir, File.join("config", "deploy", "test"))
end
end
end

def test_missing_template_dir_raises
with_env("ENVIRONMENT", nil) do
assert_raises(KubernetesDeploy::OptionsHelper::OptionsError) do
KubernetesDeploy::OptionsHelper.with_validated_template_dir(nil) do
end
end
end
end

def test_with_template_dir_from_stdin
old_stdin = $stdin
fixture_yamls = []
stdin_yamls = []

input = Tempfile.open("kubernetes_deploy_test")
fixture_path_entries = Dir.glob("#{fixture_path('hello-cloud')}/*.{yml,yaml}*")
fixture_path_entries.each do |filename|
File.open(filename, 'r') do |f|
contents = f.read
input.print(contents + "\n---\n")
contents.split(/^---$/).reject(&:empty?).each { |c| fixture_yamls << YAML.safe_load(c) }
end
end
input.rewind
$stdin = input

KubernetesDeploy::OptionsHelper.with_validated_template_dir('-') do |template_dir|
split_templates = File.read(
File.join(template_dir, KubernetesDeploy::OptionsHelper::STDIN_TEMP_FILE)
).split(/^---$/).map(&:strip).reject(&:empty?)
refute(split_templates.empty?)
split_templates.each do |template|
stdin_yamls << YAML.safe_load(template)
end

fixture_yamls.each do |fixture|
assert(stdin_yamls.include?(fixture))
end
end
ensure
$stdin = old_stdin
end
end