fog 0.0.13 → 0.0.14

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/Rakefile CHANGED
@@ -15,9 +15,8 @@ begin
15
15
  gem.summary = %Q{fog = clouds + you}
16
16
  gem.email = "me@geemus.com"
17
17
  gem.homepage = "http://github.com/geemus/fog"
18
- gem.authors = ["Wesley Beary"]
18
+ gem.authors = ["geemus (Wesley Beary)"]
19
19
  gem.rubyforge_project = "fog"
20
-
21
20
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
21
  end
23
22
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.13
1
+ 0.0.14
data/bin/fog CHANGED
@@ -9,15 +9,44 @@ elsif File.exists?(File.expand_path('~/.fog'))
9
9
  @credentials = YAML.load(File.open(File.expand_path('~/.fog')).read)
10
10
  end
11
11
 
12
+ @ec2 = Fog::AWS::EC2.new(
13
+ :aws_access_key_id => @credentials['aws_access_key_id'],
14
+ :aws_secret_access_key => @credentials['aws_secret_access_key']
15
+ )
16
+
12
17
  @s3 = Fog::AWS::S3.new(
13
18
  :aws_access_key_id => @credentials['aws_access_key_id'],
14
19
  :aws_secret_access_key => @credentials['aws_secret_access_key']
15
20
  )
16
21
 
22
+ def addresses
23
+ @ec2.addresses
24
+ end
25
+
17
26
  def buckets
18
27
  @s3.buckets
19
28
  end
20
29
 
30
+ def instances
31
+ @ec2.instances
32
+ end
33
+
34
+ def key_pairs
35
+ @ec2.key_pairs
36
+ end
37
+
38
+ def security_groups
39
+ @ec2.security_groups
40
+ end
41
+
42
+ def snapshots
43
+ @ec2.snapshots
44
+ end
45
+
46
+ def volumes
47
+ @ec2.volumes
48
+ end
49
+
21
50
  ARGV.clear # Avoid passing args to IRB
22
51
  IRB.setup(nil)
23
52
  @irb = IRB::Irb.new(nil)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{fog}
8
- s.version = "0.0.13"
8
+ s.version = "0.0.14"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Wesley Beary"]
12
- s.date = %q{2009-10-05}
11
+ s.authors = ["geemus (Wesley Beary)"]
12
+ s.date = %q{2009-10-09}
13
13
  s.default_executable = %q{fog}
14
14
  s.description = %q{brings clouds to you}
15
15
  s.email = %q{me@geemus.com}
@@ -139,6 +139,8 @@ Gem::Specification.new do |s|
139
139
  "lib/fog/response.rb",
140
140
  "spec/aws/models/ec2/address_spec.rb",
141
141
  "spec/aws/models/ec2/addresses_spec.rb",
142
+ "spec/aws/models/ec2/instance_spec.rb",
143
+ "spec/aws/models/ec2/instances_spec.rb",
142
144
  "spec/aws/models/ec2/key_pair_spec.rb",
143
145
  "spec/aws/models/ec2/key_pairs_spec.rb",
144
146
  "spec/aws/models/ec2/security_group_spec.rb",
@@ -215,6 +217,8 @@ Gem::Specification.new do |s|
215
217
  s.test_files = [
216
218
  "spec/aws/models/ec2/address_spec.rb",
217
219
  "spec/aws/models/ec2/addresses_spec.rb",
220
+ "spec/aws/models/ec2/instance_spec.rb",
221
+ "spec/aws/models/ec2/instances_spec.rb",
218
222
  "spec/aws/models/ec2/key_pair_spec.rb",
219
223
  "spec/aws/models/ec2/key_pairs_spec.rb",
220
224
  "spec/aws/models/ec2/security_group_spec.rb",
@@ -28,6 +28,8 @@ module Fog
28
28
 
29
29
  load "fog/aws/models/ec2/address.rb"
30
30
  load "fog/aws/models/ec2/addresses.rb"
31
+ load "fog/aws/models/ec2/instance.rb"
32
+ load "fog/aws/models/ec2/instances.rb"
31
33
  load "fog/aws/models/ec2/key_pair.rb"
32
34
  load "fog/aws/models/ec2/key_pairs.rb"
33
35
  load "fog/aws/models/ec2/security_group.rb"
@@ -23,6 +23,11 @@ module Fog
23
23
  true
24
24
  end
25
25
 
26
+ def instance=(new_instance)
27
+ @instance_id = new_instance.instance_id
28
+ connection.associate_address(@instance_id, @public_ip)
29
+ end
30
+
26
31
  def reload
27
32
  new_attributes = addresses.get(@public_ip).attributes
28
33
  merge_attributes(new_attributes)
@@ -9,6 +9,7 @@ module Fog
9
9
  class Addresses < Fog::Collection
10
10
 
11
11
  attribute :public_ip
12
+ attribute :instance_id
12
13
 
13
14
  def initialize(attributes)
14
15
  @public_ip ||= []
@@ -27,6 +28,9 @@ module Fog
27
28
  :connection => connection
28
29
  }.merge!(address))
29
30
  end
31
+ if instance_id
32
+ addresses = addresses.select {|address| address.instance_id == instance_id}
33
+ end
30
34
  addresses
31
35
  end
32
36
 
@@ -24,12 +24,7 @@ module Fog
24
24
  attribute :user_data
25
25
 
26
26
  def address
27
- connection.addresses.select {|address| address.instance_id == @instance_id}.first
28
- end
29
-
30
- def address=(new_address)
31
- new_address.instance_id = @instance_id
32
- connection.associate_address(@instance_id, new_address.public_ip)
27
+ connection.addresses(:instance_id => instance_id).all.first
33
28
  end
34
29
 
35
30
  def destroy
@@ -110,12 +105,7 @@ module Fog
110
105
  end
111
106
 
112
107
  def volumes
113
- connection.volumes.all.select {|volume| volume.instance_id == @instance_id}
114
- end
115
-
116
- def volume=(new_volume)
117
- new_volume.instance_id = @instance_id
118
- connection.attach_volume(@instance_id, new_volume.volume_id, new_volume.device)
108
+ connection.volumes(:instance_id => instance_id)
119
109
  end
120
110
 
121
111
  private
@@ -10,16 +10,24 @@ module Fog
10
10
 
11
11
  attribute :instance_id
12
12
 
13
+ def initialize(attributes)
14
+ @instance_id ||= []
15
+ super
16
+ end
17
+
13
18
  def all(instance_id = [])
14
- data = connection.describe_instances(instance_id)
19
+ data = connection.describe_instances(instance_id).body
15
20
  instances = Fog::AWS::EC2::Instances.new({
16
- :connection => connection
21
+ :connection => connection,
22
+ :instance_id => instance_id
17
23
  }.merge!(attributes))
18
- data['instancesSet'].each do |instance|
19
- instances << Fog::AWS::EC2::Instances.new({
20
- :connection => connection,
21
- :instances => self
22
- }.merge!(instance))
24
+ data['reservationSet'].each do |reservation|
25
+ reservation['instancesSet'].each do |instance|
26
+ instances << Fog::AWS::EC2::Instance.new({
27
+ :connection => connection,
28
+ :instances => self
29
+ }.merge!(instance))
30
+ end
23
31
  end
24
32
  instances
25
33
  end
@@ -11,7 +11,7 @@ module Fog
11
11
  attribute :instance_id, 'instanceId'
12
12
  attribute :size
13
13
  attribute :snapshot_id, 'snapshotId'
14
- attribute :status, 'status'
14
+ attribute :status
15
15
  attribute :volume_id, 'volumeId'
16
16
 
17
17
  def initialize(attributes = {})
@@ -26,6 +26,11 @@ module Fog
26
26
  true
27
27
  end
28
28
 
29
+ def instance=(new_instance)
30
+ @instance_id = new_instance.instance_id
31
+ connection.attach_volume(@instance_id, @volume_id, @device)
32
+ end
33
+
29
34
  def reload
30
35
  new_attributes = volumes.get(@volume_id).attributes
31
36
  merge_attributes(new_attributes)
@@ -9,6 +9,7 @@ module Fog
9
9
  class Volumes < Fog::Collection
10
10
 
11
11
  attribute :volume_id
12
+ attribute :instance_id
12
13
 
13
14
  def initialize(attributes)
14
15
  @volume_id ||= []
@@ -27,6 +28,9 @@ module Fog
27
28
  :volumes => self
28
29
  }.merge!(volume))
29
30
  end
31
+ if instance_id
32
+ volumes = volumes.select {|volume| volume.instance_id == instance_id}
33
+ end
30
34
  volumes
31
35
  end
32
36
 
@@ -44,7 +44,7 @@ module Fog
44
44
  options[key] = value
45
45
  end
46
46
  end
47
- bucket.objects.merge_attributes(:options => options)
47
+ bucket.objects.merge_attributes(options)
48
48
  data['Contents'].each do |object|
49
49
  owner = Fog::AWS::S3::Owner.new(object.delete('Owner').merge!(:connection => connection))
50
50
  bucket.objects << Fog::AWS::S3::Object.new({
@@ -4,11 +4,17 @@ module Fog
4
4
 
5
5
  class Objects < Fog::Collection
6
6
 
7
- attribute :options
7
+ attribute :delimiter, 'Delimiter'
8
+ attribute :is_truncated, 'IsTruncated'
9
+ attribute :marker, 'Marker'
10
+ attribute :max_keys, 'MaxKeys'
11
+ attribute :prefix, 'Prefix'
8
12
 
9
13
  def all(options = {})
10
- merge_attributes(:options => options)
11
- bucket.buckets.get(bucket.name, @options).objects
14
+ bucket.buckets.get(
15
+ bucket.name,
16
+ options.reject {|key, value| !['delimiter', 'marker', 'max-keys', 'prefix'].include?(key)}
17
+ ).objects
12
18
  end
13
19
 
14
20
  def bucket
@@ -75,7 +81,12 @@ module Fog
75
81
  end
76
82
 
77
83
  def reload
78
- all(@options)
84
+ all({
85
+ 'delimiter' => @delimiter,
86
+ 'marker' => @marker,
87
+ 'max-keys' => @max_keys,
88
+ 'prefix' => @prefix
89
+ })
79
90
  end
80
91
 
81
92
  private
@@ -0,0 +1,108 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe 'Fog::AWS::EC2::Instance' do
4
+
5
+ describe "#initialize" do
6
+
7
+ it "should remap attributes from parser" # do
8
+ # instance = Fog::AWS::EC2::Instance.new(
9
+ # 'instanceId' => 'i-00000000',
10
+ # 'publicIp' => '0.0.0.0'
11
+ # )
12
+ # instance.instance_id.should == 'i-00000000'
13
+ # instance.public_ip.should == '0.0.0.0'
14
+ # end
15
+
16
+ end
17
+
18
+ describe "#address" do
19
+ it "should have tests"
20
+ end
21
+
22
+ describe "#destroy" do
23
+
24
+ it "should return true if the instance is deleted" do
25
+ instance = ec2.instances.create(:image_id => 'ami-5ee70037')
26
+ instance.destroy.should be_true
27
+ end
28
+
29
+ end
30
+
31
+ describe "#instances" do
32
+
33
+ it "should return a Fog::AWS::EC2::Instances" do
34
+ ec2.instances.new.instances.should be_a(Fog::AWS::EC2::Instances)
35
+ end
36
+
37
+ it "should be the instances the instance is related to" do
38
+ instances = ec2.instances
39
+ instances.new.instances.should == instances
40
+ end
41
+
42
+ end
43
+
44
+ describe "#key_pair" do
45
+ it "should have tests"
46
+ end
47
+
48
+ describe "#key_pair=" do
49
+ it "should have tests"
50
+ end
51
+
52
+ describe "#monitoring=" do
53
+ it "should have tests"
54
+ end
55
+
56
+ describe "#placement=" do
57
+ it "should have tests"
58
+ end
59
+
60
+ describe "#reload" do
61
+
62
+ before(:each) do
63
+ @instance = ec2.instances.create(:image_id => 'ami-5ee70037')
64
+ @reloaded = @instance.reload
65
+ end
66
+
67
+ after(:each) do
68
+ @instance.destroy
69
+ end
70
+
71
+ it "should return a Fog::AWS::EC2::Instance" do
72
+ @reloaded.should be_a(Fog::AWS::EC2::Instance)
73
+ end
74
+
75
+ it "should reset attributes to remote state" do
76
+ @instance.attributes.should == @reloaded.attributes
77
+ end
78
+
79
+ end
80
+
81
+ describe "#save" do
82
+
83
+ before(:each) do
84
+ @instance = ec2.instances.new
85
+ end
86
+
87
+ it "should return true when it succeeds" do
88
+ @instance.save.should be_true
89
+ @instance.destroy
90
+ end
91
+
92
+ it "should not exist in instances before save" do
93
+ @instance.instances.get(@instance.instance_id).should be_nil
94
+ end
95
+
96
+ it "should exist in buckets after save" do
97
+ @instance.save
98
+ @instance.instances.get(@instance.instance_id).should_not be_nil
99
+ @instance.destroy
100
+ end
101
+
102
+ end
103
+
104
+ describe "#volumes" do
105
+ it "should have tests"
106
+ end
107
+
108
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe 'Fog::AWS::EC2::Instances' do
4
+
5
+ describe "#all" do
6
+
7
+ it "should return a Fog::AWS::EC2::Instances" do
8
+ ec2.instances.all.should be_a(Fog::AWS::EC2::Instances)
9
+ end
10
+
11
+ it "should include persisted instances" do
12
+ instance = ec2.instances.create(:image_id => 'ami-5ee70037')
13
+ ec2.instances.get(instance.instance_id).should_not be_nil
14
+ instance.destroy
15
+ end
16
+
17
+ end
18
+
19
+ describe "#create" do
20
+
21
+ before(:each) do
22
+ @instance = ec2.instances.create(:image_id => 'ami-5ee70037')
23
+ end
24
+
25
+ after(:each) do
26
+ @instance.destroy
27
+ end
28
+
29
+ it "should return a Fog::AWS::EC2::Instance" do
30
+ @instance.should be_a(Fog::AWS::EC2::Instance)
31
+ end
32
+
33
+ it "should exist on ec2" do
34
+ ec2.instances.get(@instance.instance_id).should_not be_nil
35
+ end
36
+
37
+ end
38
+
39
+ describe "#get" do
40
+
41
+ it "should return a Fog::AWS::EC2::Instance if a matching instance exists" do
42
+ instance = ec2.instances.create(:image_id => 'ami-5ee70037')
43
+ get = ec2.instances.get(instance.instance_id)
44
+ instance.attributes.should == get.attributes
45
+ instance.destroy
46
+ end
47
+
48
+ it "should return nil if no matching instance exists" do
49
+ ec2.instances.get('i-00000000').should be_nil
50
+ end
51
+
52
+ end
53
+
54
+ describe "#new" do
55
+
56
+ it "should return a Fog::AWS::EC2::Instance" do
57
+ ec2.instances.new(:image_id => 'ami-5ee70037').should be_a(Fog::AWS::EC2::Instance)
58
+ end
59
+
60
+ end
61
+
62
+ describe "#reload" do
63
+
64
+ it "should return a Fog::AWS::EC2::Instances" do
65
+ ec2.instances.all.reload.should be_a(Fog::AWS::EC2::Instances)
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -4,14 +4,16 @@ describe 'Fog::AWS::EC2::KeyPair' do
4
4
 
5
5
  describe "#initialize" do
6
6
 
7
- it "should remap attributes from parser" #do
8
- # address = Fog::AWS::EC2::KeyPair.new(
9
- # 'instanceId' => 'i-00000000',
10
- # 'publicIp' => '0.0.0.0'
11
- # )
12
- # address.instance_id.should == 'i-00000000'
13
- # address.public_ip.should == '0.0.0.0'
14
- # end
7
+ it "should remap attributes from parser" do
8
+ key_pair = Fog::AWS::EC2::KeyPair.new(
9
+ 'keyFingerprint' => 'fingerprint',
10
+ 'keyMaterial' => 'material',
11
+ 'keyName' => 'name'
12
+ )
13
+ key_pair.fingerprint.should == 'fingerprint'
14
+ key_pair.material.should == 'material'
15
+ key_pair.name.should == 'name'
16
+ end
15
17
 
16
18
  end
17
19
 
@@ -4,14 +4,18 @@ describe 'Fog::AWS::EC2::SecurityGroup' do
4
4
 
5
5
  describe "#initialize" do
6
6
 
7
- it "should remap attributes from parser" #do
8
- # address = Fog::AWS::EC2::SecurityGroup.new(
9
- # 'instanceId' => 'i-00000000',
10
- # 'publicIp' => '0.0.0.0'
11
- # )
12
- # address.instance_id.should == 'i-00000000'
13
- # address.public_ip.should == '0.0.0.0'
14
- # end
7
+ it "should remap attributes from parser" do
8
+ security_group = Fog::AWS::EC2::SecurityGroup.new(
9
+ 'groupDescription' => 'description',
10
+ 'groupName' => 'name',
11
+ 'ipPermissions' => 'permissions',
12
+ 'ownerId' => 'owner'
13
+ )
14
+ security_group.group_description.should == 'description'
15
+ security_group.group_name.should == 'name'
16
+ security_group.ip_permissions.should == 'permissions'
17
+ security_group.owner_id.should == 'owner'
18
+ end
15
19
 
16
20
  end
17
21
 
@@ -4,14 +4,16 @@ describe 'Fog::AWS::EC2::Snapshots' do
4
4
 
5
5
  describe "#initialize" do
6
6
 
7
- it "should remap attributes from parser" # do
8
- # snapshot = Fog::AWS::EC2::Address.new(
9
- # 'instanceId' => 'i-00000000',
10
- # 'publicIp' => '0.0.0.0'
11
- # )
12
- # address.instance_id.should == 'i-00000000'
13
- # address.public_ip.should == '0.0.0.0'
14
- # end
7
+ it "should remap attributes from parser" do
8
+ snapshot = Fog::AWS::EC2::Snapshot.new(
9
+ 'snapshotId' => 'snap-00000000',
10
+ 'startTime' => 'now',
11
+ 'volumeId' => 'vol-00000000'
12
+ )
13
+ snapshot.snapshot_id.should == 'snap-00000000'
14
+ snapshot.start_time.should == 'now'
15
+ snapshot.volume_id.should == 'vol-00000000'
16
+ end
15
17
 
16
18
  end
17
19
 
@@ -11,8 +11,19 @@ describe 'Fog::AWS::EC2::Snapshots' do
11
11
  it "should include persisted snapshots" do
12
12
  volume = ec2.volumes.create
13
13
  snapshot = volume.snapshots.create
14
- ec2.snapshots.get(snapshot.snapshot_id).should_not be_nil
14
+ ec2.snapshots.all.map {|snapshot| snapshot.snapshot_id}.should include(snapshot.snapshot_id)
15
15
  snapshot.destroy
16
+ volume.destroy
17
+ end
18
+
19
+ it "should limit snapshots by volume_id if present" do
20
+ volume = ec2.volumes.create
21
+ other_volume = ec2.volumes.create
22
+ snapshot = volume.snapshots.create
23
+ other_volume.snapshots.all.map {|snapshot| snapshot.snapshot_id}.should_not include(snapshot.snapshot_id)
24
+ snapshot.destroy
25
+ other_volume.destroy
26
+ volume.destroy
16
27
  end
17
28
 
18
29
  end
@@ -4,14 +4,22 @@ describe 'Fog::AWS::EC2::Volume' do
4
4
 
5
5
  describe "#initialize" do
6
6
 
7
- it "should remap attributes from parser" # do
8
- # volume = Fog::AWS::EC2::Address.new(
9
- # 'instanceId' => 'i-00000000',
10
- # 'publicIp' => '0.0.0.0'
11
- # )
12
- # address.instance_id.should == 'i-00000000'
13
- # address.public_ip.should == '0.0.0.0'
14
- # end
7
+ it "should remap attributes from parser" do
8
+ volume = Fog::AWS::EC2::Volume.new(
9
+ 'attachmentTime' => 'now',
10
+ 'availabilityZone' => 'us-east-1a',
11
+ 'createTime' => 'recently',
12
+ 'instanceId' => 'i-00000000',
13
+ 'snapshotId' => 'snap-00000000',
14
+ 'volumeId' => 'vol-00000000'
15
+ )
16
+ volume.attachment_time.should == 'now'
17
+ volume.availability_zone.should == 'us-east-1a'
18
+ volume.create_time.should == 'recently'
19
+ volume.instance_id.should == 'i-00000000'
20
+ volume.snapshot_id.should == 'snap-00000000'
21
+ volume.volume_id.should == 'vol-00000000'
22
+ end
15
23
 
16
24
  end
17
25
 
@@ -96,7 +96,9 @@ describe 'Fog::AWS::S3::Objects' do
96
96
  file = File.open(File.dirname(__FILE__) + '/../../../lorem.txt', 'r')
97
97
  object = @bucket.objects.create(:key => 'fogobjectname', :body => file)
98
98
  url = @bucket.objects.get_url('fogobjectname', Time.now + 60 * 10)
99
- open(url).read.should == File.open(File.dirname(__FILE__) + '/../../../lorem.txt', 'r').read
99
+ unless Fog.mocking?
100
+ open(url).read.should == File.open(File.dirname(__FILE__) + '/../../../lorem.txt', 'r').read
101
+ end
100
102
  object.destroy
101
103
  end
102
104
 
@@ -38,7 +38,9 @@ describe 'S3.get_object' do
38
38
  it 'should return a signed expiring url' do
39
39
  url = s3.get_object_url('foggetobject', 'fog_get_object', Time.now + 60 * 10)
40
40
  file = File.open(File.dirname(__FILE__) + '/../../../lorem.txt', 'r')
41
- open(url).read.should == file.read
41
+ unless Fog.mocking?
42
+ open(url).read.should == file.read
43
+ end
42
44
  end
43
45
 
44
46
  end
@@ -3,7 +3,7 @@ require 'open-uri'
3
3
 
4
4
  current_directory = File.dirname(__FILE__)
5
5
  require "#{current_directory}/../lib/fog"
6
- # Fog.mock!
6
+ Fog.mock!
7
7
 
8
8
  def credentials
9
9
  @credentials ||= begin
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
- - Wesley Beary
7
+ - geemus (Wesley Beary)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-05 00:00:00 -07:00
12
+ date: 2009-10-09 00:00:00 -07:00
13
13
  default_executable: fog
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -172,6 +172,8 @@ files:
172
172
  - lib/fog/response.rb
173
173
  - spec/aws/models/ec2/address_spec.rb
174
174
  - spec/aws/models/ec2/addresses_spec.rb
175
+ - spec/aws/models/ec2/instance_spec.rb
176
+ - spec/aws/models/ec2/instances_spec.rb
175
177
  - spec/aws/models/ec2/key_pair_spec.rb
176
178
  - spec/aws/models/ec2/key_pairs_spec.rb
177
179
  - spec/aws/models/ec2/security_group_spec.rb
@@ -269,6 +271,8 @@ summary: fog = clouds + you
269
271
  test_files:
270
272
  - spec/aws/models/ec2/address_spec.rb
271
273
  - spec/aws/models/ec2/addresses_spec.rb
274
+ - spec/aws/models/ec2/instance_spec.rb
275
+ - spec/aws/models/ec2/instances_spec.rb
272
276
  - spec/aws/models/ec2/key_pair_spec.rb
273
277
  - spec/aws/models/ec2/key_pairs_spec.rb
274
278
  - spec/aws/models/ec2/security_group_spec.rb