diff --git a/lib/stackup.rb b/lib/stackup.rb index 26f286d..14afc9b 100644 --- a/lib/stackup.rb +++ b/lib/stackup.rb @@ -1,3 +1,4 @@ require "aws-sdk" require_relative "stackup/monitor" require_relative "stackup/stack" +require "json" diff --git a/lib/stackup/cli.rb b/lib/stackup/cli.rb index 4f34f44..8852a38 100644 --- a/lib/stackup/cli.rb +++ b/lib/stackup/cli.rb @@ -4,21 +4,30 @@ class CLI < Clamp::Command subcommand ["stack"], "Manage a stack." do parameter "STACK-NAME", "Name of stack", :attribute_name => :stack_name - subcommand "apply", "Create/update the stack" do + subcommand "deploy", "Create/update the stack" do parameter "TEMPLATE", "CloudFormation template (.json)", :attribute_name => :template + parameter "PARAMETERS", "CloudFormation parameters (.json)", :attribute_name => :parameters def execute - stack = Stackup::Stack.new(stack_name, template) - stack.create + params = JSON.parse(parameters) + stack = Stackup::Stack.new(stack_name) + stack.create(template, params) end end subcommand "delete", "Remove the stack." do def execute - stack = Stackup::Stack.new(stack_name, nil) + stack = Stackup::Stack.new(stack_name) stack.delete end end + + subcommand "outputs", "Stack outputs." do + def execute + stack = Stackup::Stack.new(stack_name) + stack.outputs + end + end end end diff --git a/lib/stackup/stack.rb b/lib/stackup/stack.rb index c4db375..5c3a211 100644 --- a/lib/stackup/stack.rb +++ b/lib/stackup/stack.rb @@ -15,25 +15,28 @@ def initialize(name) @name = name end - def create(template) + def create(template, parameters) response = cf.create_stack(:stack_name => name, :template_body => template, - :disable_rollback => true) + :disable_rollback => true, + :parameters => parameters) wait_till_end !response[:stack_id].nil? end - def deploy(template) + def deploy(template, parameters = []) if deployed? - update(template) + update(template, parameters) else - create(template) + create(template, parameters) end + rescue Aws::CloudFormation::Errors::ValidationError => e + puts e.message end - def update(template) + def update(template, parameters) return false unless deployed? - response = cf.update_stack(:stack_name => name, :template_body => template) + response = cf.update_stack(:stack_name => name, :template_body => template, :parameters => parameters) wait_till_end !response[:stack_id].nil? end @@ -45,6 +48,10 @@ def delete puts "Stack does not exist." end + def outputs + puts stack.outputs.flat_map { |output| "#{output.output_key} - #{output.output_value}" } + end + def display_events monitor.new_events.each do |e| ts = e.timestamp.localtime.strftime("%H:%M:%S") diff --git a/spec/stackup/stack_spec.rb b/spec/stackup/stack_spec.rb index c6d0d3e..9561b9f 100644 --- a/spec/stackup/stack_spec.rb +++ b/spec/stackup/stack_spec.rb @@ -5,6 +5,7 @@ let(:template) { double(String) } let(:cf_stack) { double(Aws::CloudFormation::Stack) } let(:cf) { double(Aws::CloudFormation::Client) } + let(:parameters) { [] } before do allow(Aws::CloudFormation::Client).to receive(:new).and_return(cf) @@ -16,12 +17,12 @@ it "should call create if stack is not deployed" do allow(stack).to receive(:deployed?).and_return(false) expect(stack).to receive(:create).and_return(true) - expect(stack.deploy(template)).to be true + expect(stack.deploy(template, parameters)).to be true end it "should call update if stack is deployed" do allow(stack).to receive(:deployed?).and_return(true) expect(stack).to receive(:update).and_return(true) - expect(stack.deploy(template)).to be true + expect(stack.deploy(template, parameters)).to be true end end @@ -32,12 +33,12 @@ allow(response).to receive(:[]).with(:stack_id).and_return("1") allow(cf).to receive(:update_stack).and_return(response) allow(cf_stack).to receive(:wait_until).and_return(true) - expect(stack.update(template)).to be true + expect(stack.update(template, parameters)).to be true end it "should not update if the stack is not deployed" do allow(cf_stack).to receive(:stack_status).and_raise(Aws::CloudFormation::Errors::ValidationError.new("1", "2")) - expect(stack.update(template)).to be false + expect(stack.update(template, parameters)).to be false end end @@ -56,14 +57,14 @@ allow(response).to receive(:[]).with(:stack_id).and_return("1") allow(cf).to receive(:create_stack).and_return(response) allow(cf_stack).to receive(:wait_until).and_return(true) - expect(stack.create(template)).to be true + expect(stack.create(template, parameters)).to be true end it "should return nil if stack was not created" do allow(response).to receive(:[]).with(:stack_id).and_return(nil) allow(cf).to receive(:create_stack).and_return(response) allow(cf_stack).to receive(:wait_until).and_return(false) - expect(stack.create(template)).to be false + expect(stack.create(template, parameters)).to be false end end diff --git a/stackup.gemspec b/stackup.gemspec index 2950a20..f2a007b 100644 --- a/stackup.gemspec +++ b/stackup.gemspec @@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |spec| spec.name = "stackup" - spec.version = "0.0.4" + spec.version = "0.0.5" spec.authors = ["Arvind Kunday", "Mike Williams"] spec.email = ["arvind.kunday@rea-group.com", "mike.williams@rea-group.com"] spec.summary = "Tools for deployment to AWS"