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.
Files changed (41) hide show
  1. data/CHANGELOG +12 -0
  2. data/Manifest +6 -5
  3. data/README.md +1 -1
  4. data/Rakefile +13 -20
  5. data/boxgrinder-build.gemspec +7 -10
  6. data/lib/boxgrinder-build/helpers/aws-helper.rb +81 -0
  7. data/lib/boxgrinder-build/helpers/ec2-helper.rb +182 -0
  8. data/lib/boxgrinder-build/helpers/guestfs-helper.rb +5 -1
  9. data/lib/boxgrinder-build/helpers/s3-helper.rb +124 -0
  10. data/lib/boxgrinder-build/plugins/delivery/ebs/ebs-plugin.rb +95 -299
  11. data/lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb +2 -1
  12. data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +67 -133
  13. data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin.rb +15 -14
  14. data/rubygem-boxgrinder-build.spec +23 -28
  15. data/spec/appliance-spec.rb +1 -0
  16. data/spec/helpers/augeas-helper-spec.rb +1 -0
  17. data/spec/helpers/ec2-helper-spec.rb +260 -0
  18. data/spec/helpers/guestfs-helper-spec.rb +34 -7
  19. data/spec/helpers/image-helper-spec.rb +1 -0
  20. data/spec/helpers/linux-helper-spec.rb +1 -0
  21. data/spec/helpers/package-helper-spec.rb +1 -0
  22. data/spec/helpers/plugin-helper-spec.rb +1 -0
  23. data/spec/helpers/s3-helper-spec.rb +168 -0
  24. data/spec/managers/plugin-manager-spec.rb +1 -0
  25. data/spec/plugins/base-plugin-spec.rb +1 -1
  26. data/spec/plugins/delivery/ebs/ebs-plugin-spec.rb +115 -204
  27. data/spec/plugins/delivery/elastichosts/elastichosts-plugin-spec.rb +5 -4
  28. data/spec/plugins/delivery/local/local-plugin-spec.rb +1 -0
  29. data/spec/plugins/delivery/s3/s3-plugin-spec.rb +143 -134
  30. data/spec/plugins/delivery/sftp/sftp-plugin-spec.rb +1 -0
  31. data/spec/plugins/os/centos/centos-plugin-spec.rb +1 -0
  32. data/spec/plugins/os/fedora/fedora-plugin-spec.rb +1 -0
  33. data/spec/plugins/os/rhel/rhel-plugin-spec.rb +1 -0
  34. data/spec/plugins/os/rpm-based/kickstart-spec.rb +5 -1
  35. data/spec/plugins/os/rpm-based/rpm-based-os-plugin-spec.rb +9 -7
  36. data/spec/plugins/os/rpm-based/rpm-dependency-validator-spec.rb +1 -0
  37. data/spec/plugins/os/sl/sl-plugin-spec.rb +1 -0
  38. data/spec/plugins/platform/ec2/ec2-plugin-spec.rb +1 -0
  39. data/spec/plugins/platform/virtualbox/virtualbox-plugin-spec.rb +1 -0
  40. data/spec/plugins/platform/vmware/vmware-plugin-spec.rb +1 -0
  41. metadata +17 -23
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'boxgrinder-build/appliance'
21
22
  require 'ostruct'
22
23
  require 'logger'
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'boxgrinder-build/helpers/augeas-helper'
21
22
 
22
23
  module BoxGrinder
@@ -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
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'boxgrinder-build/helpers/image-helper'
21
22
 
22
23
  module BoxGrinder
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'boxgrinder-build/helpers/linux-helper'
21
22
 
22
23
  module BoxGrinder
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'logger'
21
22
  require 'boxgrinder-build/helpers/package-helper'
22
23
 
@@ -17,6 +17,7 @@
17
17
  # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18
18
 
19
19
  require 'rubygems'
20
+ require 'rspec'
20
21
  require 'boxgrinder-core/helpers/log-helper'
21
22
  require 'boxgrinder-build/helpers/plugin-helper'
22
23
  require 'ostruct'
@@ -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