simple_deploy 0.6.7 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ ## v0.7.0:
2
+
3
+ * Added --as-command-args argument to outputs command
4
+ * Added support to read stack parameters from other stack outputs
5
+ * Better handling of errors for deploy/execute commands (#149, #150, #155)
6
+
1
7
  ## v0.6.7:
2
8
 
3
9
  * Upgraded to stackster 0.4.2
@@ -17,8 +17,13 @@ simple_deploy create -n STACK_NAME -t PATH_TO_TEMPLATE -e ENVIRONMENT -a KEY1=VA
17
17
 
18
18
  EOS
19
19
  opt :help, "Display Help"
20
- opt :attributes, "= seperated attribute and it's value", :type => :string,
20
+ opt :attributes, "= seperated attribute(s) and it's value. \
21
+ Can be specified multiple times.", :type => :string,
21
22
  :multi => true
23
+ opt :input_stack, "Read outputs from given stack(s) and map them \
24
+ to parameter inputs in the new stack. These will be passed to inputs with \
25
+ matching or pluralized names. Can be specified multiple times.", :type => :string,
26
+ :multi => true
22
27
  opt :environment, "Set the target environment", :type => :string
23
28
  opt :log_level, "Log level: debug, info, warn, error", :type => :string,
24
29
  :default => 'info'
@@ -29,29 +34,44 @@ EOS
29
34
  valid_options? :provided => @opts,
30
35
  :required => [:environment, :name, :template]
31
36
 
32
- config = Config.new.environment @opts[:environment]
33
-
34
- attributes = parse_attributes :attributes => @opts[:attributes]
37
+ @config = Config.new.environment @opts[:environment]
35
38
 
36
39
  stack = Stack.new :environment => @opts[:environment],
37
40
  :name => @opts[:name],
38
- :config => config,
41
+ :config => @config,
39
42
  :logger => logger
40
43
 
41
44
  rescue_stackster_exceptions_and_exit do
42
- stack.create :attributes => attributes,
45
+ stack.create :attributes => merged_attributes,
43
46
  :template => @opts[:template]
44
47
  end
45
48
  end
46
49
 
47
- def logger
48
- @logger ||= SimpleDeployLogger.new :log_level => @opts[:log_level]
49
- end
50
-
51
50
  def command_summary
52
51
  'Create a new stack'
53
52
  end
54
53
 
54
+ private
55
+
56
+ def merged_attributes
57
+ provided_attributes = parse_attributes :attributes => @opts[:attributes]
58
+
59
+ attribute_merger.merge :attributes => provided_attributes,
60
+ :config => @config,
61
+ :logger => @logger,
62
+ :environment => @opts[:environment],
63
+ :input_stacks => @opts[:input_stack],
64
+ :template => @opts[:template]
65
+ end
66
+
67
+ def attribute_merger
68
+ SimpleDeploy::Misc::AttributeMerger.new
69
+ end
70
+
71
+ def logger
72
+ @logger ||= SimpleDeployLogger.new :log_level => @opts[:log_level]
73
+ end
74
+
55
75
  end
56
76
 
57
77
  end
@@ -50,8 +50,10 @@ EOS
50
50
  :internal => @opts[:internal]
51
51
 
52
52
  begin
53
- stack.execute :command => @opts[:command],
54
- :sudo => @opts[:sudo]
53
+ unless stack.execute :command => @opts[:command],
54
+ :sudo => @opts[:sudo]
55
+ exit 1
56
+ end
55
57
  rescue SimpleDeploy::Exceptions::NoInstances
56
58
  logger.error "Stack has no running instances."
57
59
  exit 1
@@ -17,6 +17,8 @@ simple_deploy outputs -n STACK_NAME -e ENVIRONMENT
17
17
 
18
18
  EOS
19
19
  opt :help, "Display Help"
20
+ opt :as_command_args,
21
+ "Displays the attributes in a format suitable for using on the command line"
20
22
  opt :environment, "Set the target environment", :type => :string
21
23
  opt :log_level, "Log level: debug, info, warn, error", :type => :string,
22
24
  :default => 'warn'
@@ -34,25 +36,37 @@ EOS
34
36
  :logger => logger
35
37
 
36
38
  rescue_stackster_exceptions_and_exit do
37
- outputs = stack.outputs
39
+ @outputs = stack.outputs
38
40
 
39
- logger.info "No outputs." unless outputs.any?
41
+ logger.info "No outputs." unless @outputs.any?
40
42
 
41
- outputs.each do |hash|
42
- puts "%s: %s" % [hash['OutputKey'], hash['OutputValue']]
43
- end
43
+ @opts[:as_command_args] ? command_args_output : default_output
44
44
  end
45
45
  end
46
46
 
47
- def logger
48
- @logger ||= SimpleDeployLogger.new :log_level => @opts[:log_level]
49
- end
50
-
51
47
  def command_summary
52
48
  'Show outputs of a stack'
53
49
  end
54
50
 
55
- end
51
+ private
52
+
53
+ def command_args_output
54
+ @outputs.each do |hash|
55
+ print "-a %s=%s " % [hash['OutputKey'], hash['OutputValue']]
56
+ end
57
+ puts ""
58
+ end
56
59
 
60
+ def default_output
61
+ @outputs.each do |hash|
62
+ puts "%s: %s" % [hash['OutputKey'], hash['OutputValue']]
63
+ end
64
+ end
65
+
66
+ def logger
67
+ @logger ||= SimpleDeployLogger.new :log_level => @opts[:log_level]
68
+ end
69
+
70
+ end
57
71
  end
58
72
  end
@@ -8,6 +8,12 @@ module SimpleDeploy
8
8
  @message = message
9
9
  end
10
10
  end
11
+
12
+ class NoInstances < Base
13
+ end
14
+
15
+ class Exceptions::NoInstances < Base
16
+ end
11
17
 
12
18
  end
13
19
  end
@@ -0,0 +1,45 @@
1
+ module SimpleDeploy
2
+ module Misc
3
+ class AttributeMerger
4
+
5
+ def merge(args)
6
+ @attributes = args[:attributes]
7
+ @config = args[:config]
8
+ @environment = args[:environment]
9
+ @logger = args[:logger]
10
+ @input_stacks = args[:input_stacks]
11
+ @template = args[:template]
12
+
13
+ combine_provided_and_mapped_attributes
14
+ end
15
+
16
+ private
17
+
18
+ def combine_provided_and_mapped_attributes
19
+ @attributes + mapped_attributes_not_provided
20
+ end
21
+
22
+ def mapped_attributes
23
+ mapper.map_outputs_from_stacks :stacks => @input_stacks,
24
+ :template => @template
25
+ end
26
+
27
+ def mapped_attributes_not_provided
28
+ mapped_attributes.reject do |a|
29
+ provided_attribute_keys.include? a.keys.first
30
+ end
31
+ end
32
+
33
+ def provided_attribute_keys
34
+ @attributes.map {|a| a.keys.first}
35
+ end
36
+
37
+ def mapper
38
+ @om ||= Stack::OutputMapper.new :environment => @environment,
39
+ :config => @config,
40
+ :logger => @logger
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1 @@
1
+ require 'simple_deploy/misc/attribute_merger'
@@ -0,0 +1,88 @@
1
+ module SimpleDeploy
2
+ class Stack
3
+ class OutputMapper
4
+
5
+ def initialize(args)
6
+ @config = args[:config]
7
+ @environment = args[:environment]
8
+ @logger = args[:logger]
9
+ end
10
+
11
+ def map_outputs_from_stacks(args)
12
+ @stacks = args[:stacks]
13
+ @template = args[:template]
14
+ @results = {}
15
+
16
+ merge_stacks_outputs
17
+
18
+ pluralize_keys
19
+
20
+ prune_unused_parameters
21
+
22
+ @results.each_pair do |key, value|
23
+ @logger.info "Mapping output '#{key}' to input parameter with value '#{value}'."
24
+ end
25
+
26
+ @results.map { |x| { x.first => x.last } }
27
+ end
28
+
29
+ private
30
+
31
+ def merge_stacks_outputs
32
+ count = 0
33
+
34
+ @stacks.each do |s|
35
+ count += 1
36
+ @logger.info "Reading outputs from stack '#{s}'."
37
+ stack = Stack.new :environment => @environment,
38
+ :config => @config,
39
+ :logger => @logger,
40
+ :name => s
41
+ stack.wait_for_stable
42
+ merge_outputs stack
43
+ SimpleDeploy::Backoff.exp_periods(count < 5 ? count : 5) do |backoff|
44
+ @logger.info "Backing off for #{backoff} seconds."
45
+ sleep backoff
46
+ end
47
+ end
48
+ end
49
+
50
+ def merge_outputs(stack)
51
+ stack.outputs.each do |output|
52
+ key = output['OutputKey']
53
+ value = output['OutputValue']
54
+
55
+ @logger.debug "Read output #{key}=#{value}."
56
+
57
+ if @results.has_key? key
58
+ @results[key] += ",#{value}"
59
+ else
60
+ @results[key] = value
61
+ end
62
+ end
63
+ end
64
+
65
+ def pluralize_keys
66
+ plural_params = @results.each_with_object({}) do |results, new|
67
+ key = results.first
68
+ pluralized_key = "#{key}s"
69
+
70
+ if template_parameters.include? pluralized_key
71
+ new[pluralized_key] = results[1]
72
+ end
73
+ end
74
+
75
+ @results.merge! plural_params
76
+ end
77
+
78
+ def prune_unused_parameters
79
+ @results.select! { |key| template_parameters.include? key }
80
+ end
81
+
82
+ def template_parameters
83
+ @parameters ||= Template.new(:file => @template).parameters
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -20,7 +20,22 @@ module SimpleDeploy
20
20
  def execute(args)
21
21
  return false if @instances.nil? || @instances.empty?
22
22
  create_execute_task args
23
- @task.execute
23
+
24
+ status = false
25
+
26
+ begin
27
+ @task.execute
28
+ status = true
29
+ @logger.info "Command executed against instances successfully."
30
+ rescue ::Capistrano::CommandError => error
31
+ @logger.error "Error running execute statement: #{error}"
32
+ rescue ::Capistrano::ConnectionError => error
33
+ @logger.error "Error connecting to instances: #{error}"
34
+ rescue ::Capistrano::Error => error
35
+ @logger.error "Error: #{error}"
36
+ end
37
+
38
+ status
24
39
  end
25
40
 
26
41
  private
@@ -1,6 +1,7 @@
1
1
  require 'stackster'
2
2
  require 'simple_deploy/stack/deployment'
3
3
  require 'simple_deploy/stack/execute'
4
+ require 'simple_deploy/stack/output_mapper'
4
5
  require 'simple_deploy/stack/stack_attribute_formater'
5
6
 
6
7
  module SimpleDeploy
@@ -0,0 +1,21 @@
1
+ module SimpleDeploy
2
+ class Template
3
+ def initialize(args)
4
+ @file = args[:file]
5
+ end
6
+
7
+ def parameters
8
+ parsed_template_contents.fetch('Parameters', {}).keys
9
+ end
10
+
11
+ private
12
+
13
+ def parsed_template_contents
14
+ JSON.parse contents
15
+ end
16
+
17
+ def contents
18
+ @contents ||= IO.read @file
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleDeploy
2
- VERSION = "0.6.7"
2
+ VERSION = "0.7.0"
3
3
  end
data/lib/simple_deploy.rb CHANGED
@@ -3,6 +3,8 @@ require 'simple_deploy/exceptions'
3
3
  require 'simple_deploy/config'
4
4
  require 'simple_deploy/artifact'
5
5
  require 'simple_deploy/stack'
6
+ require 'simple_deploy/misc'
7
+ require 'simple_deploy/template'
6
8
  require 'simple_deploy/notifier'
7
9
  require 'simple_deploy/logger'
8
10
  require 'simple_deploy/version'
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::CLI::Create do
4
+ before do
5
+ @config_object = mock 'config'
6
+ @config_env = mock 'environment config'
7
+ @stack_mock = mock 'stack'
8
+ @attribute_merger_mock = mock 'attribute merger'
9
+ @logger = stub 'logger', :info => true
10
+
11
+ @options = { :attributes => [ 'attr1=val1' ],
12
+ :input_stack => [ 'stack1' ],
13
+ :environment => 'test',
14
+ :name => 'mytest',
15
+ :log_level => 'info',
16
+ :template => '/tmp/test.json' }
17
+ Trollop.stub :options => @options
18
+ SimpleDeploy::Config.stub :new => @config_object
19
+ SimpleDeploy::SimpleDeployLogger.should_receive(:new).
20
+ with(:log_level => 'info').
21
+ and_return @logger
22
+ @config_object.stub :environments => { 'test' => 'config_data' }
23
+ @config_object.should_receive(:environment).with('test').
24
+ and_return 'config_data'
25
+ SimpleDeploy::Stack.should_receive(:new).
26
+ with(:environment => 'test',
27
+ :name => 'mytest',
28
+ :config => 'config_data',
29
+ :logger => @logger).
30
+ and_return(@stack_mock)
31
+ SimpleDeploy::Misc::AttributeMerger.stub :new => @attribute_merger_mock
32
+ merge_options = { :attributes => [ { "attr1" => "val1" } ],
33
+ :config => 'config_data',
34
+ :logger => @logger,
35
+ :environment => 'test',
36
+ :template => '/tmp/test.json',
37
+ :input_stacks => ["stack1"] }
38
+ @attribute_merger_mock.should_receive(:merge).with(merge_options).
39
+ and_return({ "attr1" => "val1",
40
+ "attr2" => "val2" })
41
+ @create = SimpleDeploy::CLI::Create.new
42
+ end
43
+
44
+ it "should create a stack with provided and merged attributes" do
45
+ @stack_mock.should_receive(:create).
46
+ with({ :attributes => { "attr1" => "val1",
47
+ "attr2" => "val2" },
48
+ :template => '/tmp/test.json' })
49
+ @create.create
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'simple_deploy/cli'
3
+
4
+ describe SimpleDeploy::CLI::Outputs do
5
+
6
+ before do
7
+ @config_object = mock 'config'
8
+ @config_env = mock 'environment config'
9
+ @stack = mock 'stack'
10
+ @logger = stub 'logger'
11
+ @options = { :environment => 'test',
12
+ :log_level => 'info',
13
+ :name => 'mytest' }
14
+ @data = [{ 'OutputKey' => 'key1', 'OutputValue' => 'value1' },
15
+ { 'OutputKey' => 'key2', 'OutputValue' => 'value2' }]
16
+ Trollop.stub :options => @options
17
+ @config_object.stub(:environments => { 'test' => 'data' })
18
+ SimpleDeploy::Config.stub :new => @config_object
19
+ SimpleDeploy::SimpleDeployLogger.should_receive(:new).
20
+ with(:log_level => 'info').
21
+ and_return @logger
22
+ SimpleDeploy::Stack.should_receive(:new).
23
+ with(:environment => 'test',
24
+ :name => 'mytest',
25
+ :config => @config_env,
26
+ :logger => @logger).
27
+ and_return(@stack)
28
+ @stack.stub :outputs => @data
29
+ @config_object.should_receive(:environment).with('test').
30
+ and_return @config_env
31
+ @outputs = SimpleDeploy::CLI::Outputs.new
32
+ end
33
+
34
+ it "should successfully return the show command with default values" do
35
+ @outputs.should_receive(:puts).with('key1: value1')
36
+ @outputs.should_receive(:puts).with('key2: value2')
37
+ @outputs.show
38
+ end
39
+
40
+ it "should successfully return the show command with as_command_args" do
41
+ @options[:as_command_args] = true
42
+ @outputs.should_receive(:print).with('-a key1=value1 ')
43
+ @outputs.should_receive(:print).with('-a key2=value2 ')
44
+ @outputs.should_receive(:puts).with('')
45
+ @outputs.show
46
+ end
47
+
48
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::Misc::AttributeMerger do
4
+
5
+ before do
6
+ @config_mock = mock 'config'
7
+ @mapper_mock = mock 'mapper'
8
+ @logger_stub = stub 'logger', :info => true
9
+
10
+ @stacks = ['stack1', 'stack2']
11
+ @options = { :config => @config_mock,
12
+ :environment => 'default',
13
+ :logger => @logger_stub,
14
+ :attributes => [ { 'attrib1' => 'val1' } ],
15
+ :input_stacks => @stacks,
16
+ :template => '/tmp/file.json' }
17
+ SimpleDeploy::Stack::OutputMapper.should_receive(:new).
18
+ with(:environment => @options[:environment],
19
+ :config => @options[:config],
20
+ :logger => @options[:logger]).
21
+ and_return @mapper_mock
22
+ @merger = SimpleDeploy::Misc::AttributeMerger.new
23
+ end
24
+
25
+ it "should return the consolidated list of attributes" do
26
+ @mapper_mock.should_receive(:map_outputs_from_stacks).
27
+ with(:stacks => @options[:input_stacks],
28
+ :template => @options[:template]).
29
+ and_return [ { 'attrib2' => 'val2' } ]
30
+ @merger.merge(@options).should == [ { 'attrib1' => 'val1' },
31
+ { 'attrib2' => 'val2' } ]
32
+ end
33
+
34
+ it "should return provided attributes over outputs" do
35
+ @mapper_mock.should_receive(:map_outputs_from_stacks).
36
+ with(:stacks => @options[:input_stacks],
37
+ :template => @options[:template]).
38
+ and_return [ { 'attrib1' => 'val2' } ]
39
+ @merger.merge(@options).should == [ { 'attrib1' => 'val1' } ]
40
+ end
41
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::Stack::OutputMapper do
4
+ before do
5
+ @config_mock = mock 'config'
6
+ @logger_stub = stub 'logger', :debug => true, :info => true
7
+
8
+ stack1_outputs = [ { 'OutputKey' => 'Test1', 'OutputValue' => 'val1' },
9
+ { 'OutputKey' => 'Nother', 'OutputValue' => 'another' } ]
10
+
11
+ stack2_outputs = [ { 'OutputKey' => 'Test2', 'OutputValue' => 'val2' },
12
+ { 'OutputKey' => 'NotMe', 'OutputValue' => 'another' } ]
13
+
14
+ stack3_outputs = [ { 'OutputKey' => 'Test1', 'OutputValue' => 'valA' } ]
15
+
16
+ stack4_outputs = [ { 'OutputKey' => 'Test', 'OutputValue' => 'val' } ]
17
+
18
+ @stack1_stub = stub 'stack1', :outputs => stack1_outputs, :wait_for_stable => true
19
+ @stack2_stub = stub 'stack2', :outputs => stack2_outputs, :wait_for_stable => true
20
+ @stack3_stub = stub 'stack3', :outputs => stack3_outputs, :wait_for_stable => true
21
+ @stack4_stub = stub 'stack4', :outputs => stack4_outputs, :wait_for_stable => true
22
+
23
+ @template_stub = stub 'template', :parameters => ["Test1", "Test2", "Tests"]
24
+
25
+ @mapper = SimpleDeploy::Stack::OutputMapper.new :config => @config_mock,
26
+ :environment => 'default',
27
+ :logger => @logger_stub
28
+ end
29
+
30
+ context "when provided stacks" do
31
+ before do
32
+ SimpleDeploy::Template.should_receive(:new).
33
+ with(:file => '/tmp/file.json').
34
+ and_return @template_stub
35
+ end
36
+
37
+ it "should return the outputs which match parameters" do
38
+ SimpleDeploy::Stack.should_receive(:new).
39
+ with(:environment => 'default',
40
+ :config => @config_mock,
41
+ :logger => @logger_stub,
42
+ :name => 'stack1').
43
+ and_return @stack1_stub
44
+ @mapper.should_receive(:sleep)
45
+ @mapper.map_outputs_from_stacks(:stacks => ['stack1'],
46
+ :template => '/tmp/file.json').
47
+ should == [{ 'Test1' => 'val1' }]
48
+ end
49
+
50
+ it "should return the outputs which match pluralized parameters" do
51
+ SimpleDeploy::Stack.should_receive(:new).
52
+ with(:environment => 'default',
53
+ :config => @config_mock,
54
+ :logger => @logger_stub,
55
+ :name => 'stack4').
56
+ and_return @stack4_stub
57
+ @mapper.should_receive(:sleep)
58
+ @mapper.map_outputs_from_stacks(:stacks => ['stack4'],
59
+ :template => '/tmp/file.json').
60
+ should == [{ 'Tests' => 'val' }]
61
+ end
62
+
63
+ it "should return the outputs which match parameters from multiple stacks" do
64
+ SimpleDeploy::Stack.should_receive(:new).
65
+ with(:environment => 'default',
66
+ :config => @config_mock,
67
+ :logger => @logger_stub,
68
+ :name => 'stack1').
69
+ and_return @stack1_stub
70
+ SimpleDeploy::Stack.should_receive(:new).
71
+ with(:environment => 'default',
72
+ :config => @config_mock,
73
+ :logger => @logger_stub,
74
+ :name => 'stack2').
75
+ and_return @stack2_stub
76
+ @mapper.should_receive(:sleep).exactly(3).times
77
+ @mapper.map_outputs_from_stacks(:stacks => ['stack1', 'stack2'],
78
+ :template => '/tmp/file.json').
79
+ should == [{ 'Test1' => 'val1' }, {'Test2' => 'val2' }]
80
+ end
81
+
82
+ it "should concatenate multiple outputs of same name into CSV" do
83
+ SimpleDeploy::Stack.should_receive(:new).
84
+ with(:environment => 'default',
85
+ :config => @config_mock,
86
+ :logger => @logger_stub,
87
+ :name => 'stack1').
88
+ and_return @stack1_stub
89
+ SimpleDeploy::Stack.should_receive(:new).
90
+ with(:environment => 'default',
91
+ :config => @config_mock,
92
+ :logger => @logger_stub,
93
+ :name => 'stack3').
94
+ and_return @stack3_stub
95
+ @mapper.should_receive(:sleep).exactly(3).times
96
+ @mapper.map_outputs_from_stacks(:stacks => ['stack1', 'stack3'],
97
+ :template => '/tmp/file.json').
98
+ should == [{ 'Test1' => 'val1,valA' }]
99
+ end
100
+ end
101
+
102
+ it "should return an empty hash if no stacks are specified" do
103
+ @mapper.map_outputs_from_stacks(:stacks => [],
104
+ :template => '/tmp/file.json').
105
+ should == []
106
+ end
107
+
108
+ end
@@ -6,77 +6,118 @@ describe SimpleDeploy::Stack::SSH do
6
6
  @task_mock = mock 'task'
7
7
  @config_mock = mock 'config'
8
8
  @logger_stub = stub 'logger', :debug => true,
9
- :info => true,
10
- :error => true
9
+ :info => true,
10
+ :error => true
11
11
  @config_mock.stub :logger => @logger_stub
12
12
  @config_mock.should_receive(:region).
13
- with('test-env').
14
- and_return 'test-us-west-1'
13
+ with('test-env').
14
+ and_return 'test-us-west-1'
15
15
  @stack_mock.stub :attributes => { :ssh_gateway => false }
16
+ @options = { :config => @config_mock,
17
+ :instances => ['1.2.3.4', '4.3.2.1'],
18
+ :environment => 'test-env',
19
+ :ssh_user => 'user',
20
+ :ssh_key => 'key',
21
+ :stack => @stack_mock,
22
+ :name => 'test-stack' }
23
+ @task_logger_mock = mock 'task_logger'
24
+ @ssh_options = Hash.new
25
+ @task_mock.stub :logger => @task_logger_mock,
26
+ :variables => @ssh_options
16
27
  end
17
28
 
18
29
  context "when unsuccessful" do
19
30
  it "should return false when no running instances running" do
20
- options = { :config => @config_mock,
21
- :instances => [],
22
- :environment => 'test-env',
23
- :ssh_user => 'user',
24
- :ssh_key => 'key',
25
- :stack => @stack_mock,
26
- :name => 'test-stack' }
27
- @ssh = SimpleDeploy::Stack::SSH.new options
31
+ @ssh = SimpleDeploy::Stack::SSH.new @options.merge({ :instances => [] })
32
+
28
33
  @ssh.execute(:sudo => true, :command => 'uname').should be_false
29
34
  end
35
+
36
+ context "with capistrano configured" do
37
+ before do
38
+ Capistrano::Configuration.should_receive(:new).
39
+ with(:output => @logger_stub).
40
+ and_return @task_mock
41
+
42
+ @task_logger_mock.should_receive(:level=).with(3)
43
+ @task_mock.should_receive(:set).with :user, 'user'
44
+ @task_mock.should_receive(:server).with('1.2.3.4', :instances)
45
+ @task_mock.should_receive(:server).with('4.3.2.1', :instances)
46
+ end
47
+
48
+ it "should return false when Capistrano command error" do
49
+ @ssh = SimpleDeploy::Stack::SSH.new @options
50
+
51
+ @task_mock.should_receive(:load).with({ :string=>"task :execute do\n sudo 'a_bad_command'\n end" })
52
+ @task_mock.should_receive(:execute).and_raise Capistrano::CommandError.new 'command error'
53
+
54
+ @ssh.execute(:sudo => true, :command => 'a_bad_command').should be_false
55
+ end
56
+
57
+ it "should return false when Capistrano connection error" do
58
+ @ssh = SimpleDeploy::Stack::SSH.new @options
59
+
60
+ @task_mock.stub :logger => @task_logger_mock,
61
+ :variables => @ssh_options
62
+ @task_mock.should_receive(:load).with({ :string=>"task :execute do\n sudo 'uname'\n end" })
63
+ @task_mock.should_receive(:execute).and_raise Capistrano::ConnectionError.new 'connection error'
64
+
65
+ @ssh.execute(:sudo => true, :command => 'uname').should be_false
66
+ end
67
+
68
+ it "should return false when Capistrano generic error" do
69
+ @ssh = SimpleDeploy::Stack::SSH.new @options
70
+
71
+ @task_mock.should_receive(:load).with({ :string=>"task :execute do\n sudo 'uname'\n end" })
72
+ @task_mock.should_receive(:execute).and_raise Capistrano::Error.new 'generic error'
73
+
74
+ @ssh.execute(:sudo => true, :command => 'uname').should be_false
75
+ end
76
+ end
30
77
  end
31
78
 
32
79
  context "when successful" do
33
80
  before do
34
- options = { :config => @config_mock,
35
- :instances => ['1.2.3.4', '4.3.2.1'],
36
- :environment => 'test-env',
37
- :ssh_user => 'user',
38
- :ssh_key => 'key',
39
- :stack => @stack_mock,
40
- :name => 'test-stack' }
41
- @ssh = SimpleDeploy::Stack::SSH.new options
81
+ @ssh = SimpleDeploy::Stack::SSH.new @options
42
82
  end
43
-
83
+
44
84
  describe "when execute called" do
45
85
  before do
46
- task_logger_mock = mock 'task_logger'
47
- @ssh_options = Hash.new
48
86
  Capistrano::Configuration.should_receive(:new).
49
- with(:output => @logger_stub).
50
- and_return @task_mock
51
- @task_mock.stub :logger => task_logger_mock,
52
- :variables => @ssh_options
53
- task_logger_mock.should_receive(:level=).with(3)
87
+ with(:output => @logger_stub).
88
+ and_return @task_mock
89
+
90
+ @task_logger_mock.should_receive(:level=).with(3)
54
91
  @task_mock.should_receive(:set).with :user, 'user'
55
92
  @task_mock.should_receive(:server).with('1.2.3.4', :instances)
56
93
  @task_mock.should_receive(:server).with('4.3.2.1', :instances)
57
94
  end
58
95
 
59
- describe "when succesful" do
96
+ describe "when successful" do
60
97
  it "should execute a task with sudo" do
61
- @task_mock.should_receive(:load).with({:string=>"task :execute do\n sudo 'uname'\n end"})
98
+ @task_mock.should_receive(:load).with({ :string=>"task :execute do\n sudo 'uname'\n end" })
62
99
  @task_mock.should_receive(:execute).and_return true
100
+
63
101
  @ssh.execute(:sudo => true,
64
102
  :command => 'uname').should be_true
65
103
  end
66
104
 
67
105
  it "should execute a task as the calling user " do
68
- @task_mock.should_receive(:load).with({:string=>"task :execute do\n run 'uname'\n end"})
106
+ @task_mock.should_receive(:load).with({ :string=>"task :execute do\n run 'uname'\n end" })
69
107
  @task_mock.should_receive(:execute).and_return true
108
+
70
109
  @ssh.execute(:sudo => false,
71
110
  :command => 'uname').should be_true
72
111
  end
73
- end
74
-
75
- after do
76
- @ssh_options.should == { :ssh_options => {
77
- :keys => 'key', :paranoid => false
78
- }
79
- }
112
+
113
+ it "sets the ssh options" do
114
+ @task_mock.stub(:load)
115
+ @task_mock.stub(:execute).and_return(true)
116
+ @ssh.execute :sudo => false, :command => 'uname'
117
+
118
+ @ssh_options.should == { :ssh_options => { :keys => 'key',
119
+ :paranoid => false } }
120
+ end
80
121
  end
81
122
  end
82
123
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::Template do
4
+ before do
5
+ @contents = {
6
+ "Parameters" => {
7
+ "Test1" => {
8
+ "Type" => "String",
9
+ "Description" => "Test Param #1"
10
+ },
11
+ "Test2" => {
12
+ "Type" => "String",
13
+ "Description" => "Test Param #2"
14
+ }
15
+ }
16
+ }.to_json
17
+ IO.should_receive(:read).with('/tmp/file').and_return @contents
18
+ @template = SimpleDeploy::Template.new :file => '/tmp/file'
19
+ end
20
+
21
+ it "should return the parameters for a given template" do
22
+ @template.parameters.should == ["Test1", "Test2"]
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-15 00:00:00.000000000 Z
12
+ date: 2013-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &70295198764320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
24
+ version_requirements: *70295198764320
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: rspec
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &70295198763260 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ~>
@@ -37,76 +32,51 @@ dependencies:
37
32
  version: 2.11.0
38
33
  type: :development
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 2.11.0
35
+ version_requirements: *70295198763260
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: capistrano
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &70295198762340 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
- - - '='
41
+ - - =
52
42
  - !ruby/object:Gem::Version
53
43
  version: 2.13.5
54
44
  type: :runtime
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - '='
60
- - !ruby/object:Gem::Version
61
- version: 2.13.5
46
+ version_requirements: *70295198762340
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: stackster
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &70295198760620 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
- - - '='
52
+ - - =
68
53
  - !ruby/object:Gem::Version
69
54
  version: 0.4.2
70
55
  type: :runtime
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - '='
76
- - !ruby/object:Gem::Version
77
- version: 0.4.2
57
+ version_requirements: *70295198760620
78
58
  - !ruby/object:Gem::Dependency
79
59
  name: tinder
80
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &70295198759920 !ruby/object:Gem::Requirement
81
61
  none: false
82
62
  requirements:
83
- - - '='
63
+ - - =
84
64
  - !ruby/object:Gem::Version
85
65
  version: 1.8.0
86
66
  type: :runtime
87
67
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - '='
92
- - !ruby/object:Gem::Version
93
- version: 1.8.0
68
+ version_requirements: *70295198759920
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: trollop
96
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &70295198758960 !ruby/object:Gem::Requirement
97
72
  none: false
98
73
  requirements:
99
- - - '='
74
+ - - =
100
75
  - !ruby/object:Gem::Version
101
76
  version: '2.0'
102
77
  type: :runtime
103
78
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - '='
108
- - !ruby/object:Gem::Version
109
- version: '2.0'
79
+ version_requirements: *70295198758960
110
80
  description: Opinionated gem for Managing AWS Cloud Formation stacks and deploying
111
81
  updates to Instances.
112
82
  email:
@@ -151,37 +121,46 @@ files:
151
121
  - lib/simple_deploy/env.rb
152
122
  - lib/simple_deploy/exceptions.rb
153
123
  - lib/simple_deploy/logger.rb
124
+ - lib/simple_deploy/misc.rb
125
+ - lib/simple_deploy/misc/attribute_merger.rb
154
126
  - lib/simple_deploy/notifier.rb
155
127
  - lib/simple_deploy/notifier/campfire.rb
156
128
  - lib/simple_deploy/stack.rb
157
129
  - lib/simple_deploy/stack/deployment.rb
158
130
  - lib/simple_deploy/stack/deployment/status.rb
159
131
  - lib/simple_deploy/stack/execute.rb
132
+ - lib/simple_deploy/stack/output_mapper.rb
160
133
  - lib/simple_deploy/stack/ssh.rb
161
134
  - lib/simple_deploy/stack/stack_attribute_formater.rb
135
+ - lib/simple_deploy/template.rb
162
136
  - lib/simple_deploy/version.rb
163
137
  - simple_deploy.gemspec
164
138
  - spec/artifact_spec.rb
165
139
  - spec/backoff_spec.rb
166
140
  - spec/cli/attributes_spec.rb
167
141
  - spec/cli/clone_spec.rb
142
+ - spec/cli/create_spec.rb
168
143
  - spec/cli/deploy_spec.rb
169
144
  - spec/cli/destroy_spec.rb
145
+ - spec/cli/outputs_spec.rb
170
146
  - spec/cli/protect_spec.rb
171
147
  - spec/cli/shared_spec.rb
172
148
  - spec/cli/update_spec.rb
173
149
  - spec/cli_spec.rb
174
150
  - spec/config_spec.rb
175
151
  - spec/logger_spec.rb
152
+ - spec/misc/attribute_merger_spec.rb
176
153
  - spec/notifier/campfire_spec.rb
177
154
  - spec/notifier_spec.rb
178
155
  - spec/spec_helper.rb
179
156
  - spec/stack/deployment/status_spec.rb
180
157
  - spec/stack/deployment_spec.rb
181
158
  - spec/stack/execute_spec.rb
159
+ - spec/stack/output_mapper_spec.rb
182
160
  - spec/stack/ssh_spec.rb
183
161
  - spec/stack/stack_attribute_formater_spec.rb
184
162
  - spec/stack_spec.rb
163
+ - spec/template_spec.rb
185
164
  homepage: ''
186
165
  licenses: []
187
166
  post_install_message:
@@ -196,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
175
  version: '0'
197
176
  segments:
198
177
  - 0
199
- hash: -4528929630264236802
178
+ hash: 1762969189670717891
200
179
  required_rubygems_version: !ruby/object:Gem::Requirement
201
180
  none: false
202
181
  requirements:
@@ -205,10 +184,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
184
  version: '0'
206
185
  segments:
207
186
  - 0
208
- hash: -4528929630264236802
187
+ hash: 1762969189670717891
209
188
  requirements: []
210
189
  rubyforge_project: simple_deploy
211
- rubygems_version: 1.8.24
190
+ rubygems_version: 1.8.16
212
191
  signing_key:
213
192
  specification_version: 3
214
193
  summary: Opinionated gem for AWS resource management.
@@ -217,20 +196,25 @@ test_files:
217
196
  - spec/backoff_spec.rb
218
197
  - spec/cli/attributes_spec.rb
219
198
  - spec/cli/clone_spec.rb
199
+ - spec/cli/create_spec.rb
220
200
  - spec/cli/deploy_spec.rb
221
201
  - spec/cli/destroy_spec.rb
202
+ - spec/cli/outputs_spec.rb
222
203
  - spec/cli/protect_spec.rb
223
204
  - spec/cli/shared_spec.rb
224
205
  - spec/cli/update_spec.rb
225
206
  - spec/cli_spec.rb
226
207
  - spec/config_spec.rb
227
208
  - spec/logger_spec.rb
209
+ - spec/misc/attribute_merger_spec.rb
228
210
  - spec/notifier/campfire_spec.rb
229
211
  - spec/notifier_spec.rb
230
212
  - spec/spec_helper.rb
231
213
  - spec/stack/deployment/status_spec.rb
232
214
  - spec/stack/deployment_spec.rb
233
215
  - spec/stack/execute_spec.rb
216
+ - spec/stack/output_mapper_spec.rb
234
217
  - spec/stack/ssh_spec.rb
235
218
  - spec/stack/stack_attribute_formater_spec.rb
236
219
  - spec/stack_spec.rb
220
+ - spec/template_spec.rb