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/README.md +127 -0
- data/bin/blobstore_client_console +21 -20
- data/config/local.yml.example +2 -0
- data/lib/blobstore_client.rb +12 -41
- data/lib/blobstore_client/atmos_blobstore_client.rb +52 -35
- data/lib/blobstore_client/base.rb +76 -40
- data/lib/blobstore_client/client.rb +12 -7
- data/lib/blobstore_client/dav_blobstore_client.rb +67 -0
- data/lib/blobstore_client/errors.rb +1 -0
- data/lib/blobstore_client/local_client.rb +24 -15
- data/lib/blobstore_client/s3_blobstore_client.rb +97 -96
- data/lib/blobstore_client/simple_blobstore_client.rb +24 -11
- data/lib/blobstore_client/swift_blobstore_client.rb +78 -87
- data/lib/blobstore_client/version.rb +1 -1
- metadata +33 -67
- data/README +0 -1
- data/Rakefile +0 -49
- data/spec/assets/file +0 -1
- data/spec/spec_helper.rb +0 -8
- data/spec/unit/atmos_blobstore_client_spec.rb +0 -72
- data/spec/unit/blobstore_client_spec.rb +0 -44
- data/spec/unit/local_client_spec.rb +0 -78
- data/spec/unit/s3_blobstore_client_spec.rb +0 -282
- data/spec/unit/simple_blobstore_client_spec.rb +0 -106
- data/spec/unit/swift_blobstore_client_spec.rb +0 -315
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# Ruby client for Blobstores
|
2
|
+
Copyright (c) 2009-2013 VMware, Inc.
|
3
|
+
|
4
|
+
Lets BOSH access multiple blobstores using a unified API.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
bin/blobstore_client_console [<options>]
|
9
|
+
-p, --provider PROVIDER Bosh Blobstore provider
|
10
|
+
-c, --config FILE Bosh Blobstore configuration file
|
11
|
+
|
12
|
+
## Console
|
13
|
+
|
14
|
+
To explore the client API for accessing a blobstore, try creating and using a local blobstore:
|
15
|
+
|
16
|
+
```
|
17
|
+
$ gem install blobstore_client
|
18
|
+
$ blobstore_client_console -p local -c config/local.yml.example
|
19
|
+
=> Welcome to BOSH blobstore client console
|
20
|
+
You can use 'bsc' to access blobstore client methods
|
21
|
+
> bsc.create("this is a test blob")
|
22
|
+
=> "ef00746b-21ec-4473-a888-bf257cb7ea21"
|
23
|
+
> bsc.get("ef00746b-21ec-4473-a888-bf257cb7ea21")
|
24
|
+
=> "this is a test blob"
|
25
|
+
> bsc.exists?("ef00746b-21ec-4473-a888-bf257cb7ea21")
|
26
|
+
=> true
|
27
|
+
> Dir['/tmp/local_blobstore/**']
|
28
|
+
=> ["/tmp/local_blobstore/ef00746b-21ec-4473-a888-bf257cb7ea21"]
|
29
|
+
> bsc.delete("ef00746b-21ec-4473-a888-bf257cb7ea21")
|
30
|
+
=> true
|
31
|
+
```
|
32
|
+
|
33
|
+
## Configuration
|
34
|
+
|
35
|
+
These options are passed to the Bosh Blobstore client when it is instantiated.
|
36
|
+
|
37
|
+
### Local
|
38
|
+
|
39
|
+
These are the options for the Blobstore client when provider is `local`:
|
40
|
+
|
41
|
+
* `blobstore_path` (required)
|
42
|
+
Path for the blobstore
|
43
|
+
|
44
|
+
### Simple
|
45
|
+
|
46
|
+
These are the options for the Blobstore client when provider is `simple`:
|
47
|
+
|
48
|
+
* `endpoint` (required)
|
49
|
+
Blobstore endpoint
|
50
|
+
* `user` (optional)
|
51
|
+
Blobstore User
|
52
|
+
* `password` (optional)
|
53
|
+
Blobstore Password
|
54
|
+
* `bucket` (optional, by default `resources`)
|
55
|
+
Name of the bucket
|
56
|
+
|
57
|
+
### Amazon S3
|
58
|
+
|
59
|
+
These are the options for the Blobstore client when provider is `s3`:
|
60
|
+
|
61
|
+
* `bucket_name` (required)
|
62
|
+
Name of the S3 bucket
|
63
|
+
* `encryption_key` (optional)
|
64
|
+
Encryption_key that is applied before the object is sent to S3
|
65
|
+
* `access_key_id` (optional, if not present, the blobstore client operates in read only mode)
|
66
|
+
S3 Access Key
|
67
|
+
* `secret_access_key` (optional, if not present, the blobstore client operates in read only mode)
|
68
|
+
S3 Secret Access Key
|
69
|
+
|
70
|
+
### Atmos
|
71
|
+
|
72
|
+
These are the options for the Blobstore client when provider is `atmos`:
|
73
|
+
|
74
|
+
* `url` (required)
|
75
|
+
Atmos URL
|
76
|
+
* `uid` (required)
|
77
|
+
Atmos UID
|
78
|
+
* `secret` (required)
|
79
|
+
Atmos password
|
80
|
+
|
81
|
+
### OpenStack Swift provider
|
82
|
+
|
83
|
+
These are the options for the Blobstore client when provider is `swift`:
|
84
|
+
|
85
|
+
* `container_name` (required)
|
86
|
+
Name of the container
|
87
|
+
* `swift_provider` (required)
|
88
|
+
OpenStack Swift provider (supported: `hp`, `openstack` and `rackspace`)
|
89
|
+
|
90
|
+
#### HP Object Storage
|
91
|
+
|
92
|
+
These are the options for the Blobstore client when `swift_provider` is `hp`:
|
93
|
+
|
94
|
+
* `hp_access_key` (required)
|
95
|
+
HP Object Storage Access Key
|
96
|
+
* `hp_secret_key` (required)
|
97
|
+
HP Object Storage Secret Key
|
98
|
+
* `hp_tenant_id` (required)
|
99
|
+
HP Object Storage Project ID
|
100
|
+
* `hp_avl_zone` (required)
|
101
|
+
HP Object Storage Availability Zone (`region-a.geo-1` or `region-b.geo-1`)
|
102
|
+
|
103
|
+
#### OpenStack Object Storage
|
104
|
+
|
105
|
+
These are the options for the Blobstore client when `swift_provider` is `openstack`:
|
106
|
+
|
107
|
+
* `openstack_auth_url` (required)
|
108
|
+
URL of the OpenStack Identity endpoint to connect to
|
109
|
+
* `openstack_username` (required)
|
110
|
+
OpenStack user name
|
111
|
+
* `openstack_api_key` (required)
|
112
|
+
OpenStack API key
|
113
|
+
* `openstack_tenant` (required)
|
114
|
+
OpenStack tenant name
|
115
|
+
* `openstack_region` (optional)
|
116
|
+
OpenStack region
|
117
|
+
|
118
|
+
#### Rackspace Cloud Files
|
119
|
+
|
120
|
+
These are the options for the Blobstore client when `swift_provider` is `rackspace`:
|
121
|
+
|
122
|
+
* `rackspace_username` (required)
|
123
|
+
Rackspace Cloud Files Username
|
124
|
+
* `rackspace_api_key` (required)
|
125
|
+
Rackspace Cloud Files API Key
|
126
|
+
* `rackspace_region` (optional)
|
127
|
+
Rackspace Cloud Files Region (`dfw` or `ord`)
|
@@ -14,36 +14,37 @@
|
|
14
14
|
# irb(main):003:0> bsc.delete(oid)
|
15
15
|
# => true
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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"
|
17
|
+
require 'blobstore_client'
|
18
|
+
require 'irb'
|
19
|
+
require 'irb/completion'
|
20
|
+
require 'ostruct'
|
21
|
+
require 'optparse'
|
22
|
+
require 'psych'
|
31
23
|
|
32
24
|
@provider = nil
|
33
25
|
config_file = nil
|
34
26
|
|
35
27
|
opts_parser = OptionParser.new do |opts|
|
36
|
-
opts.on(
|
37
|
-
opts.on(
|
28
|
+
opts.on('-p', '--provider PROVIDER') { |p| @provider = p }
|
29
|
+
opts.on('-c', '--config FILE') { |file| config_file = file }
|
38
30
|
end
|
39
31
|
opts_parser.parse!
|
40
32
|
|
41
33
|
unless @provider && config_file
|
42
34
|
puts opts_parser
|
35
|
+
puts "\nExample config file:"
|
36
|
+
puts <<-YAML
|
37
|
+
---
|
38
|
+
endpoint: http://1.2.3.4:25250
|
39
|
+
user: agent
|
40
|
+
password: agent
|
41
|
+
bucket: resources
|
42
|
+
|
43
|
+
YAML
|
43
44
|
exit(1)
|
44
45
|
end
|
45
46
|
|
46
|
-
@config =
|
47
|
+
@config = Psych.load_file(config_file)
|
47
48
|
|
48
49
|
module ConsoleHelpers
|
49
50
|
def bsc
|
@@ -55,12 +56,12 @@ include ConsoleHelpers
|
|
55
56
|
|
56
57
|
begin
|
57
58
|
require 'ruby-debug'
|
58
|
-
puts
|
59
|
+
puts '=> Debugger enabled'
|
59
60
|
rescue LoadError
|
60
|
-
puts
|
61
|
+
puts '=> ruby-debug not found, debugger disabled'
|
61
62
|
end
|
62
63
|
|
63
|
-
puts
|
64
|
+
puts '=> Welcome to BOSH blobstore client console'
|
64
65
|
puts "You can use 'bsc' to access blobstore client methods"
|
65
66
|
|
66
67
|
IRB.start
|
data/lib/blobstore_client.rb
CHANGED
@@ -1,43 +1,14 @@
|
|
1
1
|
# Copyright (c) 2009-2012 VMware, Inc.
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
require "blobstore_client/atmos_blobstore_client"
|
16
|
-
|
17
|
-
module Bosh
|
18
|
-
module Blobstore
|
19
|
-
class Client
|
20
|
-
|
21
|
-
PROVIDER_MAP = {
|
22
|
-
"simple" => SimpleBlobstoreClient,
|
23
|
-
"s3" => S3BlobstoreClient,
|
24
|
-
"swift" => SwiftBlobstoreClient,
|
25
|
-
"atmos" => AtmosBlobstoreClient,
|
26
|
-
"local" => LocalClient
|
27
|
-
}
|
28
|
-
|
29
|
-
def self.create(blobstore_provider, options = {})
|
30
|
-
provider = PROVIDER_MAP[blobstore_provider]
|
31
|
-
|
32
|
-
unless provider
|
33
|
-
providers = PROVIDER_MAP.keys.sort.join(", ")
|
34
|
-
raise BlobstoreError,
|
35
|
-
"Invalid client provider, available providers are: #{providers}"
|
36
|
-
end
|
37
|
-
|
38
|
-
provider.new(options)
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
3
|
+
require 'common/common'
|
4
|
+
require 'blobstore_client/version'
|
5
|
+
require 'blobstore_client/errors'
|
6
|
+
require 'blobstore_client/client'
|
7
|
+
|
8
|
+
Bosh::Blobstore.autoload(:BaseClient, 'blobstore_client/base')
|
9
|
+
Bosh::Blobstore.autoload(:S3BlobstoreClient, 'blobstore_client/s3_blobstore_client')
|
10
|
+
Bosh::Blobstore.autoload(:SimpleBlobstoreClient, 'blobstore_client/simple_blobstore_client')
|
11
|
+
Bosh::Blobstore.autoload(:SwiftBlobstoreClient, 'blobstore_client/swift_blobstore_client')
|
12
|
+
Bosh::Blobstore.autoload(:AtmosBlobstoreClient, 'blobstore_client/atmos_blobstore_client')
|
13
|
+
Bosh::Blobstore.autoload(:LocalClient, 'blobstore_client/local_client')
|
14
|
+
Bosh::Blobstore.autoload(:DavBlobstoreClient, 'blobstore_client/dav_blobstore_client')
|
@@ -1,93 +1,110 @@
|
|
1
1
|
# Copyright (c) 2009-2012 VMware, Inc.
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'atmos'
|
4
|
+
require 'uri'
|
5
|
+
require 'multi_json'
|
6
|
+
require 'httpclient'
|
6
7
|
|
7
8
|
module Bosh
|
8
9
|
module Blobstore
|
9
10
|
class AtmosBlobstoreClient < BaseClient
|
10
|
-
SHARE_URL_EXP =
|
11
|
+
SHARE_URL_EXP = '1893484800' # expires on 2030 Jan-1
|
11
12
|
|
12
13
|
def initialize(options)
|
13
14
|
super(options)
|
14
15
|
@atmos_options = {
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
16
|
+
url: @options[:url],
|
17
|
+
uid: @options[:uid],
|
18
|
+
secret: @options[:secret]
|
18
19
|
}
|
19
20
|
@tag = @options[:tag]
|
20
|
-
|
21
|
-
#
|
21
|
+
|
22
|
+
# Add proxy if ENV has the variable
|
23
|
+
proxy = case URI.parse(@atmos_options[:url] || '').scheme
|
24
|
+
when 'https'
|
25
|
+
ENV['HTTPS_PROXY'] || ENV['https_proxy']
|
26
|
+
when 'http'
|
27
|
+
ENV['HTTP_PROXY'] || ENV['http_proxy']
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
if proxy
|
32
|
+
@atmos_options[:proxy] = proxy
|
33
|
+
@http_client = HTTPClient.new(proxy: proxy)
|
34
|
+
end
|
35
|
+
@http_client ||= HTTPClient.new
|
22
36
|
@http_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
23
37
|
end
|
24
38
|
|
25
39
|
def atmos_server
|
26
|
-
unless @atmos_options[:secret]
|
27
|
-
|
28
|
-
end
|
40
|
+
raise 'Atmos password is missing (read-only mode)' unless @atmos_options[:secret]
|
41
|
+
|
29
42
|
@atmos ||= Atmos::Store.new(@atmos_options)
|
30
43
|
end
|
31
44
|
|
32
|
-
|
33
|
-
|
34
|
-
|
45
|
+
protected
|
46
|
+
|
47
|
+
def create_file(id, file)
|
48
|
+
raise BlobstoreError, 'Atmos does not support supplying the object id' if id
|
49
|
+
obj_conf = { data: file, length: File.size(file.path) }
|
50
|
+
obj_conf[:listable_metadata] = { @tag => true } if @tag
|
35
51
|
object_id = atmos_server.create(obj_conf).aoid
|
36
52
|
encode_object_id(object_id)
|
37
53
|
end
|
38
54
|
|
39
55
|
def get_file(object_id, file)
|
40
56
|
object_info = decode_object_id(object_id)
|
41
|
-
oid = object_info[
|
42
|
-
sig = object_info[
|
57
|
+
oid = object_info['oid']
|
58
|
+
sig = object_info['sig']
|
43
59
|
|
44
60
|
url = @atmos_options[:url] + "/rest/objects/#{oid}?uid=" +
|
45
|
-
|
46
|
-
|
61
|
+
URI.escape(@atmos_options[:uid]) +
|
62
|
+
"&expires=#{SHARE_URL_EXP}&signature=#{URI.escape(sig)}"
|
47
63
|
|
48
64
|
response = @http_client.get(url) do |block|
|
49
65
|
file.write(block)
|
50
66
|
end
|
51
67
|
|
52
68
|
if response.status != 200
|
53
|
-
raise BlobstoreError,
|
54
|
-
[response.status, response.content]
|
69
|
+
raise BlobstoreError, sprintf('Could not fetch object, %s/%s', [response.status, response.content])
|
55
70
|
end
|
56
71
|
end
|
57
72
|
|
58
|
-
def
|
73
|
+
def delete_object(object_id)
|
59
74
|
object_info = decode_object_id(object_id)
|
60
|
-
oid = object_info[
|
61
|
-
atmos_server.get(:
|
62
|
-
rescue Atmos::Exceptions::NoSuchObjectException
|
75
|
+
oid = object_info['oid']
|
76
|
+
atmos_server.get(id: oid).delete
|
77
|
+
rescue Atmos::Exceptions::NoSuchObjectException
|
63
78
|
raise NotFound, "Atmos object '#{object_id}' not found"
|
64
79
|
end
|
65
80
|
|
81
|
+
def object_exists?(object_id)
|
82
|
+
atmos_server.get(id: object_id).exists?
|
83
|
+
end
|
84
|
+
|
66
85
|
private
|
67
86
|
|
68
87
|
def decode_object_id(object_id)
|
69
88
|
begin
|
70
|
-
object_info = MultiJson.decode(Base64.decode64(URI
|
71
|
-
rescue MultiJson::DecodeError
|
72
|
-
raise BlobstoreError,
|
73
|
-
"Please try updating the release"
|
89
|
+
object_info = MultiJson.decode(Base64.decode64(URI.unescape(object_id)))
|
90
|
+
rescue MultiJson::DecodeError
|
91
|
+
raise BlobstoreError, 'Failed to parse object_id. Please try updating the release'
|
74
92
|
end
|
75
93
|
|
76
|
-
if !object_info.kind_of?(Hash) || object_info[
|
77
|
-
|
94
|
+
if !object_info.kind_of?(Hash) || object_info['oid'].nil? ||
|
95
|
+
object_info['sig'].nil?
|
78
96
|
raise BlobstoreError, "Invalid object_id (#{object_id})"
|
79
97
|
end
|
80
98
|
object_info
|
81
99
|
end
|
82
100
|
|
83
101
|
def encode_object_id(object_id)
|
84
|
-
hash_string = "GET
|
85
|
-
@atmos_options[:uid] + "\n" + SHARE_URL_EXP
|
102
|
+
hash_string = "GET\n/rest/objects/#{object_id}\n#{@atmos_options[:uid]}\n#{SHARE_URL_EXP}"
|
86
103
|
secret = Base64.decode64(@atmos_options[:secret])
|
87
104
|
sig = HMAC::SHA1.digest(secret, hash_string)
|
88
105
|
signature = Base64.encode64(sig.to_s).chomp
|
89
|
-
json = MultiJson.encode({:
|
90
|
-
URI
|
106
|
+
json = MultiJson.encode({ oid: object_id, sig: signature })
|
107
|
+
URI.escape(Base64.encode64(json))
|
91
108
|
end
|
92
109
|
end
|
93
110
|
end
|
@@ -1,76 +1,107 @@
|
|
1
1
|
# Copyright (c) 2009-2012 VMware, Inc.
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'securerandom'
|
4
5
|
|
5
6
|
module Bosh
|
6
7
|
module Blobstore
|
7
8
|
class BaseClient < Client
|
8
9
|
|
10
|
+
# @param [Hash] options blobstore specific options
|
9
11
|
def initialize(options)
|
10
12
|
@options = Bosh::Common.symbolize_keys(options)
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def get_file(id, file)
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def create(contents)
|
15
|
+
# Saves a file or a string to the blobstore.
|
16
|
+
# if it is a String, it writes it to a temp file
|
17
|
+
# then calls create_file() with the (temp) file
|
18
|
+
# @overload create(contents, id=nil)
|
19
|
+
# @param [String] contents contents to upload
|
20
|
+
# @param [String] id suggested object id, if nil a uuid is generated
|
21
|
+
# @overload create(file, id=nil)
|
22
|
+
# @param [File] file file to upload
|
23
|
+
# @param [String] id suggested object id, if nil a uuid is generated
|
24
|
+
# @return [String] object id of the created blobstore object
|
25
|
+
def create(contents, id = nil)
|
29
26
|
if contents.kind_of?(File)
|
30
|
-
create_file(contents)
|
27
|
+
create_file(id, contents)
|
31
28
|
else
|
32
29
|
temp_path do |path|
|
33
|
-
|
34
|
-
|
35
|
-
file.write(contents)
|
36
|
-
end
|
37
|
-
return create_file(File.open(path, "r"))
|
38
|
-
rescue BlobstoreError => e
|
39
|
-
raise e
|
40
|
-
rescue Exception => e
|
41
|
-
raise BlobstoreError,
|
42
|
-
"Failed to create object, underlying error: %s %s" %
|
43
|
-
[e.message, e.backtrace.join("\n")]
|
30
|
+
File.open(path, 'w') do |file|
|
31
|
+
file.write(contents)
|
44
32
|
end
|
33
|
+
return create_file(id, File.open(path, 'r'))
|
45
34
|
end
|
46
35
|
end
|
36
|
+
rescue BlobstoreError => e
|
37
|
+
raise e
|
38
|
+
rescue Exception => e
|
39
|
+
raise BlobstoreError,
|
40
|
+
sprintf('Failed to create object, underlying error: %s %s', e.inspect, e.backtrace.join("\n"))
|
47
41
|
end
|
48
42
|
|
43
|
+
# Get an object from the blobstore.
|
44
|
+
# @param [String] id object id
|
45
|
+
# @param [File] file where to store the fetched object
|
46
|
+
# @return [String] the object contents if the file parameter is nil
|
49
47
|
def get(id, file = nil)
|
50
48
|
if file
|
51
49
|
get_file(id, file)
|
50
|
+
file.flush
|
52
51
|
else
|
53
52
|
result = nil
|
54
53
|
temp_path do |path|
|
55
|
-
|
56
|
-
|
57
|
-
result = File.open(path, "r") { |file| file.read }
|
58
|
-
rescue BlobstoreError => e
|
59
|
-
raise e
|
60
|
-
rescue Exception => e
|
61
|
-
raise BlobstoreError,
|
62
|
-
"Failed to create object, underlying error: %s %s" %
|
63
|
-
[e.message, e.backtrace.join("\n")]
|
64
|
-
end
|
54
|
+
File.open(path, 'w') { |f| get_file(id, f) }
|
55
|
+
result = File.open(path, 'r') { |f| f.read }
|
65
56
|
end
|
66
57
|
result
|
67
58
|
end
|
59
|
+
rescue BlobstoreError => e
|
60
|
+
raise e
|
61
|
+
rescue Exception => e
|
62
|
+
raise BlobstoreError,
|
63
|
+
sprintf('Failed to fetch object, underlying error: %s %s', e.inspect, e.backtrace.join("\n"))
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [void]
|
67
|
+
def delete(oid)
|
68
|
+
delete_object(oid)
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
def exists?(oid)
|
73
|
+
object_exists?(oid)
|
68
74
|
end
|
69
75
|
|
70
76
|
protected
|
71
77
|
|
78
|
+
# @return [String] the id
|
79
|
+
def create_file(id, file)
|
80
|
+
# needs to be implemented in each subclass
|
81
|
+
not_supported
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_file(id, file)
|
85
|
+
# needs to be implemented in each subclass
|
86
|
+
not_supported
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete_object(oid)
|
90
|
+
# needs to be implemented in each subclass
|
91
|
+
not_supported
|
92
|
+
end
|
93
|
+
|
94
|
+
def object_exists?(oid)
|
95
|
+
# needs to be implemented in each subclass
|
96
|
+
not_supported
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate_object_id
|
100
|
+
SecureRandom.uuid
|
101
|
+
end
|
102
|
+
|
72
103
|
def temp_path
|
73
|
-
path = File.join(Dir
|
104
|
+
path = File.join(Dir.tmpdir, "temp-path-#{SecureRandom.uuid}")
|
74
105
|
begin
|
75
106
|
yield path if block_given?
|
76
107
|
path
|
@@ -79,6 +110,11 @@ module Bosh
|
|
79
110
|
end
|
80
111
|
end
|
81
112
|
|
113
|
+
private
|
114
|
+
|
115
|
+
def not_supported
|
116
|
+
raise NotImplemented, 'not supported by this blobstore'
|
117
|
+
end
|
82
118
|
end
|
83
119
|
end
|
84
120
|
end
|