boxgrinder-build 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Manifest +6 -5
- data/README.md +1 -1
- data/Rakefile +13 -20
- data/boxgrinder-build.gemspec +7 -10
- data/lib/boxgrinder-build/helpers/aws-helper.rb +81 -0
- data/lib/boxgrinder-build/helpers/ec2-helper.rb +182 -0
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +5 -1
- data/lib/boxgrinder-build/helpers/s3-helper.rb +124 -0
- data/lib/boxgrinder-build/plugins/delivery/ebs/ebs-plugin.rb +95 -299
- data/lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb +2 -1
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +67 -133
- data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin.rb +15 -14
- data/rubygem-boxgrinder-build.spec +23 -28
- data/spec/appliance-spec.rb +1 -0
- data/spec/helpers/augeas-helper-spec.rb +1 -0
- data/spec/helpers/ec2-helper-spec.rb +260 -0
- data/spec/helpers/guestfs-helper-spec.rb +34 -7
- data/spec/helpers/image-helper-spec.rb +1 -0
- data/spec/helpers/linux-helper-spec.rb +1 -0
- data/spec/helpers/package-helper-spec.rb +1 -0
- data/spec/helpers/plugin-helper-spec.rb +1 -0
- data/spec/helpers/s3-helper-spec.rb +168 -0
- data/spec/managers/plugin-manager-spec.rb +1 -0
- data/spec/plugins/base-plugin-spec.rb +1 -1
- data/spec/plugins/delivery/ebs/ebs-plugin-spec.rb +115 -204
- data/spec/plugins/delivery/elastichosts/elastichosts-plugin-spec.rb +5 -4
- data/spec/plugins/delivery/local/local-plugin-spec.rb +1 -0
- data/spec/plugins/delivery/s3/s3-plugin-spec.rb +143 -134
- data/spec/plugins/delivery/sftp/sftp-plugin-spec.rb +1 -0
- data/spec/plugins/os/centos/centos-plugin-spec.rb +1 -0
- data/spec/plugins/os/fedora/fedora-plugin-spec.rb +1 -0
- data/spec/plugins/os/rhel/rhel-plugin-spec.rb +1 -0
- data/spec/plugins/os/rpm-based/kickstart-spec.rb +5 -1
- data/spec/plugins/os/rpm-based/rpm-based-os-plugin-spec.rb +9 -7
- data/spec/plugins/os/rpm-based/rpm-dependency-validator-spec.rb +1 -0
- data/spec/plugins/os/sl/sl-plugin-spec.rb +1 -0
- data/spec/plugins/platform/ec2/ec2-plugin-spec.rb +1 -0
- data/spec/plugins/platform/virtualbox/virtualbox-plugin-spec.rb +1 -0
- data/spec/plugins/platform/vmware/vmware-plugin-spec.rb +1 -0
- metadata +17 -23
data/spec/appliance-spec.rb
CHANGED
@@ -0,0 +1,260 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'rspec'
|
20
|
+
require 'boxgrinder-build/helpers/ec2-helper'
|
21
|
+
require 'aws-sdk'
|
22
|
+
|
23
|
+
module BoxGrinder
|
24
|
+
describe EC2Helper do
|
25
|
+
|
26
|
+
FAST_POLL = 0.1
|
27
|
+
FAST_TO = 1
|
28
|
+
|
29
|
+
before(:each) do
|
30
|
+
AWS.stub!
|
31
|
+
AWS.config({:access_key_id => '', :secret_access_key => ''})
|
32
|
+
@ec2 = AWS::EC2.new()
|
33
|
+
@ec2helper = EC2Helper.new(@ec2)
|
34
|
+
@ami = mock(AWS::EC2::Image)
|
35
|
+
@instance = mock(AWS::EC2::Instance)
|
36
|
+
@snapshot = mock(AWS::EC2::Snapshot)
|
37
|
+
@volume = mock(AWS::EC2::Volume)
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ".wait_for_image_state" do
|
41
|
+
before(:each) do
|
42
|
+
@ami.stub!(:state).and_return(:ham, :biscuit, :available)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should wait until the image state is :available before returning" do
|
46
|
+
@ami.stub(:exists?).and_return(true)
|
47
|
+
|
48
|
+
@ami.should_receive(:exists?).once.and_return(true)
|
49
|
+
@ami.should_receive(:state).exactly(3).times
|
50
|
+
@ec2helper.wait_for_image_state(:available, @ami, :frequency => FAST_POLL, :timeout => FAST_TO)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should wait until the image exists before sampling for state" do
|
54
|
+
@ami.stub(:exists?).and_return(false, false, true)
|
55
|
+
|
56
|
+
@ami.should_receive(:exists?).once.exactly(3).times
|
57
|
+
@ami.should_receive(:state).exactly(3).times
|
58
|
+
@ec2helper.wait_for_image_state(:available, @ami, :frequency => FAST_POLL, :timeout => FAST_TO)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe ".wait_for_image_death" do
|
63
|
+
it "should wait until image no longer exists" do
|
64
|
+
@ami.stub!(:exists?).and_return(true, true, false)
|
65
|
+
|
66
|
+
@ami.should_receive(:exists?).exactly(3).times
|
67
|
+
@ec2helper.wait_for_image_death(@ami, :frequency => FAST_POLL, :timeout => FAST_TO)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return normally if InvalidImageID::NotFound error occurs" do
|
71
|
+
@ami.stub!(:exists?).and_raise(aws_sdk_exception_hack(AWS::EC2::Errors::InvalidImageID::NotFound))
|
72
|
+
|
73
|
+
@ami.should_receive(:exists?).once
|
74
|
+
@ec2helper.wait_for_image_death(@ami, :frequency => FAST_POLL, :timeout => FAST_TO)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".wait_for_instance_status" do
|
79
|
+
it "should wait until the instance status is :available before returning" do
|
80
|
+
@instance.stub!(:status).and_return(:bacon, :buttie, :available)
|
81
|
+
|
82
|
+
@instance.should_receive(:status).exactly(3).times
|
83
|
+
@ec2helper.wait_for_instance_status(:available, @instance, :frequency => FAST_POLL, :timeout => FAST_TO)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe ".wait_for_instance_death" do
|
88
|
+
it "should wait until instance status is :terminated before returning" do
|
89
|
+
@instance.stub!(:exists?).and_return(true)
|
90
|
+
@instance.stub!(:status).and_return(:stottie, :bread, :terminated)
|
91
|
+
|
92
|
+
@instance.should_receive(:status).exactly(3).times
|
93
|
+
@ec2helper.wait_for_instance_death(@instance, :frequency => FAST_POLL, :timeout => FAST_TO)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return normally if InvalidInstance::NotFound error occurs" do
|
97
|
+
@instance.stub!(:exists?).and_return(true)
|
98
|
+
@instance.stub!(:status).and_raise(aws_sdk_exception_hack(AWS::EC2::Errors::InvalidInstanceID::NotFound))
|
99
|
+
|
100
|
+
@instance.should_receive(:exists?).once
|
101
|
+
@instance.should_receive(:status).once
|
102
|
+
@ec2helper.wait_for_instance_death(@instance, :frequency => FAST_POLL, :timeout => FAST_TO)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return immediately if the instance does not appear to exist at all" do
|
106
|
+
@instance.stub!(:exists?).and_return(false)
|
107
|
+
|
108
|
+
@instance.should_receive(:exists?).once
|
109
|
+
@ec2helper.wait_for_instance_death(@instance, :frequency => FAST_POLL, :timeout => FAST_TO)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe ".wait_for_snapshot_status" do
|
114
|
+
it "should wait until the instance status is :completed before returning" do
|
115
|
+
@snapshot.stub!(:status).and_return(:crumpet, :tea, :completed, :cricket)
|
116
|
+
@snapshot.stub!(:progress).and_return(99)
|
117
|
+
|
118
|
+
@snapshot.should_receive(:status).exactly(3).times
|
119
|
+
@ec2helper.wait_for_snapshot_status(:completed, @snapshot, :frequency => FAST_POLL, :timeout => FAST_TO)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe ".wait_for_volume_status" do
|
124
|
+
it "should wait until the instance status is :available before returning" do
|
125
|
+
@volume.stub!(:status).and_return(:edictum, :imperatoris, :available)
|
126
|
+
|
127
|
+
@volume.should_receive(:status).exactly(3).times
|
128
|
+
@ec2helper.wait_for_volume_status(:available, @volume, :frequency => FAST_POLL, :timeout => FAST_TO)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe ".current_availability_zone" do
|
133
|
+
it "should return the current availability zone" do
|
134
|
+
EC2Helper.stub!(:get_meta_data).and_return('protuberant-potato-1a')
|
135
|
+
|
136
|
+
EC2Helper.should_receive(:get_meta_data).
|
137
|
+
with('/latest/meta-data/placement/availability-zone/').
|
138
|
+
and_return('protuberant-potato-1a')
|
139
|
+
EC2Helper.current_availability_zone.should == 'protuberant-potato-1a'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe ".current_instance_id" do
|
144
|
+
it "should return the current instance id" do
|
145
|
+
EC2Helper.stub!(:get_meta_data).and_return('voluminous-verbiage')
|
146
|
+
|
147
|
+
EC2Helper.should_receive(:get_meta_data).
|
148
|
+
with('/latest/meta-data/instance-id').
|
149
|
+
and_return('voluminous-verbiage')
|
150
|
+
EC2Helper.current_instance_id.should == 'voluminous-verbiage'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe ".availability_zone_to_region" do
|
155
|
+
it "should convert an availability zone to a region" do
|
156
|
+
EC2Helper.availability_zone_to_region('protuberant-potato-1a').
|
157
|
+
should == 'protuberant-potato-1'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe ".ami_by_name" do
|
162
|
+
before(:each) do
|
163
|
+
@ec2.stub!(:images)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should query for an image filtered by name" do
|
167
|
+
@ec2.should_receive(:images)
|
168
|
+
@ec2.images.should_receive(:with_owner).with('987654321')
|
169
|
+
@ec2.images.should_receive(:filter).with('name','inauspicious-interlocution').and_return([@ami])
|
170
|
+
|
171
|
+
@ec2helper.ami_by_name('inauspicious-interlocution', '987654321').should == @ami
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should return nil if no results are returned" do
|
175
|
+
@ec2.should_receive(:images)
|
176
|
+
@ec2.images.should_receive(:with_owner).with('987654321')
|
177
|
+
@ec2.images.should_receive(:filter).with('name','inauspicious-interlocution').and_return([])
|
178
|
+
|
179
|
+
@ec2helper.ami_by_name('inauspicious-interlocution', '987654321').should == nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe ".snapshot_by_id" do
|
184
|
+
before(:each) do
|
185
|
+
snap_mock = mock('snapshots')
|
186
|
+
@ec2.stub!(:snapshots).and_return(snap_mock)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should query for a snapshot by snapshot-id" do
|
190
|
+
|
191
|
+
@ec2.snapshots.
|
192
|
+
should_receive(:filter).
|
193
|
+
with('snapshot-id','count-bezukhov').
|
194
|
+
and_return([@snapshot])
|
195
|
+
|
196
|
+
@ec2helper.snapshot_by_id('count-bezukhov').should == @snapshot
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should return nil if no results are returned" do
|
201
|
+
@ec2.snapshots.
|
202
|
+
should_receive(:filter).
|
203
|
+
with('snapshot-id','count-bezukhov').
|
204
|
+
and_return([])
|
205
|
+
|
206
|
+
@ec2helper.snapshot_by_id('count-bezukhov').should == nil
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
describe ".live_instances" do
|
212
|
+
before(:each) do
|
213
|
+
instances_mock = mock('instances')
|
214
|
+
@ec2.stub!(:instances).and_return(instances_mock)
|
215
|
+
|
216
|
+
@instance_1 = mock(AWS::EC2::Instance)
|
217
|
+
@instance_2 = mock(AWS::EC2::Instance)
|
218
|
+
@instance_3 = mock(AWS::EC2::Instance)
|
219
|
+
|
220
|
+
@instance_1.stub!(:status).and_return(:available)
|
221
|
+
@instance_2.stub!(:status).and_return(:available)
|
222
|
+
@ami.stub!(:id).and_return('war-and-peace')
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should query for live instances by ami" do
|
226
|
+
@ec2.instances.
|
227
|
+
should_receive(:filter).
|
228
|
+
with('image-id','war-and-peace').
|
229
|
+
and_return([@instance_1, @instance_2])
|
230
|
+
|
231
|
+
@ec2helper.live_instances(@ami).should == [@instance_1, @instance_2]
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should ignore any :terminated instances" do
|
235
|
+
@instance_3.stub!(:status).and_return(:terminated)
|
236
|
+
|
237
|
+
@ec2.should_receive(:instances)
|
238
|
+
@ec2.instances.should_receive(:filter).
|
239
|
+
with('image-id','war-and-peace').
|
240
|
+
and_return([@instance_3, @instance_2, @instance_1])
|
241
|
+
|
242
|
+
@ec2helper.live_instances(@ami).should == [@instance_2, @instance_1]
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
describe ".endpoints" do
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
# Complex auto-generated exceptions means we can't use the normal method of raising
|
252
|
+
def aws_sdk_exception_hack(klass)
|
253
|
+
mock_param = mock('fake_param')
|
254
|
+
mock_param.stub!(:status).and_return(1)
|
255
|
+
mock_param.stub!(:body).and_return('')
|
256
|
+
klass.new(mock_param, mock_param)
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
end
|
@@ -16,18 +16,22 @@
|
|
16
16
|
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
17
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
18
|
|
19
|
-
require 'rubygems'
|
20
19
|
require 'boxgrinder-build/helpers/guestfs-helper'
|
20
|
+
require 'rubygems'
|
21
|
+
require 'rspec'
|
22
|
+
require 'hashery/opencascade'
|
21
23
|
|
22
24
|
module BoxGrinder
|
23
25
|
describe GuestFSHelper do
|
24
26
|
before(:each) do
|
27
|
+
ENV.delete("LIBGUESTFS_MEMSIZE")
|
28
|
+
|
25
29
|
@log = Logger.new('/dev/null')
|
26
30
|
@appliance_config = mock('ApplianceConfig')
|
27
31
|
@appliance_config.stub!(:hardware).and_return(:partitions => {})
|
28
32
|
|
29
33
|
@config = mock('Config')
|
30
|
-
@config.stub!(:dir).and_return(:tmp => '/tmp')
|
34
|
+
@config.stub!(:dir).and_return(OpenCascade.new(:tmp => '/tmp'))
|
31
35
|
|
32
36
|
@helper = GuestFSHelper.new('a/raw/disk', @appliance_config, @config, :log => @log)
|
33
37
|
end
|
@@ -41,6 +45,7 @@ module BoxGrinder
|
|
41
45
|
guestfs.should_receive(:set_verbose)
|
42
46
|
guestfs.should_receive(:set_trace)
|
43
47
|
guestfs.should_receive(:set_selinux).with(1)
|
48
|
+
guestfs.should_receive(:set_memsize).with(300)
|
44
49
|
|
45
50
|
@helper.should_receive(:hw_virtualization_available?).and_return(true)
|
46
51
|
|
@@ -59,6 +64,7 @@ module BoxGrinder
|
|
59
64
|
guestfs.should_receive(:set_verbose)
|
60
65
|
guestfs.should_receive(:set_trace)
|
61
66
|
guestfs.should_receive(:set_selinux).with(1)
|
67
|
+
guestfs.should_receive(:set_memsize).with(300)
|
62
68
|
|
63
69
|
@helper.should_receive(:hw_virtualization_available?).and_return(true)
|
64
70
|
|
@@ -76,6 +82,7 @@ module BoxGrinder
|
|
76
82
|
guestfs.should_receive(:set_verbose)
|
77
83
|
guestfs.should_receive(:set_trace)
|
78
84
|
guestfs.should_receive(:set_selinux).with(1)
|
85
|
+
guestfs.should_receive(:set_memsize).with(300)
|
79
86
|
|
80
87
|
@helper.should_receive(:hw_virtualization_available?).and_return(false)
|
81
88
|
|
@@ -85,6 +92,26 @@ module BoxGrinder
|
|
85
92
|
|
86
93
|
@helper.prepare_guestfs {}
|
87
94
|
end
|
95
|
+
|
96
|
+
it "should prepare guestfs with custom memory settings" do
|
97
|
+
ENV['LIBGUESTFS_MEMSIZE'] = "500"
|
98
|
+
|
99
|
+
guestfs = mock('Guestfs')
|
100
|
+
@helper.instance_variable_set(:@guestfs, guestfs)
|
101
|
+
|
102
|
+
guestfs.should_receive(:set_append).with('noapic')
|
103
|
+
guestfs.should_receive(:set_verbose)
|
104
|
+
guestfs.should_receive(:set_trace)
|
105
|
+
guestfs.should_receive(:set_selinux).with(1)
|
106
|
+
guestfs.should_receive(:set_memsize).with(500)
|
107
|
+
|
108
|
+
@helper.should_receive(:hw_virtualization_available?).and_return(true)
|
109
|
+
|
110
|
+
guestfs.should_receive(:add_drive).with('a/raw/disk')
|
111
|
+
guestfs.should_receive(:set_network).with(1)
|
112
|
+
|
113
|
+
@helper.prepare_guestfs {}
|
114
|
+
end
|
88
115
|
end
|
89
116
|
|
90
117
|
describe ".initialize_guestfs" do
|
@@ -129,7 +156,7 @@ module BoxGrinder
|
|
129
156
|
end
|
130
157
|
|
131
158
|
it "should run guestfs with two partitions" do
|
132
|
-
@appliance_config.stub!(:hardware).and_return(:partitions => {'/' => nil, '/home' => nil})
|
159
|
+
@appliance_config.stub!(:hardware).and_return(OpenCascade.new(:partitions => {'/' => nil, '/home' => nil}))
|
133
160
|
|
134
161
|
guestfs = mock('Guestfs')
|
135
162
|
@helper.instance_variable_set(:@guestfs, guestfs)
|
@@ -145,7 +172,7 @@ module BoxGrinder
|
|
145
172
|
end
|
146
173
|
|
147
174
|
it "should run guestfs with no partitions and don't load selinux" do
|
148
|
-
@appliance_config.stub!(:hardware).and_return(:partitions => {'/' => nil, '/home' => nil})
|
175
|
+
@appliance_config.stub!(:hardware).and_return(OpenCascade.new(:partitions => {'/' => nil, '/home' => nil}))
|
149
176
|
|
150
177
|
guestfs = mock('Guestfs')
|
151
178
|
@helper.instance_variable_set(:@guestfs, guestfs)
|
@@ -199,7 +226,7 @@ module BoxGrinder
|
|
199
226
|
it "should mount two partitions" do
|
200
227
|
guestfs = mock('Guestfs')
|
201
228
|
|
202
|
-
@appliance_config.stub!(:hardware).and_return(:partitions => {'/' => nil, '/home' => nil})
|
229
|
+
@appliance_config.stub!(:hardware).and_return(OpenCascade.new(:partitions => {'/' => nil, '/home' => nil}))
|
203
230
|
guestfs.should_receive(:list_partitions).and_return(['/dev/vda1', '/dev/vda2'])
|
204
231
|
|
205
232
|
@helper.should_receive(:mount_partition).with('/dev/vda1', '/', '')
|
@@ -212,7 +239,7 @@ module BoxGrinder
|
|
212
239
|
it "should mount partitions with extended partitions" do
|
213
240
|
guestfs = mock('Guestfs')
|
214
241
|
|
215
|
-
@appliance_config.stub!(:hardware).and_return(:partitions => {'/' => nil, '/home' => nil, '/var/www' => nil, '/var/mock' => nil})
|
242
|
+
@appliance_config.stub!(:hardware).and_return(OpenCascade.new(:partitions => {'/' => nil, '/home' => nil, '/var/www' => nil, '/var/mock' => nil}))
|
216
243
|
guestfs.should_receive(:list_partitions).and_return(['/dev/vda1', '/dev/vda2', '/dev/vda3', '/dev/vda4', '/dev/vda5'])
|
217
244
|
|
218
245
|
@helper.should_receive(:mount_partition).with('/dev/vda1', '/', '')
|
@@ -370,4 +397,4 @@ module BoxGrinder
|
|
370
397
|
end
|
371
398
|
end
|
372
399
|
end
|
373
|
-
end
|
400
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'rspec'
|
21
|
+
require 'boxgrinder-build/helpers/s3-helper'
|
22
|
+
require 'aws-sdk'
|
23
|
+
|
24
|
+
module BoxGrinder
|
25
|
+
describe S3Helper do
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
AWS.stub!
|
29
|
+
AWS.config({:access_key_id => '', :secret_access_key => ''})
|
30
|
+
@ec2 = AWS::EC2.new
|
31
|
+
@s3 = AWS::S3.new
|
32
|
+
@ec2helper = EC2Helper.new(@ec2)
|
33
|
+
@s3helper = S3Helper.new(@ec2, @s3)
|
34
|
+
@s3obj = mock(AWS::S3::S3Object)
|
35
|
+
@bucket = mock(AWS::S3::Bucket)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".bucket" do
|
39
|
+
|
40
|
+
it "should return the existing bucket if it already exists" do
|
41
|
+
@bucket.stub!(:exists).and_return(true)
|
42
|
+
@s3.stub_chain(:buckets, :[]).and_return(@bucket)
|
43
|
+
|
44
|
+
@s3.buckets.should_receive(:[]).with('tolstoy').and_return(@bucket)
|
45
|
+
@bucket.should_receive(:exists?).and_return(true)
|
46
|
+
|
47
|
+
@s3helper.bucket(:bucket => 'tolstoy').should == @bucket
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when the bucket does not yet exist" do
|
51
|
+
|
52
|
+
before(:each) do
|
53
|
+
@bucket.stub!(:exists).and_return(false)
|
54
|
+
@s3.stub_chain(:buckets, :[]).and_return(@bucket)
|
55
|
+
@s3.stub_chain(:buckets, :create).and_return(@bucket_real)
|
56
|
+
|
57
|
+
@bucket_real = mock(AWS::S3::Bucket)
|
58
|
+
@bucket_real.stub!(:exists).and_return(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
context ":create_if_missing" do
|
62
|
+
|
63
|
+
it "should return nil if :create_if_missing is not set" do
|
64
|
+
@s3.buckets.should_receive(:[]).with('tolstoy').and_return(@bucket)
|
65
|
+
@bucket.should_receive(:exists?).once.and_return(false)
|
66
|
+
@s3helper.bucket(:bucket => 'tolstoy').should == nil
|
67
|
+
end
|
68
|
+
|
69
|
+
context "When :create_if_missing is set" do
|
70
|
+
|
71
|
+
it "should return a bucket, with other settings defaulted" do
|
72
|
+
@s3.buckets.should_receive(:[]).with('tolstoy').and_return(@bucket)
|
73
|
+
@bucket.should_receive(:exists?).once.and_return(false)
|
74
|
+
@s3.buckets.
|
75
|
+
should_receive(:create).
|
76
|
+
once.
|
77
|
+
with('tolstoy', :acl => :private, :location_constraint => 'us-east-1').
|
78
|
+
and_return(@bucket_real)
|
79
|
+
|
80
|
+
@s3helper.bucket(:bucket => 'tolstoy', :create_if_missing => true).should == @bucket_real
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return a bucket assigned with the attributes provided by the user" do
|
84
|
+
@s3.buckets.should_receive(:[]).with('tolstoy').and_return(@bucket)
|
85
|
+
@bucket.should_receive(:exists?).once.and_return(false)
|
86
|
+
@s3.buckets.
|
87
|
+
should_receive(:create).
|
88
|
+
once.
|
89
|
+
with('tolstoy', :acl => :ham, :location_constraint => 'biscuit').
|
90
|
+
and_return(@bucket_real)
|
91
|
+
|
92
|
+
@s3helper.bucket(:bucket => 'tolstoy', :create_if_missing => true,
|
93
|
+
:acl => :ham, :location_constraint => 'biscuit').should == @bucket_real
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe ".object_exists?" do
|
102
|
+
|
103
|
+
it "should return true if the object exists" do
|
104
|
+
@s3obj.stub!(:exists?).and_return(true)
|
105
|
+
@s3obj.should_receive(:exists?).and_return(true)
|
106
|
+
@s3helper.object_exists?(@s3obj).should == true
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return false if the object does not exist" do
|
110
|
+
@s3obj.stub!(:exists?).and_return(false)
|
111
|
+
@s3obj.should_receive(:exists?).and_return(false)
|
112
|
+
@s3helper.object_exists?(@s3obj).should == false
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe ".delete_folder" do
|
118
|
+
|
119
|
+
it "should delete a folder from a bucket" do
|
120
|
+
object = mock(AWS::S3::S3Object)
|
121
|
+
objects = [object]
|
122
|
+
|
123
|
+
@bucket.stub!(:objects)
|
124
|
+
@bucket.objects.
|
125
|
+
should_receive(:with_prefix).
|
126
|
+
with('cacoethes/carpendi').
|
127
|
+
and_return(objects)
|
128
|
+
|
129
|
+
object.should_receive(:delete).once
|
130
|
+
|
131
|
+
@s3helper.delete_folder(@bucket, '/cacoethes/carpendi/')
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe ".stub_s3obj" do
|
137
|
+
|
138
|
+
it "should return a stub AWS::S3::S3Object associated with the specified bucket" do
|
139
|
+
object = mock(AWS::S3::S3Object)
|
140
|
+
objects = mock(AWS::S3::ObjectCollection)
|
141
|
+
objects.stub!(:[]).and_return(object)
|
142
|
+
objects.stub!(:to_sym).and_return(:anything)
|
143
|
+
|
144
|
+
@bucket.stub!(objects).and_return(objects)
|
145
|
+
@bucket.should_receive(:objects).and_return(objects)
|
146
|
+
objects.should_receive(:[]).and_return(object)
|
147
|
+
|
148
|
+
@s3helper.stub_s3obj(@bucket, 'vini/vidi/vici') == @s3obj
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe ".parse_path" do
|
154
|
+
|
155
|
+
it "should return root if is empty" do
|
156
|
+
@s3helper.parse_path('').should == '/'
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should remove extranous slashes" do
|
160
|
+
@s3helper.parse_path('//cave/canem//').
|
161
|
+
should == 'cave/canem/'
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|