stackster 0.2.9 → 0.3.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/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .rvmrc
6
+ coverage
7
+ *.swp
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ ## v0.3.0
2
+
3
+ * Now uses consistent reads
4
+ * Increased the testing coverage
5
+
1
6
  ## v0.2.9
2
7
 
3
8
  * Bug fix in private method.
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Run specs'
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = %w(--color)
8
+ end
@@ -28,7 +28,7 @@ module Stackster
28
28
  end
29
29
 
30
30
  def select(query)
31
- @connect.select(query).body['Items']
31
+ @connect.select(query, 'ConsistentRead' => true).body['Items']
32
32
  end
33
33
 
34
34
  def delete(domain, key)
@@ -24,7 +24,7 @@ module Stackster
24
24
  end
25
25
 
26
26
  def save
27
- set_name_attribute
27
+ set_default_attributes
28
28
 
29
29
  attributes.each_pair do |key,value|
30
30
  @logger.debug "Setting attribute #{key}=#{value}"
@@ -45,8 +45,9 @@ module Stackster
45
45
 
46
46
  private
47
47
 
48
- def set_name_attribute
48
+ def set_default_attributes
49
49
  attributes.merge!('Name' => name)
50
+ attributes.merge!('CreatedAt' => Time.now.utc)
50
51
  end
51
52
 
52
53
  def get_attributes
@@ -5,9 +5,6 @@ module Stackster
5
5
  @config = args[:config]
6
6
  end
7
7
 
8
- # Data structure is return deffernelty for class
9
- # ToDo - Add support for classic
10
- # Currently only supports VPC
11
8
  def list_stack_instances(stack_name)
12
9
  h = []
13
10
  describe_instances.each do |instance|
@@ -50,10 +50,6 @@ module Stackster
50
50
  stack_reader.attributes
51
51
  end
52
52
 
53
- def show
54
- stack_reader.show
55
- end
56
-
57
53
  def outputs
58
54
  stack_reader.outputs
59
55
  end
@@ -1,3 +1,3 @@
1
1
  module Stackster
2
- VERSION = "0.2.9"
2
+ VERSION = "0.3.0"
3
3
  end
data/script/ci_setup CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  # Source RVM profile and set ruby / gemset
4
4
  . /etc/profile
5
- rvm use "1.9.3-p125@stackster" --create
5
+
6
+ # Exit with error if any command returns non zero
7
+ set -e
6
8
 
7
9
  # Bundle gems
10
+ rvm use "1.9.3-p125@stackster" --create
8
11
  bundle
9
12
 
10
- # Create blank deployment config
11
- touch $HOME/.stackster.yml
12
-
13
13
  # Run spec tests
14
- rspec spec
14
+ rake spec
@@ -1,9 +1,39 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ #@logger_stub = stub 'logger stub', :info => 'true', :warn => 'true'
6
+ @logger_mock = mock 'Logger'
7
+ @config_stub = stub 'Config', :logger => @logger_mock, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
4
8
 
5
- ['error'].each do |t|
6
- it "should test #{t}"
9
+ @exception_stub1 = stub 'Excon::Response'
10
+ @exception_stub1.stub(:response).and_return(@exception_stub1)
11
+ @exception_stub1.stub(:body).and_return('<opt><Error><Message>No updates are to be performed.</Message></Error></opt>')
12
+
13
+ @exception_stub2 = stub 'Excon::Response'
14
+ @exception_stub2.stub(:response).and_return(@exception_stub2)
15
+ @exception_stub2.stub(:body).and_return('<opt><Error><Message>Oops.</Message></Error></opt>')
7
16
  end
8
17
 
18
+ describe 'process' do
19
+ it 'should process no update messages' do
20
+ @logger_mock.should_receive(:info).with('No updates are to be performed.')
21
+
22
+ error = Stackster::AWS::CloudFormation::Error.new :exception => @exception_stub1, :config => @config_stub
23
+ error.process
24
+ end
25
+
26
+ it 'should process general messages' do
27
+ @logger_mock.should_receive(:error).with('Oops.')
28
+
29
+ error = Stackster::AWS::CloudFormation::Error.new :exception => @exception_stub2, :config => @config_stub
30
+
31
+ begin
32
+ error.process
33
+ fail 'should have exited'
34
+ rescue SystemExit => e
35
+ e.status.should == 1
36
+ end
37
+ end
38
+ end
9
39
  end
@@ -1,10 +1,174 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true'
6
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
7
+ @error_stub = stub 'Error', :process => 'Processed Error'
8
+ @response_stub = stub 'Excon::Response', :body => {
9
+ 'Stacks' => [{'StackStatus' => 'green', 'Outputs' => [{'key' => 'value'}]}],
10
+ 'StackResources' => [{'StackName' => 'my_stack'}],
11
+ 'StackEvents' => ['event1', 'event2'],
12
+ 'TemplateBody' => '{EIP: "string"}'
13
+ }
4
14
 
5
- ['create', 'update', 'destroy', 'describe_stack', 'stack_resources',
6
- 'stack_events', 'stack_status', 'stack_outputs', 'template'].each do |t|
7
- it "should test #{t}"
15
+ @cf_mock = mock 'CloudFormation'
16
+ Fog::AWS::CloudFormation.stub(:new).and_return(@cf_mock)
17
+
18
+ @args = {
19
+ :parameters => { 'parameter1' => 'my_param' },
20
+ :name => 'my_stack',
21
+ :template => 'my_template'
22
+ }
23
+
24
+ @exception = Exception.new('Failed')
25
+
26
+ @cf = Stackster::AWS::CloudFormation.new(:config => @config_stub)
27
+ end
28
+
29
+ describe "create" do
30
+ it "should create the stack on Cloud Formation" do
31
+ @cf_mock.should_receive(:create_stack).with('my_stack',
32
+ { 'Capabilities' => ['CAPABILITY_IAM'],
33
+ 'TemplateBody' => 'my_template',
34
+ 'Parameters' => { 'parameter1' => 'my_param' }
35
+ })
36
+
37
+ @cf.create(@args)
38
+ end
39
+
40
+ it "should trap exceptions" do
41
+ @cf_mock.should_receive(:create_stack).with('my_stack',
42
+ { 'Capabilities' => ['CAPABILITY_IAM'],
43
+ 'TemplateBody' => 'my_template',
44
+ 'Parameters' => { 'parameter1' => 'my_param' }
45
+ }).and_raise(@exception)
46
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
47
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
48
+
49
+ @cf.create(@args).should == 'Processed Error'
50
+ end
8
51
  end
9
52
 
53
+ describe "update" do
54
+ it "should update the stack on Cloud Formation" do
55
+ @cf_mock.should_receive(:update_stack).with('my_stack',
56
+ { 'Capabilities' => ['CAPABILITY_IAM'],
57
+ 'TemplateBody' => 'my_template',
58
+ 'Parameters' => { 'parameter1' => 'my_param' }
59
+ })
60
+
61
+ @cf.update(@args)
62
+ end
63
+
64
+ it "should trap exceptions" do
65
+ @cf_mock.should_receive(:update_stack).with('my_stack',
66
+ { 'Capabilities' => ['CAPABILITY_IAM'],
67
+ 'TemplateBody' => 'my_template',
68
+ 'Parameters' => { 'parameter1' => 'my_param' }
69
+ }).and_raise(@exception)
70
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
71
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
72
+
73
+ @cf.update(@args).should == 'Processed Error'
74
+ end
75
+ end
76
+
77
+
78
+ describe 'destroy' do
79
+ it "should delete the stack on Cloud Formation" do
80
+ @cf_mock.should_receive(:delete_stack).with('my_stack')
81
+
82
+ @cf.destroy('my_stack')
83
+ end
84
+
85
+ it "should trap exceptions" do
86
+ @cf_mock.should_receive(:delete_stack).with('my_stack').and_raise(@exception)
87
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
88
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
89
+
90
+ @cf.destroy('my_stack').should == 'Processed Error'
91
+ end
92
+ end
93
+
94
+
95
+ describe 'describe_stack' do
96
+ it "should return the Cloud Formation description of the stack" do
97
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
98
+
99
+ @cf.describe_stack('my_stack').should == [{'StackStatus' => 'green', 'Outputs' => [{'key' => 'value'}]}]
100
+ end
101
+
102
+ it "should trap exceptions" do
103
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_raise(@exception)
104
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
105
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
106
+
107
+ @cf.describe_stack('my_stack').should == 'Processed Error'
108
+ end
109
+ end
110
+
111
+ describe "stack_resources" do
112
+ it "should return the Cloud Formation description of the stack resources" do
113
+ @cf_mock.should_receive(:describe_stack_resources).with('StackName' => 'my_stack').and_return(@response_stub)
114
+
115
+ @cf.stack_resources('my_stack').should == [{'StackName' => 'my_stack'}]
116
+ end
117
+
118
+ it "should trap exceptions" do
119
+ @cf_mock.should_receive(:describe_stack_resources).with('StackName' => 'my_stack').and_raise(@exception)
120
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
121
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
122
+
123
+ @cf.stack_resources('my_stack').should == 'Processed Error'
124
+ end
125
+ end
126
+
127
+ describe "stack_events" do
128
+ it "should return the Cloud Formation description of the stack events" do
129
+ @cf_mock.should_receive(:describe_stack_events).with('my_stack').and_return(@response_stub)
130
+
131
+ @cf.stack_events('my_stack', 2).should == ['event1', 'event2']
132
+ end
133
+
134
+ it "should trap exceptions" do
135
+ @cf_mock.should_receive(:describe_stack_events).with('my_stack').and_raise(@exception)
136
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
137
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
138
+
139
+ @cf.stack_events('my_stack', 2).should == 'Processed Error'
140
+ end
141
+ end
142
+
143
+ describe "stack_status" do
144
+ it "should return the Cloud Formation status of the stack" do
145
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
146
+
147
+ @cf.stack_status('my_stack').should == 'green'
148
+ end
149
+ end
150
+
151
+ describe "stack_outputs" do
152
+ it "should return the Cloud Formation outputs for the stack" do
153
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
154
+
155
+ @cf.stack_outputs('my_stack').should == [{'key' => 'value'}]
156
+ end
157
+ end
158
+
159
+ describe "template" do
160
+ it "should return the Cloud Formation template for the stack" do
161
+ @cf_mock.should_receive(:get_template).with('my_stack').and_return(@response_stub)
162
+
163
+ @cf.template('my_stack').should == '{EIP: "string"}'
164
+ end
165
+
166
+ it "should trap exceptions" do
167
+ @cf_mock.should_receive(:get_template).with('my_stack').and_raise(@exception)
168
+ Stackster::AWS::CloudFormation::Error.should_receive(:new).
169
+ with(:config => @config_stub, :exception => @exception).and_return(@error_stub)
170
+
171
+ @cf.template('my_stack').should == 'Processed Error'
172
+ end
173
+ end
10
174
  end
data/spec/aws/ec2_spec.rb CHANGED
@@ -1,7 +1,23 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
6
+ @response_stub = stub 'Excon::Response', :body => {
7
+ 'reservationSet' => [{'instanceSet' => [{'ipAddress' => '192.168.1.1'}]}]
8
+ }
4
9
 
5
- it "should test describe instances"
10
+ @cf_mock = mock 'CloudFormation'
11
+ Fog::Compute::AWS.stub(:new).and_return(@cf_mock)
6
12
 
13
+ @ec2 = Stackster::AWS::EC2.new(:config => @config_stub)
14
+ end
15
+
16
+ describe "describe_instances" do
17
+ it "should return the Cloud Formation description of the instances" do
18
+ @cf_mock.should_receive(:describe_instances).and_return(@response_stub)
19
+
20
+ @ec2.describe_instances.should == [{'instanceSet' => [{'ipAddress' => '192.168.1.1'}]}]
21
+ end
22
+ end
7
23
  end
@@ -1,10 +1,72 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
6
+ @response_stub = stub 'Excon::Response', :body => {
7
+ 'RequestId' => 'rid',
8
+ 'Domains' => ['domain1', 'domain2'],
9
+ 'Items' => { 'item1' => { 'key' => ['value'] } }
10
+ }
4
11
 
5
- ['domains', 'create_domain', 'put_attributes',
6
- 'select', 'delete' ].each do |t|
7
- it "should test #{t}"
12
+ @db_mock = mock 'SimpleDB'
13
+ Fog::AWS::SimpleDB.stub(:new).and_return(@db_mock)
14
+ @db_mock.stub(:list_domains).and_return(@response_stub)
15
+
16
+ @db = Stackster::AWS::SimpleDB.new(:config => @config_stub)
17
+ end
18
+
19
+ describe 'domains' do
20
+ it 'should return a list of domains' do
21
+ @db.domains.should == ['domain1', 'domain2']
22
+ end
23
+ end
24
+
25
+ describe 'domain_exists?' do
26
+ it 'should return true for existing domains' do
27
+ @db.domain_exists?('domain1').should be_true
28
+ end
29
+
30
+ it 'should return false for non-existent domains' do
31
+ @db.domain_exists?('baddomain1').should_not be_true
32
+ end
8
33
  end
9
34
 
35
+ describe 'create_domain' do
36
+ it 'should create a new domain' do
37
+ @db_mock.should_receive(:create_domain).with('newdomain').and_return(@response_stub)
38
+
39
+ @db.create_domain('newdomain').body['RequestId'].should == 'rid'
40
+ end
41
+
42
+ it 'should not create a duplicate domain' do
43
+ @db_mock.should_not_receive(:create_domain)
44
+
45
+ @db.create_domain('domain1').should be_nil
46
+ end
47
+ end
48
+
49
+ describe 'put_attributes' do
50
+ it 'should update the specified domain' do
51
+ @db_mock.should_receive(:put_attributes).with('domain1', 'item1', { 'key' => 'value' }, {}).and_return(@response_stub)
52
+
53
+ @db.put_attributes('domain1', 'item1', { 'key' => 'value' }, {}).body['RequestId'].should == 'rid'
54
+ end
55
+ end
56
+
57
+ describe 'select' do
58
+ it 'should return query items' do
59
+ @db_mock.should_receive(:select).with('item1', { "ConsistentRead" => true } ).and_return(@response_stub)
60
+
61
+ @db.select('item1').should == { 'item1' => { 'key' => ['value'] } }
62
+ end
63
+ end
64
+
65
+ describe 'delete' do
66
+ it 'should delete the attributes identified by domain and key' do
67
+ @db_mock.should_receive(:delete_attributes).with('domain1', 'item1').and_return(@response_stub)
68
+
69
+ @db.delete('domain1', 'item1').body['RequestId'].should == 'rid'
70
+ end
71
+ end
10
72
  end
data/spec/entry_spec.rb CHANGED
@@ -57,14 +57,12 @@ describe Stackster do
57
57
  @entry.name.should == 'test-stack-us-west-1'
58
58
  end
59
59
 
60
- it "should set the Name attribute to stack name before saving"
61
-
62
- it "should set the attributes in simple db" do
60
+ it "should set the attributes in simple db including default attributes" do
63
61
  @simple_db_mock.should_receive(:put_attributes).
64
62
  with("stacks",
65
63
  "test-stack-us-west-1",
66
- { "key" => "value", "Name" => "test-stack-us-west-1" },
67
- { :replace => ["key", "Name"] } )
64
+ { "key" => "value", "Name" => "test-stack-us-west-1", "CreatedAt" => anything },
65
+ { :replace => ["key", "Name", "CreatedAt"] } )
68
66
  @entry.attributes = {"key"=>"value"}
69
67
 
70
68
  @entry.save
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
3
 
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_filter "/spec/"
7
+ end
8
+
4
9
  require 'stackster'
5
10
 
6
11
  RSpec.configure do |config|
@@ -1,10 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true'
6
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
4
7
 
5
- ['attributes', 'attribute_names', 'instances_private_ip_addresses',
6
- 'display', 'resources', 'template'].each do |t|
7
- it "should test #{t}"
8
+ @stack_reader_mock = mock 'StackReader'
9
+ Stackster::StackReader.stub(:new).and_return(@stack_reader_mock)
10
+ @stack_reader_mock.stub(:attributes).and_return(:chef_repo_bucket_prefix => 'chef_repo_bp')
11
+ @stack_reader_mock.stub(:outputs).and_return([{'key' => 'value'}])
12
+ @stack_reader_mock.stub(:status).and_return('green')
13
+ @stack_reader_mock.stub(:events).and_return(['event1', 'event2', 'event3'])
14
+ @stack_reader_mock.stub(:resources).and_return([{'StackName' => 'my_stack'}])
15
+
16
+ @stack_formater = Stackster::StackFormater.new(:name => 'my_stack', :config => @config_stub)
8
17
  end
9
18
 
19
+ describe 'display' do
20
+ it 'should return formatted information for the stack' do
21
+ @stack_formater.display.should == {
22
+ 'attributes' => { :chef_repo_bucket_prefix => 'chef_repo_bp' },
23
+ 'status' => 'green',
24
+ 'outputs' => [{'key' => 'value'}],
25
+ 'events' => ['event1', 'event2', 'event3'],
26
+ 'resources' => [{'StackName' => 'my_stack'}]
27
+ }
28
+ end
29
+ end
10
30
  end
@@ -1,10 +1,75 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
+ before do
5
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true'
6
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west1'
4
7
 
5
- ['attributes', 'outputs', 'status', 'events', 'resources',
6
- 'instances', 'resources', 'template'].each do |t|
7
- it "should test #{t}"
8
+ @entry_mock = mock 'Entry'
9
+ @entry_mock.stub(:attributes).and_return(:chef_repo_bucket_prefix => 'chef_repo_bp')
10
+ Stackster::Entry.stub(:new).and_return(@entry_mock)
11
+
12
+ @cf_mock = mock 'CloudFormation'
13
+ Stackster::AWS::CloudFormation.stub(:new).and_return(@cf_mock)
14
+ @cf_mock.stub(:stack_outputs).and_return([{'key' => 'value'}])
15
+ @cf_mock.stub(:stack_status).and_return('green')
16
+ @cf_mock.stub(:stack_events).and_return(['event1', 'event2'])
17
+ @cf_mock.stub(:stack_resources).and_return([{'StackName' => 'my_stack'}])
18
+ @cf_mock.stub(:template).and_return('{"Parameters": {"EIP": "string"}}')
19
+
20
+ @instance_reader_mock = mock 'InstanceReader'
21
+ Stackster::InstanceReader.stub(:new).and_return(@instance_reader_mock)
22
+ @instance_reader_mock.stub(:list_stack_instances).and_return(['instance1', 'instance2'])
23
+
24
+ @stack_reader = Stackster::StackReader.new(:name => 'my_stack', :config => @config_stub)
25
+ end
26
+
27
+
28
+ describe 'attributes' do
29
+ it 'should return the stack attributes' do
30
+ @stack_reader.attributes.should == { :chef_repo_bucket_prefix => 'chef_repo_bp' }
31
+ end
32
+ end
33
+
34
+ describe 'outputs' do
35
+ it 'should return the stack outputs' do
36
+ @stack_reader.outputs.should == [{'key' => 'value'}]
37
+ end
38
+ end
39
+
40
+ describe 'status' do
41
+ it 'should return the stack status' do
42
+ @stack_reader.status.should == 'green'
43
+ end
8
44
  end
9
45
 
46
+ describe 'events' do
47
+ it 'should return the stack events' do
48
+ @stack_reader.events(2).should == ['event1', 'event2']
49
+ end
50
+ end
51
+
52
+ describe 'resources' do
53
+ it 'should return the stack resources' do
54
+ @stack_reader.resources.should == [{'StackName' => 'my_stack'}]
55
+ end
56
+ end
57
+
58
+ describe 'template' do
59
+ it 'should return the stack template' do
60
+ @stack_reader.template.should == '{"Parameters": {"EIP": "string"}}'
61
+ end
62
+ end
63
+
64
+ describe 'parameters' do
65
+ it 'should return the stack parameters' do
66
+ @stack_reader.parameters.should == ['EIP']
67
+ end
68
+ end
69
+
70
+ describe 'instances' do
71
+ it 'should return the stack instances' do
72
+ @stack_reader.instances.should == ['instance1', 'instance2']
73
+ end
74
+ end
10
75
  end
data/spec/stack_spec.rb CHANGED
@@ -26,11 +26,12 @@ describe Stackster do
26
26
 
27
27
  describe "mocking a stack object" do
28
28
  before do
29
- @config_mock = mock 'config mock'
30
- Stackster::Config.should_receive(:new).and_return @config_mock
29
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true', :error => 'true'
30
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west-1'
31
+ Stackster::Config.should_receive(:new).and_return @config_stub
31
32
  @entry_mock = mock 'entry mock'
32
33
  Stackster::Entry.should_receive(:new).with(:name => 'test-stack',
33
- :config => @config_mock).
34
+ :config => @config_stub).
34
35
  and_return @entry_mock
35
36
  @stack = Stackster::Stack.new :name => 'test-stack',
36
37
  :config => 'my-config',
@@ -38,7 +39,6 @@ describe Stackster do
38
39
  end
39
40
 
40
41
  context "when creating a stack" do
41
-
42
42
  it "should create a new stack" do
43
43
  stack_creater_mock = mock 'stack creater'
44
44
  @entry_mock.should_receive(:set_attributes).
@@ -48,7 +48,7 @@ describe Stackster do
48
48
  with(:name => 'test-stack',
49
49
  :entry => @entry_mock,
50
50
  :template_file => 'template_file',
51
- :config => @config_mock).
51
+ :config => @config_stub).
52
52
  and_return stack_creater_mock
53
53
  stack_creater_mock.should_receive(:create)
54
54
 
@@ -56,13 +56,22 @@ describe Stackster do
56
56
  :attributes => { 'test-attr' => 'test-value' }
57
57
  end
58
58
 
59
- it "should not create a stack entry if the create fails"
60
-
59
+ it "should not create a stack entry if the create fails" do
60
+ @entry_mock.should_receive(:set_attributes).
61
+ with({ 'test-attr' => 'test-value' })
62
+ @entry_mock.should_not_receive(:save)
63
+
64
+ begin
65
+ @stack.create :template => 'template_file',
66
+ :attributes => { 'test-attr' => 'test-value' }
67
+ fail "should have raised Errno::ENOENT"
68
+ rescue Errno::ENOENT
69
+ end
70
+ end
61
71
  end
62
72
 
63
73
  context "when updating a stack" do
64
-
65
- it "should should update an existing stack" do
74
+ it "should update an existing stack" do
66
75
  stack_updater_mock = mock 'stack updater'
67
76
  stack_reader_mock = mock 'stack reader'
68
77
  @entry_mock.should_receive(:set_attributes).
@@ -72,20 +81,47 @@ describe Stackster do
72
81
 
73
82
  Stackster::StackReader.should_receive(:new).
74
83
  with(:name => 'test-stack',
75
- :config => @config_mock).
84
+ :config => @config_stub).
76
85
  and_return stack_reader_mock
77
86
  Stackster::StackUpdater.should_receive(:new).
78
87
  with(:name => 'test-stack',
79
88
  :entry => @entry_mock,
80
89
  :template_body => 'template-body-json',
81
- :config => @config_mock).
90
+ :config => @config_stub).
82
91
  and_return stack_updater_mock
83
92
  stack_updater_mock.should_receive(:update_stack_if_parameters_changed).
84
93
  and_return true
85
94
  @stack.update :attributes => { 'update' => 'test-attrs' }
86
95
  end
87
96
 
88
- it "should not update a stack entry if the create fails"
97
+ it "should not update a stack entry if the update fails" do
98
+ @entry_mock.should_receive(:set_attributes).
99
+ with({ 'update' => 'test-attrs' })
100
+ @entry_mock.should_not_receive(:save)
101
+
102
+ stack_reader_mock = mock 'stack reader'
103
+ stack_reader_mock.should_receive(:template).and_return('template-body-json')
104
+ Stackster::StackReader.should_receive(:new).
105
+ with(:name => 'test-stack',
106
+ :config => @config_stub).
107
+ and_return stack_reader_mock
108
+
109
+ stack_updater_mock = mock 'stack updater'
110
+ Stackster::StackUpdater.should_receive(:new).
111
+ with(:name => 'test-stack',
112
+ :entry => @entry_mock,
113
+ :template_body => 'template-body-json',
114
+ :config => @config_stub).
115
+ and_return stack_updater_mock
116
+ stack_updater_mock.should_receive(:update_stack_if_parameters_changed).
117
+ and_raise('test-stack has not reached a stable state')
118
+
119
+ begin
120
+ @stack.update :attributes => { 'update' => 'test-attrs' }
121
+ fail 'should have raised RuntimeException'
122
+ rescue RuntimeError
123
+ end
124
+ end
89
125
  end
90
126
 
91
127
  context "when destroying a stack" do
@@ -93,20 +129,97 @@ describe Stackster do
93
129
  stack_destroyer_mock = mock 'stack destroyer'
94
130
  Stackster::StackDestroyer.should_receive(:new).
95
131
  with(:name => 'test-stack',
96
- :config => @config_mock).
132
+ :config => @config_stub).
97
133
  and_return stack_destroyer_mock
98
134
  stack_destroyer_mock.should_receive(:destroy)
99
135
  @entry_mock.should_receive(:delete_attributes)
100
136
  @stack.destroy
101
137
  end
102
138
  end
139
+ end
140
+
141
+ describe 'wrapper methods' do
142
+ before do
143
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true', :error => 'true'
144
+ @config_stub = stub 'Config', :logger => @logger_stub, :access_key => 'key', :secret_key => 'XXX', :region => 'us-west-1'
145
+ @entry_stub = stub 'Entry'
146
+ Stackster::Config.should_receive(:new).and_return(@config_stub)
147
+ Stackster::Entry.should_receive(:new).and_return(@entry_stub)
148
+
149
+ @stack = Stackster::Stack.new :name => 'test-stack',
150
+ :config => @config_stub,
151
+ :logger => @logger_stub
152
+ end
103
153
 
104
- ['attributes', 'display', 'show', 'outputs',
105
- 'status', 'events', 'instances', 'instances_public_ip_addresses',
106
- 'instances_private_ip_addresses', 'resources', 'template'].each do |t|
107
- it "should test #{t}"
154
+ context "formater" do
155
+ before do
156
+ @stack_formater_mock = mock 'StackFormater'
157
+ Stackster::StackFormater.should_receive(:new).and_return(@stack_formater_mock)
158
+ @stack_formater_mock.stub(:display).and_return({
159
+ 'attributes' => { :chef_repo_bucket_prefix => 'chef_repo_bp' },
160
+ 'status' => 'green',
161
+ 'outputs' => [{'key' => 'value'}],
162
+ 'events' => ['event1', 'event2', 'event3'],
163
+ 'resources' => [{'StackName' => 'test-stack'}]
164
+ })
165
+ end
166
+
167
+ it 'should display formatted stack attributes' do
168
+ @stack.display.should == {
169
+ 'attributes' => { :chef_repo_bucket_prefix => 'chef_repo_bp' },
170
+ 'status' => 'green',
171
+ 'outputs' => [{'key' => 'value'}],
172
+ 'events' => ['event1', 'event2', 'event3'],
173
+ 'resources' => [{'StackName' => 'test-stack'}]
174
+ }
175
+ end
108
176
  end
109
177
 
110
- end
178
+ context 'reader' do
179
+ before do
180
+ @stack_reader_mock = mock 'StackReader'
181
+ Stackster::StackReader.should_receive(:new).and_return(@stack_reader_mock)
182
+ @stack_reader_mock.stub(:attributes).and_return(:chef_repo_bucket_prefix => 'chef_repo_bp')
183
+ @stack_reader_mock.stub(:outputs).and_return([{'key' => 'value'}])
184
+ @stack_reader_mock.stub(:status).and_return('green')
185
+ @stack_reader_mock.stub(:events).and_return(['event1', 'event2', 'event3'])
186
+ @stack_reader_mock.stub(:resources).and_return([{'StackName' => 'my_stack'}])
187
+ @stack_reader_mock.stub(:template).and_return('{"Parameters": {"EIP": "string"}}')
188
+ @stack_reader_mock.stub(:parameters).and_return(['EIP'])
189
+ @stack_reader_mock.stub(:instances).and_return(['instance1', 'instance2'])
190
+ end
191
+
192
+ it 'should return the stack attributes' do
193
+ @stack.attributes.should == { :chef_repo_bucket_prefix => 'chef_repo_bp' }
194
+ end
195
+
196
+ it 'should return the stack outputs' do
197
+ @stack.outputs.should == [{'key' => 'value'}]
198
+ end
111
199
 
200
+ it 'should return the stack status' do
201
+ @stack.status.should == 'green'
202
+ end
203
+
204
+ it 'should return the stack events' do
205
+ @stack.events(3).should == ['event1', 'event2', 'event3']
206
+ end
207
+
208
+ it 'should return the stack resources' do
209
+ @stack.resources.should == [{'StackName' => 'my_stack'}]
210
+ end
211
+
212
+ it 'should return the stack template' do
213
+ @stack.template.should == '{"Parameters": {"EIP": "string"}}'
214
+ end
215
+
216
+ it 'should return the stack parameters' do
217
+ @stack.parameters.should == ['EIP']
218
+ end
219
+
220
+ it 'should return the stack instances' do
221
+ @stack.instances.should == ['instance1', 'instance2']
222
+ end
223
+ end
224
+ end
112
225
  end
data/stackster.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
 
21
21
  # specify any dependencies here; for example:
22
22
  s.add_development_dependency "rspec"
23
+ s.add_development_dependency "simplecov"
23
24
 
24
25
  s.add_runtime_dependency "fog"
25
26
  s.add_runtime_dependency 'logger'
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.9
4
+ version: 0.3.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: 2012-07-23 00:00:00.000000000 Z
12
+ date: 2012-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70160791318120 !ruby/object:Gem::Requirement
16
+ requirement: &2160251380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70160791318120
24
+ version_requirements: *2160251380
25
+ - !ruby/object:Gem::Dependency
26
+ name: simplecov
27
+ requirement: &2160250100 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2160250100
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: fog
27
- requirement: &70160791317340 !ruby/object:Gem::Requirement
38
+ requirement: &2160248940 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - ! '>='
@@ -32,10 +43,10 @@ dependencies:
32
43
  version: '0'
33
44
  type: :runtime
34
45
  prerelease: false
35
- version_requirements: *70160791317340
46
+ version_requirements: *2160248940
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: logger
38
- requirement: &70160791315460 !ruby/object:Gem::Requirement
49
+ requirement: &2160247880 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
@@ -43,10 +54,10 @@ dependencies:
43
54
  version: '0'
44
55
  type: :runtime
45
56
  prerelease: false
46
- version_requirements: *70160791315460
57
+ version_requirements: *2160247880
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: trollop
49
- requirement: &70160791312720 !ruby/object:Gem::Requirement
60
+ requirement: &2160246820 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :runtime
56
67
  prerelease: false
57
- version_requirements: *70160791312720
68
+ version_requirements: *2160246820
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: xml-simple
60
- requirement: &70160791309680 !ruby/object:Gem::Requirement
71
+ requirement: &2160244280 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,7 +76,7 @@ dependencies:
65
76
  version: '0'
66
77
  type: :runtime
67
78
  prerelease: false
68
- version_requirements: *70160791309680
79
+ version_requirements: *2160244280
69
80
  description: Thats what I do
70
81
  email:
71
82
  - brett@weav.net
@@ -135,21 +146,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
146
  - - ! '>='
136
147
  - !ruby/object:Gem::Version
137
148
  version: '0'
138
- segments:
139
- - 0
140
- hash: 107402892190402761
141
149
  required_rubygems_version: !ruby/object:Gem::Requirement
142
150
  none: false
143
151
  requirements:
144
152
  - - ! '>='
145
153
  - !ruby/object:Gem::Version
146
154
  version: '0'
147
- segments:
148
- - 0
149
- hash: 107402892190402761
150
155
  requirements: []
151
156
  rubyforge_project: stackster
152
- rubygems_version: 1.8.16
157
+ rubygems_version: 1.8.10
153
158
  signing_key:
154
159
  specification_version: 3
155
160
  summary: I make deployments easier