fog-backblaze 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile +5 -1
- data/README.md +6 -0
- data/Rakefile +1 -1
- data/examples/directory_model.rb +78 -0
- data/lib/fog/backblaze/version.rb +1 -1
- data/lib/fog/storage/backblaze.rb +3 -2
- data/lib/fog/storage/backblaze/models/directory.rb +11 -0
- data/lib/fog/storage/backblaze/real.rb +90 -15
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5decfdf565507b6f9426990d2a6b4a7d5df99d1f
|
4
|
+
data.tar.gz: e5b109b24fbf90c10644d890a31358e236991822
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01cb22086898cbbc02f5daedcfb13f8315210f43769bf04c0b82f29d71804bfcd3a35c44ffe90a56f93db8861af201356c1bbe3bd04e12a4876a0a13b5dace55
|
7
|
+
data.tar.gz: 6898b75ab5cb46e06ede150d7b0e0b707e64d05378602279ef62b647c02c59fa49f361a27ee11b66876a14bf3e30bbed14437103372983537a5123a4fd7d7774
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
0.2.0 2018-08-16
|
2
|
+
==========================================================
|
3
|
+
|
4
|
+
- Add support for api keys
|
5
|
+
- More tests
|
6
|
+
- Add CHANGELOG.md
|
7
|
+
|
8
|
+
0.1.2 2018-05-19
|
9
|
+
==========================================================
|
10
|
+
|
11
|
+
- Support IO objects for #put_object
|
12
|
+
- Support `options[:extra_headers]` for #put_object
|
13
|
+
- Use autoload
|
14
|
+
- Add #update_bucket
|
15
|
+
- Always use `::JSON`
|
16
|
+
|
17
|
+
0.1.1 2018-03-25
|
18
|
+
==========================================================
|
19
|
+
|
20
|
+
- Basic functionality
|
data/Gemfile
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
|
3
|
+
git_source(:github) do |repo_name|
|
4
|
+
"https://github.com/#{repo_name}.git"
|
5
|
+
end
|
6
|
+
|
4
7
|
gemspec
|
5
8
|
|
6
9
|
gem "bundler", ">= 1.15"
|
7
10
|
gem "rake", "~> 12.0"
|
8
11
|
gem "minitest", ">= 5.0"
|
12
|
+
gem 'minitest-reporters', '1.3.2.beta2'
|
data/README.md
CHANGED
@@ -23,6 +23,12 @@ require "fog/backblaze"
|
|
23
23
|
|
24
24
|
connection = Fog::Storage.new(
|
25
25
|
provider: 'backblaze',
|
26
|
+
|
27
|
+
# with one key (more secure)
|
28
|
+
b2_key_id: 'xxxx',
|
29
|
+
b2_key_token: 'zzzxxxccc'
|
30
|
+
|
31
|
+
# full access to b2 account (less secure)
|
26
32
|
b2_account_id: '123456',
|
27
33
|
b2_account_token: 'aaaaabbbbbccccddddeeeeeffffff111112222223333',
|
28
34
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
$:.push(File.expand_path("../../lib", __FILE__))
|
5
|
+
|
6
|
+
require_relative "../lib/fog/backblaze"
|
7
|
+
|
8
|
+
if !ENV['B2_ACCOUNT_ID'] || ENV['B2_ACCOUNT_ID'] == ""
|
9
|
+
puts "Missing env B2_ACCOUNT_ID"
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
if !ENV['B2_ACCOUNT_TOKEN'] || ENV['B2_ACCOUNT_TOKEN'] == ""
|
14
|
+
puts "Missing env B2_ACCOUNT_TOKEN"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
connection = Fog::Storage.new(
|
19
|
+
provider: 'backblaze',
|
20
|
+
b2_account_id: ENV['B2_ACCOUNT_ID'],
|
21
|
+
b2_account_token: ENV['B2_ACCOUNT_TOKEN'],
|
22
|
+
|
23
|
+
logger: ENV['DEBUG'] ? Logger.new(STDOUT) : nil
|
24
|
+
)
|
25
|
+
|
26
|
+
bucket_name = "fog-demo-#{Time.now.to_i}"
|
27
|
+
|
28
|
+
# creating bucket with all possible options
|
29
|
+
|
30
|
+
directory = connection.directories.create(
|
31
|
+
key: bucket_name,
|
32
|
+
public: false,
|
33
|
+
bucket_info: {
|
34
|
+
test_key: "Test value"
|
35
|
+
},
|
36
|
+
lifecycle_rules: [
|
37
|
+
{
|
38
|
+
fileNamePrefix: "aaa",
|
39
|
+
daysFromUploadingToHiding: 10,
|
40
|
+
daysFromHidingToDeleting: 20
|
41
|
+
}
|
42
|
+
],
|
43
|
+
cors_rules: [
|
44
|
+
{
|
45
|
+
corsRuleName: "downloadFromAnyOrigin",
|
46
|
+
allowedOrigins: ["https"],
|
47
|
+
allowedHeaders: ["range"],
|
48
|
+
allowedOperations: [
|
49
|
+
"b2_download_file_by_id",
|
50
|
+
"b2_download_file_by_name"
|
51
|
+
],
|
52
|
+
exposeHeaders: ["x-bz-content-sha1"],
|
53
|
+
maxAgeSeconds: 3600
|
54
|
+
}
|
55
|
+
]
|
56
|
+
)
|
57
|
+
|
58
|
+
p directory
|
59
|
+
|
60
|
+
# delete new bucket on exit
|
61
|
+
at_exit do
|
62
|
+
directory.files.each do |file|
|
63
|
+
puts "removing file #{file.key}"
|
64
|
+
p file.destroy
|
65
|
+
end
|
66
|
+
puts "removing a bucket #{directory.key}"
|
67
|
+
p directory.destroy
|
68
|
+
end
|
69
|
+
|
70
|
+
# list directories (buckets)
|
71
|
+
p connection.directories
|
72
|
+
|
73
|
+
# upload in new bucket
|
74
|
+
file = directory.files.create(
|
75
|
+
key: 'Gemfile.lock',
|
76
|
+
body: File.open("./icco_example.rb"),
|
77
|
+
public: true
|
78
|
+
)
|
@@ -3,8 +3,9 @@ require 'digest'
|
|
3
3
|
require 'cgi'
|
4
4
|
|
5
5
|
class Fog::Storage::Backblaze < Fog::Service
|
6
|
-
requires
|
7
|
-
recognizes :
|
6
|
+
#requires
|
7
|
+
recognizes :b2_account_id, :b2_account_token, :b2_key_id, :b2_key_token,
|
8
|
+
:b2_bucket_name, :b2_bucket_id, :token_cache, :logger
|
8
9
|
|
9
10
|
model_path 'fog/storage/backblaze/models'
|
10
11
|
model :directory
|
@@ -10,6 +10,17 @@ class Fog::Storage::Backblaze::Directory < Fog::Model
|
|
10
10
|
|
11
11
|
alias_method :name, :key
|
12
12
|
|
13
|
+
def initialize(attrs)
|
14
|
+
attrs = attrs.dup
|
15
|
+
attrs['bucket_id'] = attrs['bucketId']
|
16
|
+
attrs['bucket_info'] = attrs['bucketInfo']
|
17
|
+
attrs['bucket_type'] = attrs['bucketType']
|
18
|
+
attrs['cors_rules'] = attrs['corsRules']
|
19
|
+
attrs['lifecycle_rules'] = attrs['lifecycleRules']
|
20
|
+
|
21
|
+
super(attrs)
|
22
|
+
end
|
23
|
+
|
13
24
|
def destroy
|
14
25
|
requires :key
|
15
26
|
response = service.delete_bucket(key)
|
@@ -28,7 +28,7 @@ class Fog::Storage::Backblaze::Real
|
|
28
28
|
# call b2_create_bucket
|
29
29
|
def put_bucket(bucket_name, extra_options = {})
|
30
30
|
options = {
|
31
|
-
accountId:
|
31
|
+
accountId: b2_account_id,
|
32
32
|
bucketType: extra_options.delete(:public) ? 'allPublic' : 'allPrivate',
|
33
33
|
bucketName: bucket_name,
|
34
34
|
}.merge(extra_options)
|
@@ -52,7 +52,7 @@ class Fog::Storage::Backblaze::Real
|
|
52
52
|
# if options[:bucketId] presents, then bucket_name is option
|
53
53
|
def update_bucket(bucket_name, extra_options)
|
54
54
|
options = {
|
55
|
-
accountId:
|
55
|
+
accountId: b2_account_id,
|
56
56
|
bucketId: extra_options[:bucketId] || _get_bucket_id!(bucket_name),
|
57
57
|
}
|
58
58
|
if extra_options.has_key?(:public)
|
@@ -76,22 +76,24 @@ class Fog::Storage::Backblaze::Real
|
|
76
76
|
end
|
77
77
|
|
78
78
|
# call b2_list_buckets
|
79
|
-
def list_buckets
|
80
|
-
response = b2_command(:b2_list_buckets, body: {
|
79
|
+
def list_buckets(options = {})
|
80
|
+
response = b2_command(:b2_list_buckets, body: {
|
81
|
+
accountId: b2_account_id
|
82
|
+
}.merge(options))
|
81
83
|
|
82
84
|
response
|
83
85
|
end
|
84
86
|
|
85
87
|
# call b2_list_buckets
|
86
88
|
def get_bucket(bucket_name)
|
87
|
-
response = list_buckets
|
89
|
+
response = list_buckets(bucketName: bucket_name)
|
90
|
+
|
88
91
|
bucket = response.json['buckets'].detect do |bucket|
|
89
92
|
bucket['bucketName'] == bucket_name
|
90
93
|
end
|
91
94
|
|
92
95
|
unless bucket
|
93
|
-
raise Fog::Errors::NotFound, "No bucket with name: #{bucket_name}
|
94
|
-
"found buckets: #{response.json['buckets'].map {|b| b['bucketName']}.join(", ")}"
|
96
|
+
raise Fog::Errors::NotFound, "No bucket with name: #{bucket_name}"
|
95
97
|
end
|
96
98
|
|
97
99
|
response.body = bucket
|
@@ -106,7 +108,7 @@ class Fog::Storage::Backblaze::Real
|
|
106
108
|
response = b2_command(:b2_delete_bucket,
|
107
109
|
body: {
|
108
110
|
bucketId: bucket_id,
|
109
|
-
accountId:
|
111
|
+
accountId: b2_account_id
|
110
112
|
}
|
111
113
|
)
|
112
114
|
|
@@ -292,6 +294,50 @@ class Fog::Storage::Backblaze::Real
|
|
292
294
|
last_response
|
293
295
|
end
|
294
296
|
|
297
|
+
# TODO TEST
|
298
|
+
# call b2_create_key
|
299
|
+
def create_key(name, capabilities: nil, bucket_id: nil, name_prefix: nil)
|
300
|
+
capabilities ||= [
|
301
|
+
'listKeys',
|
302
|
+
'writeKeys',
|
303
|
+
'deleteKeys',
|
304
|
+
'listBuckets',
|
305
|
+
'writeBuckets',
|
306
|
+
'deleteBuckets',
|
307
|
+
'listFiles',
|
308
|
+
'readFiles',
|
309
|
+
'shareFiles',
|
310
|
+
'writeFiles',
|
311
|
+
'deleteFiles'
|
312
|
+
]
|
313
|
+
|
314
|
+
response = b2_command(:b2_create_key,
|
315
|
+
body: {
|
316
|
+
accountId: b2_account_id,
|
317
|
+
keyName: name,
|
318
|
+
capabilities: capabilities,
|
319
|
+
bucketId: bucket_id,
|
320
|
+
namePrefix: name_prefix
|
321
|
+
}
|
322
|
+
)
|
323
|
+
end
|
324
|
+
|
325
|
+
# call b2_list_keys
|
326
|
+
def list_keys
|
327
|
+
response = b2_command(:b2_list_keys,
|
328
|
+
body: {
|
329
|
+
accountId: b2_account_id,
|
330
|
+
maxKeyCount: 1000
|
331
|
+
}
|
332
|
+
)
|
333
|
+
|
334
|
+
if response.status > 400
|
335
|
+
raise Fog::Errors::Error, "Failed get_object, status = #{response.status} #{response.body}"
|
336
|
+
end
|
337
|
+
|
338
|
+
response
|
339
|
+
end
|
340
|
+
|
295
341
|
def _get_object_version_ids(bucket_name, file_name)
|
296
342
|
response = b2_command(:b2_list_file_versions,
|
297
343
|
body: {
|
@@ -335,7 +381,7 @@ class Fog::Storage::Backblaze::Real
|
|
335
381
|
def _get_bucket_id!(bucket_name)
|
336
382
|
bucket_id = _get_bucket_id(bucket_name)
|
337
383
|
unless bucket_id
|
338
|
-
raise Fog::Errors::NotFound, "Can not find bucket #{bucket_name}"
|
384
|
+
raise Fog::Errors::NotFound, "Can not find bucket \"#{bucket_name}\""
|
339
385
|
end
|
340
386
|
|
341
387
|
return bucket_id
|
@@ -365,9 +411,19 @@ class Fog::Storage::Backblaze::Real
|
|
365
411
|
return cached
|
366
412
|
end
|
367
413
|
|
414
|
+
auth_string = if @options[:b2_account_id] && @options[:b2_account_token]
|
415
|
+
"#{@options[:b2_account_id]}:#{@options[:b2_account_token]}"
|
416
|
+
elsif @options[:b2_key_id] && @options[:b2_key_token]
|
417
|
+
"#{@options[:b2_key_id]}:#{@options[:b2_key_token]}"
|
418
|
+
else
|
419
|
+
raise Fog::Errors::Error, "B2 credentials are required, "\
|
420
|
+
"please use b2_account_id and b2_account_token or "\
|
421
|
+
"b2_key_id and b2_key_token"
|
422
|
+
end
|
423
|
+
|
368
424
|
@auth_response = json_req(:get, "https://api.backblazeb2.com/b2api/v1/b2_authorize_account",
|
369
425
|
headers: {
|
370
|
-
"Authorization" => "Basic " + Base64.strict_encode64(
|
426
|
+
"Authorization" => "Basic " + Base64.strict_encode64(auth_string)
|
371
427
|
},
|
372
428
|
persistent: false
|
373
429
|
)
|
@@ -400,7 +456,11 @@ class Fog::Storage::Backblaze::Real
|
|
400
456
|
def json_req(method, url, options = {})
|
401
457
|
start_time = Time.now.to_f
|
402
458
|
logger.info("Req #{method.to_s.upcase} #{url}")
|
403
|
-
|
459
|
+
if options[:body] && options[:body].size > 300
|
460
|
+
logger.debug(options.merge(body: "-- Body #{options[:body].size} bytes --").to_s)
|
461
|
+
else
|
462
|
+
logger.debug(options.to_s)
|
463
|
+
end
|
404
464
|
|
405
465
|
if !options.has_key?(:persistent) || options[:persistent] == true
|
406
466
|
@connections ||= {}
|
@@ -413,14 +473,20 @@ class Fog::Storage::Backblaze::Real
|
|
413
473
|
end
|
414
474
|
|
415
475
|
http_response.extend(Fog::Backblaze::JSONResponse)
|
416
|
-
http_response.
|
476
|
+
if http_response.josn_response? && http_response.body.size > 0
|
477
|
+
http_response.assign_json_body!
|
478
|
+
end
|
417
479
|
|
418
480
|
http_response
|
419
481
|
ensure
|
420
482
|
status = http_response && http_response.status
|
421
|
-
logger.info("Done #{method.to_s.upcase} #{url} = #{status} (#{(Time.now.to_f - start_time).round(3)} sec)")
|
422
|
-
|
423
|
-
|
483
|
+
logger.info(" Done #{method.to_s.upcase} #{url} = #{status} (#{(Time.now.to_f - start_time).round(3)} sec)")
|
484
|
+
if http_response
|
485
|
+
logger.debug(" Headers: #{http_response.headers}")
|
486
|
+
if method != :head && http_response.headers['Content-Type'].to_s !~ %r{^image/}
|
487
|
+
logger.debug(" Body: #{http_response.body}")
|
488
|
+
end
|
489
|
+
end
|
424
490
|
end
|
425
491
|
|
426
492
|
def reset_token_cache
|
@@ -430,4 +496,13 @@ class Fog::Storage::Backblaze::Real
|
|
430
496
|
def _esc_file(file_name)
|
431
497
|
CGI.escape(file_name).gsub('%2F', '/')
|
432
498
|
end
|
499
|
+
|
500
|
+
# return @options[:b2_account_id] or call b2_authorize_account when using application key
|
501
|
+
def b2_account_id
|
502
|
+
return @options[:b2_account_id] if @options[:b2_account_id]
|
503
|
+
|
504
|
+
auth = auth_response
|
505
|
+
p auth
|
506
|
+
auth['accountId']
|
507
|
+
end
|
433
508
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fog-backblaze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Evstigneev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fog-core
|
@@ -40,12 +40,14 @@ extra_rdoc_files: []
|
|
40
40
|
files:
|
41
41
|
- ".gitignore"
|
42
42
|
- ".travis.yml"
|
43
|
+
- CHANGELOG.md
|
43
44
|
- Gemfile
|
44
45
|
- LICENSE
|
45
46
|
- README.md
|
46
47
|
- Rakefile
|
47
48
|
- bin/console
|
48
49
|
- bin/setup
|
50
|
+
- examples/directory_model.rb
|
49
51
|
- examples/example.rb
|
50
52
|
- fog-backblaze.gemspec
|
51
53
|
- lib/fog/backblaze.rb
|