simple_deploy 0.6.7 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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