blobstore_client 0.5.0 → 1.5.0.pre.1113

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile DELETED
@@ -1,49 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- $:.unshift(File.expand_path("../../rake", __FILE__))
4
-
5
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __FILE__)
6
-
7
- require "rubygems"
8
- require "bundler"
9
- Bundler.setup(:default, :test)
10
-
11
- require "rake"
12
- begin
13
- require "rspec/core/rake_task"
14
- rescue LoadError
15
- end
16
-
17
- require "bundler_task"
18
- require "ci_task"
19
-
20
- gem_helper = Bundler::GemHelper.new(Dir.pwd)
21
-
22
- desc "Build Blobstore Client gem into the pkg directory"
23
- task "build" do
24
- gem_helper.build_gem
25
- end
26
-
27
- desc "Build and install Blobstore Client into system gems"
28
- task "install" do
29
- gem_helper.install_gem
30
- end
31
-
32
- BundlerTask.new
33
-
34
- if defined?(RSpec)
35
- namespace :spec do
36
- desc "Run Unit Tests"
37
- rspec_task = RSpec::Core::RakeTask.new(:unit) do |t|
38
- t.pattern = "spec/unit/**/*_spec.rb"
39
- t.rspec_opts = %w(--format progress --colour)
40
- end
41
-
42
- CiTask.new do |task|
43
- task.rspec_task = rspec_task
44
- end
45
- end
46
-
47
- desc "Install dependencies and run tests"
48
- task :spec => %w(spec:unit)
49
- end
data/spec/assets/file DELETED
@@ -1 +0,0 @@
1
- foobar
data/spec/spec_helper.rb DELETED
@@ -1,8 +0,0 @@
1
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
2
-
3
- require "rubygems"
4
- require "bundler"
5
- Bundler.setup(:default, :test)
6
-
7
- require "rspec"
8
- require "blobstore_client"
@@ -1,72 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- describe Bosh::Blobstore::AtmosBlobstoreClient do
4
-
5
- before(:each) do
6
- @atmos = mock("atmos")
7
- Atmos::Store.stub!(:new).and_return(@atmos)
8
- atmos_opt = {:url => "http://localhost",
9
- :uid => "uid",
10
- :secret => "secret"}
11
-
12
- @http_client = mock("http-client")
13
- ssl_opt = mock("ssl-opt")
14
- ssl_opt.stub!(:verify_mode=)
15
- @http_client.stub!(:ssl_config).and_return(ssl_opt)
16
-
17
- HTTPClient.stub!(:new).and_return(@http_client)
18
- @client = Bosh::Blobstore::AtmosBlobstoreClient.new(atmos_opt)
19
- end
20
-
21
- it "should create an object" do
22
- data = "some content"
23
- object = mock("object")
24
-
25
- @atmos.should_receive(:create).with {|opt|
26
- opt[:data].read.should eql data
27
- opt[:length].should eql data.length
28
- }.and_return(object)
29
-
30
- object.should_receive(:aoid).and_return("test-key")
31
-
32
- object_id = @client.create(data)
33
- object_info = MultiJson.decode(Base64.decode64(URI::unescape(object_id)))
34
- object_info["oid"].should eql("test-key")
35
- object_info["sig"].should_not be_nil
36
- end
37
-
38
- it "should delete an object" do
39
- object = mock("object")
40
- @atmos.should_receive(:get).with(:id => "test-key").and_return(object)
41
- object.should_receive(:delete)
42
- id = URI::escape(Base64.encode64(MultiJson.encode({:oid => "test-key", :sig => "sig"})))
43
- @client.delete(id)
44
- end
45
-
46
- it "should fetch an object" do
47
- url = "http://localhost/rest/objects/test-key?uid=uid&expires=1893484800&signature=sig"
48
- response = mock("response")
49
- response.stub!(:status).and_return(200)
50
- @http_client.should_receive(:get).with(url).and_yield("some-content").and_return(response)
51
- id = URI::escape(Base64.encode64(MultiJson.encode({:oid => "test-key", :sig => "sig"})))
52
- @client.get(id).should eql("some-content")
53
- end
54
-
55
- it "should refuse to create object without the password" do
56
- lambda {
57
- no_pass_client = Bosh::Blobstore::AtmosBlobstoreClient.new(:url => "http://localhost", :uid => "uid")
58
- no_pass_client.create("foo")
59
- }.should raise_error(Bosh::Blobstore::BlobstoreError)
60
- end
61
-
62
- it "should be able to read without password" do
63
- no_pass_client = Bosh::Blobstore::AtmosBlobstoreClient.new(:url => "http://localhost", :uid => "uid")
64
-
65
- url = "http://localhost/rest/objects/test-key?uid=uid&expires=1893484800&signature=sig"
66
- response = mock("response")
67
- response.stub!(:status).and_return(200)
68
- @http_client.should_receive(:get).with(url).and_yield("some-content").and_return(response)
69
- id = URI::escape(Base64.encode64(MultiJson.encode({:oid => "test-key", :sig => "sig"})))
70
- no_pass_client.get(id).should eql("some-content")
71
- end
72
- end
@@ -1,44 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- describe Bosh::Blobstore::Client do
4
-
5
- it "should have a local provider" do
6
- Dir.mktmpdir do |tmp|
7
- bs = Bosh::Blobstore::Client.create('local', {:blobstore_path => tmp})
8
- bs.should be_instance_of Bosh::Blobstore::LocalClient
9
- end
10
- end
11
-
12
- it "should have an simple provider" do
13
- bs = Bosh::Blobstore::Client.create('simple', {})
14
- bs.should be_instance_of Bosh::Blobstore::SimpleBlobstoreClient
15
- end
16
-
17
- it "should have an atmos provider" do
18
- bs = Bosh::Blobstore::Client.create('atmos', {})
19
- bs.should be_instance_of Bosh::Blobstore::AtmosBlobstoreClient
20
- end
21
-
22
- it "should have an s3 provider" do
23
- options = {:access_key_id => "foo", :secret_access_key => "bar"}
24
- bs = Bosh::Blobstore::Client.create('s3', options)
25
- bs.should be_instance_of Bosh::Blobstore::S3BlobstoreClient
26
- end
27
-
28
- it "should pick S3 provider when S3 is used without credentials" do
29
- bs = Bosh::Blobstore::Client.create('s3', {:bucket_name => "foo"})
30
- bs.should be_instance_of Bosh::Blobstore::S3BlobstoreClient
31
- end
32
-
33
- it "should have an swift provider" do
34
- bs = Bosh::Blobstore::Client.create('swift', {})
35
- bs.should be_instance_of Bosh::Blobstore::SwiftBlobstoreClient
36
- end
37
-
38
- it "should raise an exception on an unknown client" do
39
- lambda {
40
- bs = Bosh::Blobstore::Client.create('foobar', {})
41
- }.should raise_error /^Invalid client provider/
42
- end
43
-
44
- end
@@ -1,78 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- describe Bosh::Blobstore::LocalClient do
4
-
5
- before(:each) do
6
- @tmp = Dir.mktmpdir
7
- @options = {"blobstore_path" => @tmp}
8
- end
9
-
10
- after(:each) do
11
- FileUtils.rm_rf(@tmp)
12
- end
13
-
14
- it "should require blobstore_path option" do
15
- lambda {
16
- client = Bosh::Blobstore::LocalClient.new({})
17
- }.should raise_error
18
- end
19
-
20
- it "should create blobstore_path direcory if it doesn't exist'" do
21
- dir = File.join(@tmp, "blobstore")
22
- client = Bosh::Blobstore::LocalClient.new({"blobstore_path" => dir})
23
- File.directory?(dir).should be_true
24
- end
25
-
26
- describe "operations" do
27
-
28
- describe "get" do
29
- it "should retrive the correct contents" do
30
- File.open(File.join(@tmp, 'foo'), 'w') do |fh|
31
- fh.puts("bar")
32
- end
33
-
34
- client = Bosh::Blobstore::LocalClient.new(@options)
35
- client.get("foo").should == "bar\n"
36
- end
37
- end
38
-
39
- describe "create" do
40
- it "should store a file" do
41
- test_file = File.join(File.dirname(__FILE__), "../assets/file")
42
- client = Bosh::Blobstore::LocalClient.new(@options)
43
- fh = File.open(test_file)
44
- id = client.create(fh)
45
- fh.close
46
- original = File.new(test_file).readlines
47
- stored = File.new(File.join(@tmp, id)).readlines
48
- stored.should == original
49
- end
50
-
51
- it "should store a string" do
52
- client = Bosh::Blobstore::LocalClient.new(@options)
53
- string = "foobar"
54
- id = client.create(string)
55
- stored = File.new(File.join(@tmp, id)).readlines
56
- stored.should == [string]
57
- end
58
- end
59
-
60
- describe "delete" do
61
- it "should delete an id" do
62
- client = Bosh::Blobstore::LocalClient.new(@options)
63
- string = "foobar"
64
- id = client.create(string)
65
- client.delete(id)
66
- File.exist?(File.join(@tmp, id)).should_not be_true
67
- end
68
-
69
- it "should raise NotFound error when trying to delete a missing id" do
70
- client = Bosh::Blobstore::LocalClient.new(@options)
71
- lambda {
72
- client.delete("missing")
73
- }.should raise_error Bosh::Blobstore::NotFound
74
- end
75
- end
76
-
77
- end
78
- end
@@ -1,282 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- describe Bosh::Blobstore::S3BlobstoreClient do
4
-
5
- before(:each) do
6
- @aws_mock_options = {
7
- :access_key_id => "KEY",
8
- :secret_access_key => "SECRET",
9
- :use_ssl => true,
10
- :port => 443
11
- }
12
- end
13
-
14
- def s3_blobstore(options)
15
- Bosh::Blobstore::S3BlobstoreClient.new(options)
16
- end
17
-
18
- describe "read only mode" do
19
- it "does not establish S3 connection on creation" do
20
- AWS::S3::Base.should_not_receive(:establish_connection!)
21
- @client = s3_blobstore("bucket_name" => "test")
22
- end
23
-
24
- it "should raise an error on deletion" do
25
- @client = s3_blobstore("bucket_name" => "test")
26
- lambda {
27
- @client.delete("id")
28
- }.should raise_error "unsupported action"
29
- end
30
-
31
- it "should raise an error on creation" do
32
- @client = s3_blobstore("bucket_name" => "test")
33
- lambda {
34
- @client.create("id")
35
- }.should raise_error "unsupported action"
36
- end
37
-
38
- it "should fetch objects" do
39
- simple = mock("simple", :to_ary => nil, :get_file => %w[foo id])
40
- Bosh::Blobstore::SimpleBlobstoreClient.should_receive(:new).and_return(simple)
41
- @client = s3_blobstore("bucket_name" => "test")
42
- @client.get_file("foo", "id")
43
- end
44
- end
45
-
46
- describe "options" do
47
-
48
- it "establishes S3 connection on creation" do
49
- AWS::S3::Base.should_receive(:establish_connection!).with(@aws_mock_options)
50
-
51
- @client = s3_blobstore("encryption_key" => "bla",
52
- "bucket_name" => "test",
53
- "access_key_id" => "KEY",
54
- "secret_access_key" => "SECRET")
55
-
56
- @client.encryption_key.should == "bla"
57
- @client.bucket_name.should == "test"
58
- end
59
-
60
- it "supports Symbol option keys too" do
61
- AWS::S3::Base.should_receive(:establish_connection!).with(@aws_mock_options)
62
-
63
- @client = s3_blobstore(:encryption_key => "bla",
64
- :bucket_name => "test",
65
- :access_key_id => "KEY",
66
- :secret_access_key => "SECRET")
67
-
68
- @client.encryption_key.should == "bla"
69
- @client.bucket_name.should == "test"
70
- end
71
- end
72
-
73
- describe "operations" do
74
-
75
- before :each do
76
- @client = s3_blobstore(:encryption_key => "bla",
77
- :bucket_name => "test",
78
- :access_key_id => "KEY",
79
- :secret_access_key => "SECRET")
80
- end
81
-
82
- describe "create" do
83
-
84
- it "should create an object" do
85
- encrypted_file = nil
86
- @client.should_receive(:generate_object_id).and_return("object_id")
87
- @client.should_receive(:encrypt_stream).with { |from_file, _|
88
- from_file.read.should eql("some content")
89
- true
90
- }.and_return {|_, to_file|
91
- encrypted_file = to_file
92
- nil
93
- }
94
-
95
- AWS::S3::S3Object.should_receive(:store).with { |key, data, bucket|
96
- key.should eql("object_id")
97
- data.path.should eql(encrypted_file.path)
98
- bucket.should eql("test")
99
- true
100
- }
101
- @client.create("some content").should eql("object_id")
102
- end
103
-
104
- it "should not encrypt when encryption key is missing" do
105
- client = s3_blobstore(:bucket_name => "test",
106
- :access_key_id => "KEY",
107
- :secret_access_key => "SECRET")
108
- client.should_receive(:generate_object_id).and_return("object_id")
109
- client.should_not_receive(:encrypt_stream)
110
-
111
- AWS::S3::S3Object.should_receive(:store)
112
- client.create("some content").should eql("object_id")
113
- end
114
-
115
- it "should raise an exception when there is an error creating an object" do
116
- encrypted_file = nil
117
- @client.should_receive(:generate_object_id).and_return("object_id")
118
- @client.should_receive(:encrypt_stream).with { |from_file, _|
119
- from_file.read.should eql("some content")
120
- true
121
- }.and_return {|_, to_file|
122
- encrypted_file = to_file
123
- nil
124
- }
125
-
126
- AWS::S3::S3Object.should_receive(:store).with { |key, data, bucket|
127
- key.should eql("object_id")
128
- data.path.should eql(encrypted_file.path)
129
- bucket.should eql("test")
130
- true
131
- }.and_raise(AWS::S3::S3Exception.new("Epic Fail"))
132
- lambda {
133
- @client.create("some content")
134
- }.should raise_error(Bosh::Blobstore::BlobstoreError, "Failed to create object, S3 response error: Epic Fail")
135
- end
136
-
137
- end
138
-
139
- describe "fetch" do
140
-
141
- it "should fetch an object" do
142
- mock_s3_object = mock("s3_object")
143
- mock_s3_object.stub!(:value).and_yield("ENCRYPTED")
144
- AWS::S3::S3Object.should_receive(:find).with("object_id", "test").and_return(mock_s3_object)
145
- @client.should_receive(:decrypt_stream).with { |from, _|
146
- encrypted = ""
147
- from.call(lambda {|segment| encrypted << segment})
148
- encrypted.should eql("ENCRYPTED")
149
- true
150
- }.and_return {|_, to|
151
- to.write("stuff")
152
- }
153
- @client.get("object_id").should == "stuff"
154
- end
155
-
156
- it "should not decrypt when encryption key is missing" do
157
- client = s3_blobstore(:bucket_name => "test",
158
- :access_key_id => "KEY",
159
- :secret_access_key => "SECRET")
160
-
161
- mock_s3_object = mock("s3_object")
162
- mock_s3_object.stub!(:value).and_yield("stuff")
163
- AWS::S3::S3Object.should_receive(:find).with("object_id", "test").and_return(mock_s3_object)
164
- client.should_not_receive(:decrypt_stream)
165
-
166
- client.get("object_id").should == "stuff"
167
- end
168
-
169
- it "should raise an exception when there is an error fetching an object" do
170
- AWS::S3::S3Object.should_receive(:find).with("object_id", "test").and_raise(AWS::S3::S3Exception.new("Epic Fail"))
171
- lambda {
172
- @client.get("object_id")
173
- }.should raise_error(Bosh::Blobstore::BlobstoreError, "Failed to find object 'object_id', S3 response error: Epic Fail")
174
- end
175
-
176
- it "should raise more specific NotFound exception when object is not found" do
177
- AWS::S3::S3Object.should_receive(:find).with("object_id", "test").and_raise(AWS::S3::NoSuchKey.new("NO KEY", "test"))
178
- lambda {
179
- @client.get("object_id")
180
- }.should raise_error(Bosh::Blobstore::BlobstoreError, "S3 object 'object_id' not found")
181
- end
182
-
183
- end
184
-
185
- describe "delete" do
186
-
187
- it "should delete an object" do
188
- AWS::S3::S3Object.should_receive(:delete).with("object_id", "test")
189
- @client.delete("object_id")
190
- end
191
-
192
- it "should raise an exception when there is an error deleting an object" do
193
- AWS::S3::S3Object.should_receive(:delete).with("object_id", "test").and_raise(AWS::S3::S3Exception.new("Epic Fail"))
194
- lambda {
195
- @client.delete("object_id")
196
- }.should raise_error(Bosh::Blobstore::BlobstoreError, "Failed to delete object 'object_id', S3 response error: Epic Fail")
197
- end
198
-
199
- end
200
-
201
- describe "encryption" do
202
-
203
- before :each do
204
- @from_path = File.join(Dir::tmpdir, "from-#{UUIDTools::UUID.random_create}")
205
- @to_path = File.join(Dir::tmpdir, "to-#{UUIDTools::UUID.random_create}")
206
- end
207
-
208
- after :each do
209
- FileUtils.rm_f(@from_path)
210
- FileUtils.rm_f(@to_path)
211
- end
212
-
213
- it "encrypt/decrypt works as long as key is the same" do
214
- File.open(@from_path, "w") { |f| f.write("clear text") }
215
- File.open(@from_path, "r") do |from|
216
- File.open(@to_path, "w") do |to|
217
- @client.send(:encrypt_stream, from, to)
218
- end
219
- end
220
-
221
- Base64.encode64(File.read(@to_path)).should eql("XCUKDXXzjh43DmNylgVpQQ==\n")
222
-
223
- File.open(@from_path, "w") { |f| f.write(File.read(@to_path)) }
224
- File.open(@from_path, "r") do |from|
225
- File.open(@to_path, "w") do |to|
226
- @client.send(:decrypt_stream, from, to)
227
- end
228
- end
229
-
230
- File.read(@to_path).should eql("clear text")
231
- end
232
-
233
- it "encrypt/decrypt doesn't have padding issues for very small inputs" do
234
- File.open(@from_path, "w") { |f| f.write("c") }
235
- File.open(@from_path, "r") do |from|
236
- File.open(@to_path, "w") do |to|
237
- @client.send(:encrypt_stream, from, to)
238
- end
239
- end
240
-
241
- Base64.encode64(File.read(@to_path)).should eql("S1ZnX5gPfm/rQbRCcShHSg==\n")
242
-
243
- File.open(@from_path, "w") { |f| f.write(File.read(@to_path)) }
244
- File.open(@from_path, "r") do |from|
245
- File.open(@to_path, "w") do |to|
246
- @client.send(:decrypt_stream, from, to)
247
- end
248
- end
249
-
250
- File.read(@to_path).should eql("c")
251
- end
252
-
253
- it "should raise an exception if incorrect encryption key is used" do
254
- File.open(@from_path, "w") { |f| f.write("clear text") }
255
- File.open(@from_path, "r") do |from|
256
- File.open(@to_path, "w") do |to|
257
- @client.send(:encrypt_stream, from, to)
258
- end
259
- end
260
-
261
- Base64.encode64(File.read(@to_path)).should eql("XCUKDXXzjh43DmNylgVpQQ==\n")
262
-
263
- client2 = s3_blobstore(:encryption_key => "zzz",
264
- :bucket_name => "test",
265
- :access_key_id => "KEY",
266
- :secret_access_key => "SECRET")
267
-
268
- File.open(@from_path, "w") { |f| f.write(File.read(@to_path)) }
269
- File.open(@from_path, "r") do |from|
270
- File.open(@to_path, "w") do |to|
271
- lambda {
272
- client2.send(:decrypt_stream, from, to)
273
- }.should raise_error(Bosh::Blobstore::BlobstoreError, "Decryption error: bad decrypt")
274
- end
275
- end
276
- end
277
-
278
- end
279
-
280
- end
281
-
282
- end