stackster 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ ## head:
2
+
3
+ ## 0.4.3 (03/14/2013)
4
+
5
+ * Properly return instances in an auto scaling group
6
+
1
7
  ## v0.4.2:
2
8
 
3
9
  * Fixed the handling of data from the select method
@@ -0,0 +1,22 @@
1
+ require 'fog'
2
+
3
+ module Stackster
4
+ class AWS
5
+ class AutoScalingGroups
6
+
7
+ def initialize(args)
8
+ c = args[:config]
9
+ @asg_id = args[:asg_id]
10
+ @connect = Fog::AWS::AutoScaling.new :aws_access_key_id => c.access_key,
11
+ :aws_secret_access_key => c.secret_key,
12
+ :region => c.region
13
+ end
14
+
15
+ def list_instances
16
+ body = @connect.describe_auto_scaling_groups('AutoScalingGroupNames' => [@asg_id]).body
17
+ result = body['DescribeAutoScalingGroupsResult']['AutoScalingGroups'].last
18
+ result['Instances'].map { |info| info['InstanceId'] }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -7,18 +7,14 @@ module Stackster
7
7
  def initialize(args)
8
8
  c = args[:config]
9
9
  @connect = Fog::Compute::AWS.new :aws_access_key_id => c.access_key,
10
- :aws_secret_access_key => c.secret_key,
11
- :region => c.region
10
+ :aws_secret_access_key => c.secret_key,
11
+ :region => c.region
12
12
  end
13
13
 
14
- def describe_instances
15
- i = []
16
- @connect.describe_instances.body['reservationSet'].each do |instance|
17
- i << instance
18
- end
19
- i
14
+ def describe_instance(instance)
15
+ @connect.describe_instances('instance-state-name' => 'running',
16
+ 'instance-id' => instance).body['reservationSet']
20
17
  end
21
-
22
18
  end
23
19
  end
24
20
  end
data/lib/stackster/aws.rb CHANGED
@@ -2,3 +2,4 @@ require "stackster/aws/cloud_formation"
2
2
  require "stackster/aws/cloud_formation/error"
3
3
  require "stackster/aws/ec2"
4
4
  require "stackster/aws/simpledb"
5
+ require "stackster/aws/auto_scaling_groups"
@@ -6,17 +6,10 @@ module Stackster
6
6
  end
7
7
 
8
8
  def list_stack_instances(stack_name)
9
- h = []
10
- describe_instances.each do |instance|
11
- tag_set = instance['instancesSet'].first['tagSet']
12
- instance_stack_name = tag_set['aws:cloudformation:stack-name']
13
- if instance_stack_name && instance_stack_name == stack_name
14
- if instance_running? instance
15
- h << instance
16
- end
17
- end
18
- end
19
- h
9
+ @asg_id = auto_scaling_group_id(stack_name)
10
+ asg_instances = auto_scaling.list_instances if @asg_id
11
+ return [] unless asg_instances
12
+ ec2.describe_instance asg_instances
20
13
  end
21
14
 
22
15
  private
@@ -25,17 +18,26 @@ module Stackster
25
18
  @ec2 ||= AWS::EC2.new :config => @config
26
19
  end
27
20
 
28
- def get_instance_state(instance_hash)
29
- instance_hash['instancesSet'].first['instanceState']['name']
21
+ def auto_scaling
22
+ @auto_scaling ||= AWS::AutoScalingGroups.new :config => @config, :asg_id => @asg_id
30
23
  end
31
24
 
32
- def instance_running?(instance_hash)
33
- get_instance_state(instance_hash) == 'running'
25
+ def cloud_formation
26
+ @cloud_formation ||= AWS::CloudFormation.new :config => @config
34
27
  end
35
28
 
36
- def describe_instances
37
- ec2.describe_instances
29
+ def auto_scaling_group_id(stack_name)
30
+ cf_stack_resources = cloud_formation.stack_resources stack_name
31
+ parse_cf_stack_resources cf_stack_resources
38
32
  end
39
33
 
34
+ def parse_cf_stack_resources(cf_stack_resources)
35
+ cf_stack_resources.each do |resource|
36
+ if resource['ResourceType'] == 'AWS::AutoScaling::AutoScalingGroup'
37
+ return resource['PhysicalResourceId']
38
+ end
39
+ end
40
+ false
41
+ end
40
42
  end
41
43
  end
@@ -1,3 +1,3 @@
1
1
  module Stackster
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stackster do
4
+ before do
5
+ @config_stub = stub 'Config', :access_key => 'key',
6
+ :secret_key => 'XXX',
7
+ :region => 'us-west1'
8
+ instances = ['first',{ 'Instances' => [{ 'InstanceId' => 'i-000001' },
9
+ { 'InstanceId' => 'i-000002' }] }]
10
+ body = { 'DescribeAutoScalingGroupsResult' => { 'AutoScalingGroups' => instances } }
11
+ @response_stub = stub 'Fog::Response', :body => body
12
+ @auto_scaling_mock = mock 'AutoScalingGroups'
13
+ Fog::AWS::AutoScaling.stub :new => @auto_scaling_mock
14
+ @auto_scaling_groups = Stackster::AWS::AutoScalingGroups.new(:config => @config_stub,
15
+ :asg_id => 'asg_name')
16
+ end
17
+
18
+ describe 'list_instances' do
19
+ it "should return the array of instance id's when passed the AutoScaleGroup name" do
20
+ @auto_scaling_mock.should_receive(:describe_auto_scaling_groups).
21
+ with('AutoScalingGroupNames' => ['asg_name']).
22
+ and_return(@response_stub)
23
+
24
+ @auto_scaling_groups.list_instances.should == ['i-000001','i-000002' ]
25
+
26
+
27
+ end
28
+ end
29
+ end
data/spec/aws/ec2_spec.rb CHANGED
@@ -2,9 +2,15 @@ require 'spec_helper'
2
2
 
3
3
  describe Stackster do
4
4
  before do
5
+ @logger_stub = stub 'logger stub', :info => 'true', :warn => 'true', :error => 'true'
5
6
  @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'}]}]
7
+ @instance_id = 'i-123456'
8
+ @response_stub = stub 'Excon::Response', :body => {
9
+ 'reservationSet' => [{
10
+ 'instanceSet' => [{'instanceState' => {'name' => 'running'}},
11
+ {'ipAddress' => '54.10.10.1'},
12
+ {'instanceId' => 'i-123456'},
13
+ {'privateIpAddress' => '192.168.1.1'}]}]
8
14
  }
9
15
 
10
16
  @cf_mock = mock 'CloudFormation'
@@ -13,11 +19,15 @@ describe Stackster do
13
19
  @ec2 = Stackster::AWS::EC2.new(:config => @config_stub)
14
20
  end
15
21
 
16
- describe "describe_instances" do
17
- it "should return the Cloud Formation description of the instances" do
22
+ describe 'describe_instance' do
23
+ it 'should return the Cloud Formation description of only the running passed instance' do
18
24
  @cf_mock.should_receive(:describe_instances).and_return(@response_stub)
19
25
 
20
- @ec2.describe_instances.should == [{'instanceSet' => [{'ipAddress' => '192.168.1.1'}]}]
26
+ @ec2.describe_instance(@instance_id).should == [{
27
+ 'instanceSet' => [{'instanceState' => {'name' => 'running'}},
28
+ {'ipAddress' => '54.10.10.1'},
29
+ {'instanceId' => 'i-123456'},
30
+ {'privateIpAddress' => '192.168.1.1'}]}]
21
31
  end
22
32
  end
23
33
  end
@@ -1,84 +1,66 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Stackster do
3
+ describe Stackster::InstanceReader do
4
4
 
5
+ describe "list_stack_instances" do
5
6
 
6
- describe "with a single running instance" do
7
7
  before do
8
- @instances = [
9
- { 'instancesSet' =>
10
- [
11
- { 'tagSet' =>
12
- { 'aws:cloudformation:stack-name' => 'my-stack' },
13
- 'instanceState' =>
14
- { 'name' => 'running' }
15
- }
16
- ]
17
- },
18
- { 'instancesSet' =>
19
- [
20
- { 'tagSet' =>
21
- { 'aws:cloudformation:stack-name' => 'my-stack' },
22
- 'instanceState' =>
23
- { 'name' => 'terminated' }
24
- }
25
- ]
26
- },
27
- { 'instancesSet' =>
28
- [
29
- { 'tagSet' =>
30
- { 'aws:cloudformation:stack-name' => 'dead-stack' },
31
- 'instanceState' =>
32
- { 'name' => 'terminated' }
33
- }
34
- ]
35
- }
36
- ]
37
- end
8
+ @config_mock = mock 'config'
9
+ @cloud_formation_mock = mock 'cloud formation'
10
+ @auto_scaling_groups_mock = mock 'auto scaling'
11
+ @ec2_mock = mock 'ec2'
12
+ @instance_reservation_set_mock = mock 'reservation'
13
+ @instance_data_mock = mock 'instance data mock'
14
+
15
+ Stackster::AWS::CloudFormation.should_receive(:new).
16
+ with(:config => @config_mock).
17
+ and_return @cloud_formation_mock
18
+
19
+ stack_resource_results = [{'StackName' => 'stack',
20
+ 'ResourceType' => 'AWS::AutoScaling::AutoScalingGroup',
21
+ 'PhysicalResourceId' => 'asg1'}]
22
+
23
+ @cloud_formation_mock.should_receive(:stack_resources).
24
+ with('stack').
25
+ and_return stack_resource_results
26
+
27
+ Stackster::AWS::AutoScalingGroups.should_receive(:new).
28
+ with(:config => @config_mock, :asg_id => "asg1").
29
+ and_return @auto_scaling_groups_mock
38
30
 
39
- it "should list running instance within the given stack" do
40
- @ec2_mock = mock 'simple ec2'
41
- config = Stackster::Config.new(:config => { 'access_key' => 'the-key',
42
- 'secret_key' => 'secret',
43
- 'region' => 'us-west-1' })
44
31
  Stackster::AWS::EC2.should_receive(:new).
45
- with(:config => config).
32
+ with(:config => @config_mock).
46
33
  and_return @ec2_mock
47
- instance_reader = Stackster::InstanceReader.new :config => config
48
- @ec2_mock.should_receive(:describe_instances).
49
- and_return(@instances)
50
- instance_reader.list_stack_instances('my-stack').count.
51
- should == 1
52
34
  end
53
35
 
54
- it "should not include instances which are in different stacks" do
55
- @ec2_mock = mock 'simple ec2'
56
- config = Stackster::Config.new(:config => { 'access_key' => 'the-key',
57
- 'secret_key' => 'secret',
58
- 'region' => 'us-west-1' })
59
- Stackster::AWS::EC2.should_receive(:new).
60
- with(:config => config).
61
- and_return @ec2_mock
62
- instance_reader = Stackster::InstanceReader.new :config => config
63
- @ec2_mock.should_receive(:describe_instances).
64
- and_return(@instances)
65
- instance_reader.list_stack_instances('another-stack').count.
66
- should == 0
36
+ context "with no running instances" do
37
+ it "should return empty array" do
38
+ @auto_scaling_groups_mock.should_receive(:list_instances).
39
+ and_return []
40
+
41
+ @ec2_mock.should_receive(:describe_instance).
42
+ with([]).
43
+ and_return @instance_reservation_set_mock
44
+
45
+ @instance_reservation_set_mock.stub :any? => true
46
+ instance_reader = Stackster::InstanceReader.new :config => @config_mock
47
+ instance_reader.list_stack_instances('stack').should == @instance_reservation_set_mock
48
+ end
67
49
  end
68
50
 
69
- it "should not include instances which are not running" do
70
- @ec2_mock = mock 'simple ec2'
71
- config = Stackster::Config.new(:config => { 'access_key' => 'the-key',
72
- 'secret_key' => 'secret',
73
- 'region' => 'us-west-1' })
74
- Stackster::AWS::EC2.should_receive(:new).
75
- with(:config => config).
76
- and_return @ec2_mock
77
- instance_reader = Stackster::InstanceReader.new :config => config
78
- @ec2_mock.should_receive(:describe_instances).
79
- and_return(@instances)
80
- instance_reader.list_stack_instances('dead-stack').count.
81
- should == 0
51
+ context "with running instances" do
52
+ it "should return the reservation set for each running instance" do
53
+ @auto_scaling_groups_mock.should_receive(:list_instances).
54
+ and_return ['instance1']
55
+
56
+ @ec2_mock.should_receive(:describe_instance).
57
+ with(['instance1']).
58
+ and_return @instance_reservation_set_mock
59
+
60
+ @instance_reservation_set_mock.stub :any? => true
61
+ instance_reader = Stackster::InstanceReader.new :config => @config_mock
62
+ instance_reader.list_stack_instances('stack').should == @instance_reservation_set_mock
63
+ end
82
64
  end
83
65
  end
84
66
  end
data/stackster.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_development_dependency "simplecov", "~> 0.6.4"
25
25
  s.add_development_dependency "timecop", "~> 0.5.3"
26
26
 
27
- s.add_runtime_dependency "fog", "= 1.6.0"
27
+ s.add_runtime_dependency "fog", "= 1.10.0"
28
28
  s.add_runtime_dependency "trollop", "= 2.0"
29
29
  s.add_runtime_dependency "xml-simple", "= 1.1.2"
30
30
  end
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.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ 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-03-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - '='
84
84
  - !ruby/object:Gem::Version
85
- version: 1.6.0
85
+ version: 1.10.0
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - '='
92
92
  - !ruby/object:Gem::Version
93
- version: 1.6.0
93
+ version: 1.10.0
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: trollop
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -134,7 +134,7 @@ files:
134
134
  - .gitignore
135
135
  - .rvmrc
136
136
  - .travis.yml
137
- - CHANGELOG
137
+ - CHANGELOG.md
138
138
  - Gemfile
139
139
  - LICENSE
140
140
  - README.md
@@ -142,6 +142,7 @@ files:
142
142
  - bin/stackster
143
143
  - lib/stackster.rb
144
144
  - lib/stackster/aws.rb
145
+ - lib/stackster/aws/auto_scaling_groups.rb
145
146
  - lib/stackster/aws/cloud_formation.rb
146
147
  - lib/stackster/aws/cloud_formation/error.rb
147
148
  - lib/stackster/aws/ec2.rb
@@ -163,6 +164,7 @@ files:
163
164
  - lib/stackster/stack/stack_updater.rb
164
165
  - lib/stackster/stack/status.rb
165
166
  - lib/stackster/version.rb
167
+ - spec/aws/auto_scaling_groups_spec.rb
166
168
  - spec/aws/cloud_formation/error_spec.rb
167
169
  - spec/aws/cloud_formation_spec.rb
168
170
  - spec/aws/ec2_spec.rb
@@ -196,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
198
  version: '0'
197
199
  segments:
198
200
  - 0
199
- hash: 2937720752334534318
201
+ hash: -3513599222543714350
200
202
  required_rubygems_version: !ruby/object:Gem::Requirement
201
203
  none: false
202
204
  requirements:
@@ -205,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
207
  version: '0'
206
208
  segments:
207
209
  - 0
208
- hash: 2937720752334534318
210
+ hash: -3513599222543714350
209
211
  requirements: []
210
212
  rubyforge_project: stackster
211
213
  rubygems_version: 1.8.24
@@ -213,6 +215,7 @@ signing_key:
213
215
  specification_version: 3
214
216
  summary: I make deployments easier
215
217
  test_files:
218
+ - spec/aws/auto_scaling_groups_spec.rb
216
219
  - spec/aws/cloud_formation/error_spec.rb
217
220
  - spec/aws/cloud_formation_spec.rb
218
221
  - spec/aws/ec2_spec.rb