blobstore_client 0.4.0 → 0.5.0
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.
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
4
|
+
#
|
5
|
+
# Usage example:
|
6
|
+
#
|
7
|
+
# => Debugger enabled
|
8
|
+
# => Welcome to BOSH blobstore client console
|
9
|
+
# You can use 'bsc' to access blobstore client methods
|
10
|
+
# irb(main):001:0> oid = bsc.create("test data content")
|
11
|
+
# => "eyJvaWQiOiJlNGQ5MTUzMy1iOTZiLVlYjc1YzQ1NTAi%0ALCJwdXJsIjpudWxsfQ==%0A"
|
12
|
+
# irb(main):002:0> bsc.get(oid)
|
13
|
+
# => "test data content"
|
14
|
+
# irb(main):003:0> bsc.delete(oid)
|
15
|
+
# => true
|
16
|
+
|
17
|
+
gemfile = File.expand_path("../../Gemfile", __FILE__)
|
18
|
+
|
19
|
+
if File.exists?(gemfile)
|
20
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
21
|
+
require "rubygems"
|
22
|
+
require "bundler/setup"
|
23
|
+
end
|
24
|
+
|
25
|
+
$:.unshift(File.expand_path("../../lib", __FILE__))
|
26
|
+
require "blobstore_client"
|
27
|
+
require "irb"
|
28
|
+
require "irb/completion"
|
29
|
+
require "ostruct"
|
30
|
+
require "optparse"
|
31
|
+
|
32
|
+
@provider = nil
|
33
|
+
config_file = nil
|
34
|
+
|
35
|
+
opts_parser = OptionParser.new do |opts|
|
36
|
+
opts.on("-p", "--provider PROVIDER") { |p| @provider = p }
|
37
|
+
opts.on("-c", "--config FILE") { |file| config_file = file }
|
38
|
+
end
|
39
|
+
opts_parser.parse!
|
40
|
+
|
41
|
+
unless @provider && config_file
|
42
|
+
puts opts_parser
|
43
|
+
exit(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
@config = YAML.load_file(config_file)
|
47
|
+
|
48
|
+
module ConsoleHelpers
|
49
|
+
def bsc
|
50
|
+
@bsc ||= Bosh::Blobstore::Client.create(@provider, @config)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
include ConsoleHelpers
|
55
|
+
|
56
|
+
begin
|
57
|
+
require 'ruby-debug'
|
58
|
+
puts "=> Debugger enabled"
|
59
|
+
rescue LoadError
|
60
|
+
puts "=> ruby-debug not found, debugger disabled"
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "=> Welcome to BOSH blobstore client console"
|
64
|
+
puts "You can use 'bsc' to access blobstore client methods"
|
65
|
+
|
66
|
+
IRB.start
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
require "fog"
|
5
|
+
require "multi_json"
|
6
|
+
require "uri"
|
7
|
+
require "uuidtools"
|
8
|
+
|
9
|
+
module Bosh
|
10
|
+
module Blobstore
|
11
|
+
|
12
|
+
class SwiftBlobstoreClient < BaseClient
|
13
|
+
|
14
|
+
# Blobstore client for Swift
|
15
|
+
# @param [Hash] options Swift BlobStore options
|
16
|
+
# @option options [Symbol] container_name
|
17
|
+
# @option options [Symbol] swift_provider
|
18
|
+
def initialize(options)
|
19
|
+
super(options)
|
20
|
+
@http_client = HTTPClient.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def container
|
24
|
+
return @container if @container
|
25
|
+
|
26
|
+
validate_options(@options)
|
27
|
+
|
28
|
+
swift_provider = @options[:swift_provider]
|
29
|
+
swift_options = {:provider => swift_provider}
|
30
|
+
swift_options.merge!(@options[swift_provider.to_sym])
|
31
|
+
swift = Fog::Storage.new(swift_options)
|
32
|
+
|
33
|
+
container_name = @options[:container_name]
|
34
|
+
@container = swift.directories.get(container_name)
|
35
|
+
if @container.nil?
|
36
|
+
raise NotFound, "Swift container '#{container_name}' not found"
|
37
|
+
end
|
38
|
+
@container
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_file(file)
|
42
|
+
object_id = generate_object_id
|
43
|
+
object = container.files.create(:key => object_id,
|
44
|
+
:body => file,
|
45
|
+
:public => true)
|
46
|
+
encode_object_id(object_id, object.public_url)
|
47
|
+
rescue Exception => e
|
48
|
+
raise BlobstoreError, "Failed to create object: #{e.message}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_file(object_id, file)
|
52
|
+
object_info = decode_object_id(object_id)
|
53
|
+
if object_info["purl"]
|
54
|
+
response = @http_client.get(object_info["purl"]) do |block|
|
55
|
+
file.write(block)
|
56
|
+
end
|
57
|
+
if response.status != 200
|
58
|
+
raise BlobstoreError, "Could not fetch object, %s/%s" %
|
59
|
+
[response.status, response.content]
|
60
|
+
end
|
61
|
+
else
|
62
|
+
object = container.files.get(object_info["oid"]) do |block|
|
63
|
+
file.write(block)
|
64
|
+
end
|
65
|
+
if object.nil?
|
66
|
+
raise NotFound, "Swift object '#{object_id}' not found"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue Exception => e
|
70
|
+
raise BlobstoreError,
|
71
|
+
"Failed to find object '#{object_id}': #{e.message}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete(object_id)
|
75
|
+
object_info = decode_object_id(object_id)
|
76
|
+
object = container.files.get(object_info["oid"])
|
77
|
+
if object.nil?
|
78
|
+
raise NotFound, "Swift object '#{object_id}' not found"
|
79
|
+
else
|
80
|
+
object.destroy
|
81
|
+
end
|
82
|
+
rescue Exception => e
|
83
|
+
raise BlobstoreError,
|
84
|
+
"Failed to delete object '#{object_id}': #{e.message}"
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def generate_object_id
|
90
|
+
UUIDTools::UUID.random_create.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
def encode_object_id(object_id, public_url = nil)
|
94
|
+
json = MultiJson.encode({:oid => object_id, :purl => public_url})
|
95
|
+
URI::escape(Base64.encode64(json))
|
96
|
+
end
|
97
|
+
|
98
|
+
def decode_object_id(object_id)
|
99
|
+
begin
|
100
|
+
object_info = MultiJson.decode(Base64.decode64(URI::unescape(object_id)))
|
101
|
+
rescue MultiJson::DecodeError => e
|
102
|
+
raise BlobstoreError, "Failed to parse object_id: #{e.message}"
|
103
|
+
end
|
104
|
+
|
105
|
+
if !object_info.kind_of?(Hash) || object_info["oid"].nil?
|
106
|
+
raise BlobstoreError, "Invalid object_id: #{object_info.inspect}"
|
107
|
+
end
|
108
|
+
object_info
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_options(options)
|
112
|
+
unless options.is_a?(Hash)
|
113
|
+
raise "Invalid options format, Hash expected, #{options.class} given"
|
114
|
+
end
|
115
|
+
unless options.has_key?(:container_name)
|
116
|
+
raise "Swift container name is missing"
|
117
|
+
end
|
118
|
+
unless options.has_key?(:swift_provider)
|
119
|
+
raise "Swift provider is missing"
|
120
|
+
end
|
121
|
+
case options[:swift_provider]
|
122
|
+
when "hp"
|
123
|
+
unless options.has_key?(:hp)
|
124
|
+
raise "HP options are missing"
|
125
|
+
end
|
126
|
+
unless options[:hp].is_a?(Hash)
|
127
|
+
raise "Invalid HP options, Hash expected,
|
128
|
+
#{options[:hp].class} given"
|
129
|
+
end
|
130
|
+
unless options[:hp].has_key?(:hp_account_id)
|
131
|
+
raise "HP account ID is missing"
|
132
|
+
end
|
133
|
+
unless options[:hp].has_key?(:hp_secret_key)
|
134
|
+
raise "HP secret key is missing"
|
135
|
+
end
|
136
|
+
unless options[:hp].has_key?(:hp_tenant_id)
|
137
|
+
raise "HP tenant ID is missing"
|
138
|
+
end
|
139
|
+
when "rackspace"
|
140
|
+
unless options.has_key?(:rackspace)
|
141
|
+
raise "Rackspace options are missing"
|
142
|
+
end
|
143
|
+
unless options[:rackspace].is_a?(Hash)
|
144
|
+
raise "Invalid Rackspace options, Hash expected,
|
145
|
+
#{options[:rackspace].class} given"
|
146
|
+
end
|
147
|
+
unless options[:rackspace].has_key?(:rackspace_username)
|
148
|
+
raise "Rackspace username is missing"
|
149
|
+
end
|
150
|
+
unless options[:rackspace].has_key?(:rackspace_api_key)
|
151
|
+
raise "Rackspace API key is missing"
|
152
|
+
end
|
153
|
+
else
|
154
|
+
raise "Swift provider #{options[:swift_provider]} not supported"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/blobstore_client.rb
CHANGED
@@ -10,6 +10,7 @@ require "blobstore_client/client"
|
|
10
10
|
require "blobstore_client/base"
|
11
11
|
require "blobstore_client/simple_blobstore_client"
|
12
12
|
require "blobstore_client/s3_blobstore_client"
|
13
|
+
require "blobstore_client/swift_blobstore_client"
|
13
14
|
require "blobstore_client/local_client"
|
14
15
|
require "blobstore_client/atmos_blobstore_client"
|
15
16
|
|
@@ -20,6 +21,7 @@ module Bosh
|
|
20
21
|
PROVIDER_MAP = {
|
21
22
|
"simple" => SimpleBlobstoreClient,
|
22
23
|
"s3" => S3BlobstoreClient,
|
24
|
+
"swift" => SwiftBlobstoreClient,
|
23
25
|
"atmos" => AtmosBlobstoreClient,
|
24
26
|
"local" => LocalClient
|
25
27
|
}
|
@@ -30,6 +30,11 @@ describe Bosh::Blobstore::Client do
|
|
30
30
|
bs.should be_instance_of Bosh::Blobstore::S3BlobstoreClient
|
31
31
|
end
|
32
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
|
+
|
33
38
|
it "should raise an exception on an unknown client" do
|
34
39
|
lambda {
|
35
40
|
bs = Bosh::Blobstore::Client.create('foobar', {})
|
@@ -0,0 +1,315 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Bosh::Blobstore::SwiftBlobstoreClient do
|
4
|
+
|
5
|
+
def swift_options(container_name, swift_provider, credentials)
|
6
|
+
if credentials
|
7
|
+
options = {
|
8
|
+
"rackspace" => {
|
9
|
+
"rackspace_username" => "username",
|
10
|
+
"rackspace_api_key" => "api_key"
|
11
|
+
},
|
12
|
+
"hp" => {
|
13
|
+
"hp_account_id" => "account_id",
|
14
|
+
"hp_secret_key" => "secret_key",
|
15
|
+
"hp_tenant_id" => "tenant_id"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
else
|
19
|
+
options = {}
|
20
|
+
end
|
21
|
+
options["container_name"] = container_name if container_name
|
22
|
+
options["swift_provider"] = swift_provider if swift_provider
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
def swift_blobstore(options)
|
27
|
+
Bosh::Blobstore::SwiftBlobstoreClient.new(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
before(:each) do
|
31
|
+
@swift = mock("swift")
|
32
|
+
Fog::Storage.stub!(:new).and_return(@swift)
|
33
|
+
@http_client = mock("http-client")
|
34
|
+
HTTPClient.stub!(:new).and_return(@http_client)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "on HP Cloud Storage" do
|
38
|
+
|
39
|
+
describe "with credentials" do
|
40
|
+
|
41
|
+
before(:each) do
|
42
|
+
@client = swift_blobstore(swift_options("test-container",
|
43
|
+
"hp",
|
44
|
+
true))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should create an object" do
|
48
|
+
data = "some content"
|
49
|
+
directories = double("directories")
|
50
|
+
container = double("container")
|
51
|
+
files = double("files")
|
52
|
+
object = double("object")
|
53
|
+
|
54
|
+
@client.should_receive(:generate_object_id).and_return("object_id")
|
55
|
+
@swift.stub(:directories).and_return(directories)
|
56
|
+
directories.should_receive(:get).with("test-container") \
|
57
|
+
.and_return(container)
|
58
|
+
container.should_receive(:files).and_return(files)
|
59
|
+
files.should_receive(:create).with { |opt|
|
60
|
+
opt[:key].should eql "object_id"
|
61
|
+
#opt[:body].should eql data
|
62
|
+
opt[:public].should eql true
|
63
|
+
}.and_return(object)
|
64
|
+
object.should_receive(:public_url).and_return("public-url")
|
65
|
+
|
66
|
+
object_id = @client.create(data)
|
67
|
+
object_info = MultiJson.decode(Base64.decode64(
|
68
|
+
URI::unescape(object_id)))
|
69
|
+
object_info["oid"].should eql("object_id")
|
70
|
+
object_info["purl"].should eql("public-url")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should fetch an object without a public url" do
|
74
|
+
data = "some content"
|
75
|
+
directories = double("directories")
|
76
|
+
container = double("container")
|
77
|
+
files = double("files")
|
78
|
+
object = double("object")
|
79
|
+
|
80
|
+
@swift.stub(:directories).and_return(directories)
|
81
|
+
directories.should_receive(:get).with("test-container") \
|
82
|
+
.and_return(container)
|
83
|
+
container.should_receive(:files).and_return(files)
|
84
|
+
files.should_receive(:get).with("object_id").and_yield(data) \
|
85
|
+
.and_return(object)
|
86
|
+
|
87
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
88
|
+
{:oid => "object_id"})))
|
89
|
+
@client.get(oid).should eql(data)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should fetch an object with a public url" do
|
93
|
+
data = "some content"
|
94
|
+
response = mock("response")
|
95
|
+
|
96
|
+
@http_client.should_receive(:get).with("public-url") \
|
97
|
+
.and_yield(data).and_return(response)
|
98
|
+
response.stub!(:status).and_return(200)
|
99
|
+
|
100
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
101
|
+
{:oid => "object_id",
|
102
|
+
:purl => "public-url"})))
|
103
|
+
@client.get(oid).should eql(data)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should delete an object" do
|
107
|
+
directories = double("directories")
|
108
|
+
container = double("container")
|
109
|
+
files = double("files")
|
110
|
+
object = double("object")
|
111
|
+
|
112
|
+
@swift.stub(:directories).and_return(directories)
|
113
|
+
directories.should_receive(:get).with("test-container") \
|
114
|
+
.and_return(container)
|
115
|
+
container.should_receive(:files).and_return(files)
|
116
|
+
files.should_receive(:get).with("object_id").and_return(object)
|
117
|
+
object.should_receive(:destroy)
|
118
|
+
|
119
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
120
|
+
{:oid => "object_id"})))
|
121
|
+
@client.delete(oid)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "without credentials" do
|
127
|
+
|
128
|
+
before(:each) do
|
129
|
+
@client = swift_blobstore(swift_options("test-container",
|
130
|
+
"hp",
|
131
|
+
false))
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should refuse to create an object" do
|
135
|
+
data = "some content"
|
136
|
+
|
137
|
+
lambda {
|
138
|
+
object_id = @client.create(data)
|
139
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should refuse to fetch an object without a public url" do
|
143
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
144
|
+
{:oid => "object_id"})))
|
145
|
+
lambda {
|
146
|
+
@client.get(oid)
|
147
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should fetch an object with a public url" do
|
151
|
+
data = "some content"
|
152
|
+
response = mock("response")
|
153
|
+
|
154
|
+
@http_client.should_receive(:get).with("public-url") \
|
155
|
+
.and_yield(data).and_return(response)
|
156
|
+
response.stub!(:status).and_return(200)
|
157
|
+
|
158
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
159
|
+
{:oid => "object_id",
|
160
|
+
:purl => "public-url"})))
|
161
|
+
@client.get(oid).should eql(data)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should refuse to delete an object" do
|
165
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
166
|
+
{:oid => "object_id"})))
|
167
|
+
lambda {
|
168
|
+
@client.delete(oid)
|
169
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "on Rackspace Cloud Files" do
|
177
|
+
|
178
|
+
describe "with credentials" do
|
179
|
+
|
180
|
+
before(:each) do
|
181
|
+
@client = swift_blobstore(swift_options("test-container",
|
182
|
+
"rackspace",
|
183
|
+
true))
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should create an object" do
|
187
|
+
data = "some content"
|
188
|
+
directories = double("directories")
|
189
|
+
container = double("container")
|
190
|
+
files = double("files")
|
191
|
+
object = double("object")
|
192
|
+
|
193
|
+
@client.should_receive(:generate_object_id).and_return("object_id")
|
194
|
+
@swift.stub(:directories).and_return(directories)
|
195
|
+
directories.should_receive(:get).with("test-container") \
|
196
|
+
.and_return(container)
|
197
|
+
container.should_receive(:files).and_return(files)
|
198
|
+
files.should_receive(:create).with { |opt|
|
199
|
+
opt[:key].should eql "object_id"
|
200
|
+
#opt[:body].should eql data
|
201
|
+
opt[:public].should eql true
|
202
|
+
}.and_return(object)
|
203
|
+
object.should_receive(:public_url).and_return("public-url")
|
204
|
+
|
205
|
+
object_id = @client.create(data)
|
206
|
+
object_info = MultiJson.decode(Base64.decode64(
|
207
|
+
URI::unescape(object_id)))
|
208
|
+
object_info["oid"].should eql("object_id")
|
209
|
+
object_info["purl"].should eql("public-url")
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should fetch an object without a public url" do
|
213
|
+
data = "some content"
|
214
|
+
directories = double("directories")
|
215
|
+
container = double("container")
|
216
|
+
files = double("files")
|
217
|
+
object = double("object")
|
218
|
+
|
219
|
+
@swift.stub(:directories).and_return(directories)
|
220
|
+
directories.should_receive(:get).with("test-container") \
|
221
|
+
.and_return(container)
|
222
|
+
container.should_receive(:files).and_return(files)
|
223
|
+
files.should_receive(:get).with("object_id").and_yield(data) \
|
224
|
+
.and_return(object)
|
225
|
+
|
226
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
227
|
+
{:oid => "object_id"})))
|
228
|
+
@client.get(oid).should eql(data)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should fetch an object with a public url" do
|
232
|
+
data = "some content"
|
233
|
+
response = mock("response")
|
234
|
+
|
235
|
+
@http_client.should_receive(:get).with("public-url") \
|
236
|
+
.and_yield(data).and_return(response)
|
237
|
+
response.stub!(:status).and_return(200)
|
238
|
+
|
239
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
240
|
+
{:oid => "object_id",
|
241
|
+
:purl => "public-url"})))
|
242
|
+
@client.get(oid).should eql(data)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should delete an object" do
|
246
|
+
directories = double("directories")
|
247
|
+
container = double("container")
|
248
|
+
files = double("files")
|
249
|
+
object = double("object")
|
250
|
+
|
251
|
+
@swift.stub(:directories).and_return(directories)
|
252
|
+
directories.should_receive(:get).with("test-container") \
|
253
|
+
.and_return(container)
|
254
|
+
container.should_receive(:files).and_return(files)
|
255
|
+
files.should_receive(:get).with("object_id").and_return(object)
|
256
|
+
object.should_receive(:destroy)
|
257
|
+
|
258
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
259
|
+
{:oid => "object_id"})))
|
260
|
+
@client.delete(oid)
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "without credentials" do
|
266
|
+
|
267
|
+
before(:each) do
|
268
|
+
@client = swift_blobstore(swift_options("test-container",
|
269
|
+
"rackspace",
|
270
|
+
false))
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should refuse to create an object" do
|
274
|
+
data = "some content"
|
275
|
+
|
276
|
+
lambda {
|
277
|
+
object_id = @client.create(data)
|
278
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should refuse to fetch an object without a public url" do
|
282
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
283
|
+
{:oid => "object_id"})))
|
284
|
+
lambda {
|
285
|
+
@client.get(oid)
|
286
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should fetch an object with a public url" do
|
290
|
+
data = "some content"
|
291
|
+
response = mock("response")
|
292
|
+
|
293
|
+
@http_client.should_receive(:get).with("public-url") \
|
294
|
+
.and_yield(data).and_return(response)
|
295
|
+
response.stub!(:status).and_return(200)
|
296
|
+
|
297
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
298
|
+
{:oid => "object_id",
|
299
|
+
:purl => "public-url"})))
|
300
|
+
@client.get(oid).should eql(data)
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should refuse to delete an object" do
|
304
|
+
oid = URI::escape(Base64.encode64(MultiJson.encode(
|
305
|
+
{:oid => "object_id"})))
|
306
|
+
lambda {
|
307
|
+
@client.delete(oid)
|
308
|
+
}.should raise_error(Bosh::Blobstore::BlobstoreError)
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blobstore_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-s3
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.6.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: fog
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.6.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.6.0
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: httpclient
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,10 +125,12 @@ dependencies:
|
|
109
125
|
version: '0.5'
|
110
126
|
description: BOSH blobstore client
|
111
127
|
email: support@vmware.com
|
112
|
-
executables:
|
128
|
+
executables:
|
129
|
+
- blobstore_client_console
|
113
130
|
extensions: []
|
114
131
|
extra_rdoc_files: []
|
115
132
|
files:
|
133
|
+
- bin/blobstore_client_console
|
116
134
|
- lib/blobstore_client.rb
|
117
135
|
- lib/blobstore_client/atmos_blobstore_client.rb
|
118
136
|
- lib/blobstore_client/base.rb
|
@@ -121,6 +139,7 @@ files:
|
|
121
139
|
- lib/blobstore_client/local_client.rb
|
122
140
|
- lib/blobstore_client/s3_blobstore_client.rb
|
123
141
|
- lib/blobstore_client/simple_blobstore_client.rb
|
142
|
+
- lib/blobstore_client/swift_blobstore_client.rb
|
124
143
|
- lib/blobstore_client/version.rb
|
125
144
|
- README
|
126
145
|
- Rakefile
|
@@ -131,6 +150,7 @@ files:
|
|
131
150
|
- spec/unit/local_client_spec.rb
|
132
151
|
- spec/unit/s3_blobstore_client_spec.rb
|
133
152
|
- spec/unit/simple_blobstore_client_spec.rb
|
153
|
+
- spec/unit/swift_blobstore_client_spec.rb
|
134
154
|
homepage: http://www.vmware.com
|
135
155
|
licenses: []
|
136
156
|
post_install_message:
|
@@ -145,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
165
|
version: '0'
|
146
166
|
segments:
|
147
167
|
- 0
|
148
|
-
hash:
|
168
|
+
hash: -2537561053731340493
|
149
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
170
|
none: false
|
151
171
|
requirements:
|
@@ -154,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
174
|
version: '0'
|
155
175
|
segments:
|
156
176
|
- 0
|
157
|
-
hash:
|
177
|
+
hash: -2537561053731340493
|
158
178
|
requirements: []
|
159
179
|
rubyforge_project:
|
160
180
|
rubygems_version: 1.8.24
|
@@ -169,3 +189,4 @@ test_files:
|
|
169
189
|
- spec/unit/local_client_spec.rb
|
170
190
|
- spec/unit/s3_blobstore_client_spec.rb
|
171
191
|
- spec/unit/simple_blobstore_client_spec.rb
|
192
|
+
- spec/unit/swift_blobstore_client_spec.rb
|