boxgrinder-build 0.9.3 → 0.9.4
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 +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
|