stackster 0.2.7 → 0.2.8

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.2.8
2
+
3
+ * Added stack status class
4
+ * Update waits for in progress stacks to complete
5
+ * Added -l switch to set log level
6
+
1
7
  ## v0.2.7
2
8
 
3
9
  * Changed some debug levels
@@ -6,9 +6,9 @@ module Stackster
6
6
 
7
7
  def initialize(args)
8
8
  c = args[:config]
9
- @connect = Fog::AWS::SimpleDB.new :aws_access_key_id => c.access_key,
9
+ @connect = Fog::AWS::SimpleDB.new :aws_access_key_id => c.access_key,
10
10
  :aws_secret_access_key => c.secret_key,
11
- :region => c.region
11
+ :region => c.region
12
12
  end
13
13
 
14
14
  def domains
data/lib/stackster/cli.rb CHANGED
@@ -22,6 +22,8 @@ EOS
22
22
  opt :help, "Display Help"
23
23
  opt :attributes, "= seperated attribute and it's value", :type => :string,
24
24
  :multi => true
25
+ opt :log_level, "Log level: debug, info, warn, error", :type => :string,
26
+ :default => 'info'
25
27
  opt :name, "Stack name to manage", :type => :string
26
28
  opt :template, "Path to the template file", :type => :string
27
29
  end
@@ -31,24 +33,21 @@ EOS
31
33
  case @cmd
32
34
  when 'create', 'destroy', 'delete', 'list', 'update', 'show'
33
35
  @s = Stack.new :name => @opts[:name],
34
- :config => nil
36
+ :logger => StacksterLogger.new(:log_level => @opts[:log_level])
35
37
  end
36
38
 
37
39
  case @cmd
38
40
  when 'create'
39
41
  @s.create :attributes => attributes,
40
42
  :template => @opts[:template]
41
- puts "#{@opts[:name]} created."
42
43
  when 'update'
43
44
  @s.update :attributes => attributes
44
- puts "#{@opts[:name]} updated."
45
45
  when 'destroy', 'delete'
46
46
  @s.destroy
47
- puts "#{@opts[:name]} destroyed."
48
47
  when 'show'
49
48
  puts @s.display.to_yaml
50
49
  when 'list'
51
- puts StackLister.new.all
50
+ puts StackLister.new.all.sort
52
51
  else
53
52
  puts "Unkown command '#{@cmd}'"
54
53
  end
@@ -24,11 +24,17 @@ module Stackster
24
24
  end
25
25
 
26
26
  def save
27
- attributes.merge!('Name' => name)
28
- attributes.each_pair do |k,v|
29
- @logger.debug "Setting attribute #{k}=#{v}"
27
+ set_name_attribute
28
+
29
+ attributes.each_pair do |key,value|
30
+ @logger.debug "Setting attribute #{key}=#{value}"
30
31
  end
31
- sdb_connect.put_attributes('stacks', name, attributes, { :replace => attributes.keys })
32
+
33
+ sdb_connect.put_attributes('stacks',
34
+ name,
35
+ attributes,
36
+ :replace => attributes.keys )
37
+
32
38
  @logger.debug "Save to SimpleDB successful."
33
39
  end
34
40
 
@@ -39,9 +45,13 @@ module Stackster
39
45
 
40
46
  private
41
47
 
48
+ def set_name_attribute
49
+ attributes.merge!('Name' => name)
50
+ end
51
+
42
52
  def get_attributes
43
53
  u = {}
44
- attrs = sdb_connect.select("select * from stacks where itemName() = '#{name}'")
54
+ attrs = sdb_connect.select "select * from stacks where itemName() = '#{name}'"
45
55
  if attrs[name]
46
56
  attrs[name].each_pair { |k, v| u[k] = v.first }
47
57
  end
@@ -1,29 +1,32 @@
1
1
  module Stackster
2
2
  class StacksterLogger
3
3
 
4
- def initialize(args = {})
5
- @logger = args[:logger] ||= Logger.new(STDOUT)
4
+ require 'forwardable'
6
5
 
7
- unless args[:logger]
8
- @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
9
- @logger.formatter = proc do |severity, datetime, progname, msg|
10
- "#{datetime}: #{msg}\n"
11
- end
12
- end
6
+ extend Forwardable
13
7
 
14
- @logger
15
- end
8
+ def_delegators :@logger, :debug, :error, :info, :warn
16
9
 
17
- def debug(msg)
18
- @logger.debug msg
10
+ def initialize(args = {})
11
+ @log_level = args[:log_level] ||= 'info'
12
+ @logger = args[:logger] ||= new_logger(args)
19
13
  end
20
14
 
21
- def info(msg)
22
- @logger.info msg
15
+ private
16
+
17
+ def new_logger(args)
18
+ Logger.new(STDOUT).tap do |l|
19
+ l.datetime_format = '%Y-%m-%dT%H:%M:%S%z'
20
+ l.formatter = proc do |severity, datetime, progname, msg|
21
+ "#{datetime} #{severity} : #{msg}\n"
22
+ end
23
+ l.level = logger_level
24
+ end
23
25
  end
24
26
 
25
- def error(msg)
26
- @logger.error msg
27
+ def logger_level
28
+ Logger.const_get @log_level.upcase
27
29
  end
30
+
28
31
  end
29
32
  end
@@ -17,17 +17,21 @@ module Stackster
17
17
  update
18
18
  else
19
19
  @logger.debug "No Cloud Formation parameters require updating."
20
- return false
20
+ false
21
21
  end
22
22
  end
23
23
 
24
24
  private
25
25
 
26
26
  def update
27
- @logger.info "Updating Cloud Formation stack #{@name}."
28
- cloud_formation.update :name => @name,
29
- :parameters => read_parameters_from_entry_attributes,
30
- :template => @template_body
27
+ if status.wait_for_stable
28
+ @logger.info "Updating Cloud Formation stack #{@name}."
29
+ cloud_formation.update :name => @name,
30
+ :parameters => read_parameters_from_entry_attributes,
31
+ :template => @template_body
32
+ else
33
+ raise "#{@name} did not reach a stable state."
34
+ end
31
35
  end
32
36
 
33
37
  def parameter_updated?(attributes)
@@ -56,5 +60,10 @@ module Stackster
56
60
  @cloud_formation ||= AWS::CloudFormation.new :config => @config
57
61
  end
58
62
 
63
+ def status
64
+ @status ||= Status.new :name => @name,
65
+ :config => @config
66
+ end
67
+
59
68
  end
60
69
  end
@@ -0,0 +1,55 @@
1
+ module Stackster
2
+ class Status
3
+
4
+ def initialize(args)
5
+ @name = args[:name]
6
+ @config = args[:config]
7
+ @logger = @config.logger
8
+ end
9
+
10
+ def complete?
11
+ /_COMPLETE$/ === current
12
+ end
13
+
14
+ def failed?
15
+ /_FAILED$/ === current
16
+ end
17
+
18
+ def cleanup_in_progress?
19
+ /_CLEANUP_IN_PROGRESS$/ === current
20
+ end
21
+
22
+ def in_progress?
23
+ /_IN_PROGRESS$/ === current && !cleanup_in_progress?
24
+ end
25
+
26
+ def create_failed?
27
+ 'CREATE_FAILED' == current
28
+ end
29
+
30
+ def stable?
31
+ (complete? || failed?) && (! create_failed?)
32
+ end
33
+
34
+ def wait_for_stable(count=25)
35
+ 1.upto(count).each do |c|
36
+ break if stable?
37
+ @logger.info ("#{@name} not stable (#{current}). Sleeping #{c * c} second(s).")
38
+ Kernel.sleep (c * c)
39
+ end
40
+ stable?
41
+ end
42
+
43
+ private
44
+
45
+ def current
46
+ stack_reader.status
47
+ end
48
+
49
+ def stack_reader
50
+ @stack_reader ||= StackReader.new :name => @name,
51
+ :config => @config
52
+ end
53
+
54
+ end
55
+ end
@@ -4,6 +4,7 @@ require 'stackster/stack/stack_destroyer'
4
4
  require 'stackster/stack/stack_reader'
5
5
  require 'stackster/stack/stack_formater'
6
6
  require 'stackster/stack/stack_lister'
7
+ require 'stackster/stack/status'
7
8
 
8
9
  module Stackster
9
10
  class Stack
@@ -112,5 +113,10 @@ module Stackster
112
113
  :config => @config
113
114
  end
114
115
 
116
+ def status
117
+ @status ||= Status.new :name => @name,
118
+ :config => @config
119
+ end
120
+
115
121
  end
116
122
  end
@@ -1,3 +1,3 @@
1
1
  module Stackster
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
3
3
  end
data/spec/logger_spec.rb CHANGED
@@ -13,6 +13,9 @@ describe Stackster do
13
13
  logger_mock = mock 'logger'
14
14
  Logger.should_receive(:new).with(STDOUT).and_return logger_mock
15
15
  logger_mock.should_receive(:info).with 'a message'
16
+ logger_mock.should_receive(:datetime_format=).with '%Y-%m-%dT%H:%M:%S%z'
17
+ logger_mock.should_receive(:formatter=)
18
+ logger_mock.should_receive(:level=).with 1
16
19
  logger = Stackster::StacksterLogger.new
17
20
  logger.info 'a message'
18
21
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+
2
2
  require 'json'
3
3
 
4
4
  describe Stackster do
@@ -18,11 +18,12 @@ describe Stackster do
18
18
  }'
19
19
  end
20
20
 
21
- it "should update the stack when parameters change" do
21
+ it "should update the stack when parameters change and stack is stable" do
22
22
  attributes = { "param1" => "value1", "param3" => "value3" }
23
23
  config_mock = mock 'config mock'
24
24
  logger_mock = mock 'logger mock'
25
25
  entry_mock = mock 'entry mock'
26
+ status_mock = mock 'status mock'
26
27
  cloud_formation_mock = mock 'cloud formation mock'
27
28
  Stackster::AWS::CloudFormation.should_receive(:new).
28
29
  with(:config => config_mock).
@@ -36,6 +37,11 @@ describe Stackster do
36
37
  config_mock.should_receive(:logger).and_return(logger_mock)
37
38
  logger_mock.should_receive(:debug).exactly(1).times
38
39
  logger_mock.should_receive(:info).exactly(1).times
40
+ Stackster::Status.should_receive(:new).
41
+ with(:name => 'test-stack',
42
+ :config => config_mock).
43
+ and_return status_mock
44
+ status_mock.should_receive(:wait_for_stable).and_return true
39
45
  stack_updater = Stackster::StackUpdater.new :name => 'test-stack',
40
46
  :template_body => @template_body,
41
47
  :entry => entry_mock,
@@ -45,6 +51,31 @@ describe Stackster do
45
51
  should == true
46
52
  end
47
53
 
54
+ it "should raise an error when parameters change and stack is not stable" do
55
+ attributes = { "param1" => "value1", "param3" => "value3" }
56
+ config_mock = mock 'config mock'
57
+ logger_mock = mock 'logger mock'
58
+ entry_mock = mock 'entry mock'
59
+ status_mock = mock 'status mock'
60
+ cloud_formation_mock = mock 'cloud formation mock'
61
+ Stackster::AWS::CloudFormation.should_receive(:new).
62
+ exactly(0).times
63
+ config_mock.should_receive(:logger).and_return(logger_mock)
64
+ logger_mock.should_receive(:debug).exactly(1).times
65
+ Stackster::Status.should_receive(:new).
66
+ with(:name => 'test-stack',
67
+ :config => config_mock).
68
+ and_return status_mock
69
+ status_mock.should_receive(:wait_for_stable).and_return false
70
+ stack_updater = Stackster::StackUpdater.new :name => 'test-stack',
71
+ :template_body => @template_body,
72
+ :entry => entry_mock,
73
+ :config => config_mock
74
+
75
+ lambda {stack_updater.update_stack_if_parameters_changed( [ { 'param1' => 'new-value' } ] ) }.
76
+ should raise_error
77
+ end
78
+
48
79
  it "should not update the stack when parameters don't change" do
49
80
  attributes = { "param3" => "value3" }
50
81
  config_mock = mock 'config mock'
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stackster do
4
+
5
+ before do
6
+ @config_mock = mock 'config mock'
7
+ @logger_mock = mock 'logger mock'
8
+ @stack_reader_mock = mock 'stack reader mock'
9
+ Stackster::StackReader.should_receive(:new).
10
+ and_return @stack_reader_mock
11
+ @config_mock.should_receive(:logger).and_return @logger_mock
12
+ @status = Stackster::Status.new :name => 'test-stack',
13
+ :config => @config_mock
14
+ end
15
+
16
+ it "should return true if the stack is in complete state" do
17
+ @stack_reader_mock.should_receive(:status).
18
+ and_return 'UPDATE_COMPLETE'
19
+ @status.complete?.should == true
20
+ end
21
+
22
+ it "should return false if the stack is not in complete state" do
23
+ @stack_reader_mock.should_receive(:status).
24
+ and_return 'UPDATE_IN_PROGRESS'
25
+ @status.complete?.should == false
26
+ end
27
+
28
+ it "should return true if the stack is in a failed state" do
29
+ @stack_reader_mock.should_receive(:status).
30
+ and_return 'DELETE_FAILED'
31
+ @status.failed?.should == true
32
+ end
33
+
34
+ it "should return false if the stack is not in a failed state" do
35
+ @stack_reader_mock.should_receive(:status).
36
+ and_return 'UPDATE_IN_PROGRESS'
37
+ @status.failed?.should == false
38
+ end
39
+
40
+ it "should return true if the stack is in an in_progress state" do
41
+ @stack_reader_mock.should_receive(:status).exactly(2).times.
42
+ and_return 'UPDATE_IN_PROGRESS'
43
+ @status.in_progress?.should == true
44
+ end
45
+
46
+ it "should return false if the stack is not in an in_progress state" do
47
+ @stack_reader_mock.should_receive(:status).exactly(2).times.
48
+ and_return 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS'
49
+ @status.in_progress?.should == false
50
+ end
51
+
52
+ it "should return true if the stack is cleaning up" do
53
+ @stack_reader_mock.should_receive(:status).
54
+ and_return 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS'
55
+ @status.cleanup_in_progress?.should == true
56
+ end
57
+
58
+ it "should return false if the stack is not in a cleaning up state" do
59
+ @stack_reader_mock.should_receive(:status).
60
+ and_return 'UPDATE_IN_PROGRESS'
61
+ @status.cleanup_in_progress?.should == false
62
+ end
63
+
64
+ it "should return true if the stack is in a complete state" do
65
+ @stack_reader_mock.should_receive(:status).exactly(2).times.
66
+ and_return 'UPDATE_COMPLETE'
67
+ @status.stable?.should == true
68
+ end
69
+
70
+ it "should return true if the stack is in a failed state" do
71
+ @stack_reader_mock.should_receive(:status).exactly(3).times.
72
+ and_return 'UPDATE_FAILED'
73
+ @status.stable?.should == true
74
+ end
75
+
76
+ it "should return true if the stack is in an in progress state" do
77
+ @stack_reader_mock.should_receive(:status).exactly(2).times.
78
+ and_return 'IN_PROGRESS'
79
+ @status.stable?.should == false
80
+ end
81
+
82
+ it "should return false if the stack creation failed" do
83
+ @stack_reader_mock.should_receive(:status).exactly(3).times.
84
+ and_return 'CREATE_FAILED'
85
+ @status.stable?.should == false
86
+ end
87
+
88
+ it "should return true when the stack is in a stable state" do
89
+ @stack_reader_mock.should_receive(:status).exactly(4).times.
90
+ and_return 'CREATE_COMPLETE'
91
+ @status.wait_for_stable.should == true
92
+ end
93
+
94
+ it "should sleep 2 times and return false when the stack is in an unstable state" do
95
+ Kernel.stub!(:sleep)
96
+ Kernel.should_receive(:sleep).with(1)
97
+ Kernel.should_receive(:sleep).with(4)
98
+
99
+ @stack_reader_mock.should_receive(:status).exactly(11).times.
100
+ and_return 'CREATE_FAILED'
101
+ @logger_mock.should_receive(:info).exactly(2).times
102
+ @status.wait_for_stable(2).should == false
103
+ end
104
+
105
+ end
data/spec/stack_spec.rb CHANGED
@@ -41,13 +41,15 @@ describe Stackster do
41
41
 
42
42
  it "should create a new stack" do
43
43
  stack_creater_mock = mock 'stack creater'
44
- @entry_mock.should_receive(:set_attributes).with({ 'test-attr' => 'test-value' })
44
+ @entry_mock.should_receive(:set_attributes).
45
+ with({ 'test-attr' => 'test-value' })
45
46
  @entry_mock.should_receive(:save)
46
- Stackster::StackCreater.should_receive(:new).with(:name => 'test-stack',
47
- :entry => @entry_mock,
48
- :template_file => 'template_file',
49
- :config => @config_mock).
50
- and_return stack_creater_mock
47
+ Stackster::StackCreater.should_receive(:new).
48
+ with(:name => 'test-stack',
49
+ :entry => @entry_mock,
50
+ :template_file => 'template_file',
51
+ :config => @config_mock).
52
+ and_return stack_creater_mock
51
53
  stack_creater_mock.should_receive(:create)
52
54
 
53
55
  @stack.create :template => 'template_file',
@@ -68,15 +70,18 @@ describe Stackster do
68
70
  @entry_mock.should_receive(:save)
69
71
  stack_reader_mock.should_receive(:template).and_return('template-body-json')
70
72
 
71
- Stackster::StackReader.should_receive(:new).with(:name => 'test-stack',
72
- :config => @config_mock).
73
- and_return stack_reader_mock
74
- Stackster::StackUpdater.should_receive(:new).with(:name => 'test-stack',
75
- :entry => @entry_mock,
76
- :template_body => 'template-body-json',
77
- :config => @config_mock).
78
- and_return stack_updater_mock
79
- stack_updater_mock.should_receive(:update_stack_if_parameters_changed)
73
+ Stackster::StackReader.should_receive(:new).
74
+ with(:name => 'test-stack',
75
+ :config => @config_mock).
76
+ and_return stack_reader_mock
77
+ Stackster::StackUpdater.should_receive(:new).
78
+ with(:name => 'test-stack',
79
+ :entry => @entry_mock,
80
+ :template_body => 'template-body-json',
81
+ :config => @config_mock).
82
+ and_return stack_updater_mock
83
+ stack_updater_mock.should_receive(:update_stack_if_parameters_changed).
84
+ and_return true
80
85
  @stack.update :attributes => { 'update' => 'test-attrs' }
81
86
  end
82
87
 
@@ -86,9 +91,10 @@ describe Stackster do
86
91
  context "when destroying a stack" do
87
92
  it "should destroy a stack" do
88
93
  stack_destroyer_mock = mock 'stack destroyer'
89
- Stackster::StackDestroyer.should_receive(:new).with(:name => 'test-stack',
90
- :config => @config_mock).
91
- and_return stack_destroyer_mock
94
+ Stackster::StackDestroyer.should_receive(:new).
95
+ with(:name => 'test-stack',
96
+ :config => @config_mock).
97
+ and_return stack_destroyer_mock
92
98
  stack_destroyer_mock.should_receive(:destroy)
93
99
  @entry_mock.should_receive(:delete_attributes)
94
100
  @stack.destroy
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
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: 2012-07-19 00:00:00.000000000 Z
12
+ date: 2012-07-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70336360579600 !ruby/object:Gem::Requirement
16
+ requirement: &70204471061060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70336360579600
24
+ version_requirements: *70204471061060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: fog
27
- requirement: &70336360578840 !ruby/object:Gem::Requirement
27
+ requirement: &70204471059380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70336360578840
35
+ version_requirements: *70204471059380
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: logger
38
- requirement: &70336360578160 !ruby/object:Gem::Requirement
38
+ requirement: &70204471055480 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70336360578160
46
+ version_requirements: *70204471055480
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: trollop
49
- requirement: &70336360576700 !ruby/object:Gem::Requirement
49
+ requirement: &70204471053160 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70336360576700
57
+ version_requirements: *70204471053160
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: xml-simple
60
- requirement: &70336360574960 !ruby/object:Gem::Requirement
60
+ requirement: &70204471051140 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70336360574960
68
+ version_requirements: *70204471051140
69
69
  description: Thats what I do
70
70
  email:
71
71
  - brett@weav.net
@@ -101,6 +101,7 @@ files:
101
101
  - lib/stackster/stack/stack_lister.rb
102
102
  - lib/stackster/stack/stack_reader.rb
103
103
  - lib/stackster/stack/stack_updater.rb
104
+ - lib/stackster/stack/status.rb
104
105
  - lib/stackster/version.rb
105
106
  - script/ci_setup
106
107
  - spec/aws/cloud_formation/error_spec.rb
@@ -119,6 +120,7 @@ files:
119
120
  - spec/stack/stack_lister_spec.rb
120
121
  - spec/stack/stack_reader_spec.rb
121
122
  - spec/stack/stack_updater_spec.rb
123
+ - spec/stack/status_spec.rb
122
124
  - spec/stack_spec.rb
123
125
  - stackster.gemspec
124
126
  homepage: ''
@@ -135,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
137
  version: '0'
136
138
  segments:
137
139
  - 0
138
- hash: -121993254634425492
140
+ hash: -1998118593165875979
139
141
  required_rubygems_version: !ruby/object:Gem::Requirement
140
142
  none: false
141
143
  requirements:
@@ -144,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
146
  version: '0'
145
147
  segments:
146
148
  - 0
147
- hash: -121993254634425492
149
+ hash: -1998118593165875979
148
150
  requirements: []
149
151
  rubyforge_project: stackster
150
152
  rubygems_version: 1.8.16
@@ -168,4 +170,5 @@ test_files:
168
170
  - spec/stack/stack_lister_spec.rb
169
171
  - spec/stack/stack_reader_spec.rb
170
172
  - spec/stack/stack_updater_spec.rb
173
+ - spec/stack/status_spec.rb
171
174
  - spec/stack_spec.rb