fog 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.rdoc +1 -0
- data/fog.gemspec +44 -1
- data/lib/fog.rb +2 -1
- data/lib/fog/bin.rb +2 -0
- data/lib/fog/google.rb +22 -0
- data/lib/fog/google/bin.rb +20 -0
- data/lib/fog/google/models/storage/directories.rb +43 -0
- data/lib/fog/google/models/storage/directory.rb +48 -0
- data/lib/fog/google/models/storage/file.rb +87 -0
- data/lib/fog/google/models/storage/files.rb +94 -0
- data/lib/fog/google/parsers/storage/access_control_list.rb +46 -0
- data/lib/fog/google/parsers/storage/copy_object.rb +22 -0
- data/lib/fog/google/parsers/storage/get_bucket.rb +46 -0
- data/lib/fog/google/parsers/storage/get_bucket_logging.rb +40 -0
- data/lib/fog/google/parsers/storage/get_bucket_object_versions.rb +88 -0
- data/lib/fog/google/parsers/storage/get_bucket_versioning.rb +24 -0
- data/lib/fog/google/parsers/storage/get_request_payment.rb +20 -0
- data/lib/fog/google/parsers/storage/get_service.rb +32 -0
- data/lib/fog/google/requests/storage/copy_object.rb +72 -0
- data/lib/fog/google/requests/storage/delete_bucket.rb +46 -0
- data/lib/fog/google/requests/storage/delete_object.rb +50 -0
- data/lib/fog/google/requests/storage/get_bucket.rb +110 -0
- data/lib/fog/google/requests/storage/get_bucket_acl.rb +55 -0
- data/lib/fog/google/requests/storage/get_object.rb +104 -0
- data/lib/fog/google/requests/storage/get_object_acl.rb +66 -0
- data/lib/fog/google/requests/storage/get_object_torrent.rb +55 -0
- data/lib/fog/google/requests/storage/get_object_url.rb +54 -0
- data/lib/fog/google/requests/storage/get_service.rb +53 -0
- data/lib/fog/google/requests/storage/head_object.rb +64 -0
- data/lib/fog/google/requests/storage/put_bucket.rb +68 -0
- data/lib/fog/google/requests/storage/put_bucket_acl.rb +80 -0
- data/lib/fog/google/requests/storage/put_object.rb +71 -0
- data/lib/fog/google/requests/storage/put_object_url.rb +54 -0
- data/lib/fog/google/storage.rb +192 -0
- data/spec/google/models/storage/directories_spec.rb +49 -0
- data/spec/google/models/storage/directory_spec.rb +83 -0
- data/spec/google/models/storage/file_spec.rb +121 -0
- data/spec/google/models/storage/files_spec.rb +141 -0
- data/spec/google/requests/storage/copy_object_spec.rb +61 -0
- data/spec/google/requests/storage/delete_bucket_spec.rb +35 -0
- data/spec/google/requests/storage/delete_object_spec.rb +38 -0
- data/spec/google/requests/storage/get_bucket_spec.rb +110 -0
- data/spec/google/requests/storage/get_object_spec.rb +58 -0
- data/spec/google/requests/storage/get_service_spec.rb +32 -0
- data/spec/google/requests/storage/head_object_spec.rb +26 -0
- data/spec/google/requests/storage/put_bucket_spec.rb +21 -0
- data/spec/google/requests/storage/put_object_spec.rb +43 -0
- metadata +45 -2
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'pp'
|
2
|
+
module Fog
|
3
|
+
module Google
|
4
|
+
class Storage
|
5
|
+
class Real
|
6
|
+
|
7
|
+
require 'fog/google/parsers/storage/get_bucket'
|
8
|
+
|
9
|
+
# List information about objects in an Google Storage bucket
|
10
|
+
#
|
11
|
+
# ==== Parameters
|
12
|
+
# * bucket_name<~String> - name of bucket to list object keys from
|
13
|
+
# * options<~Hash> - config arguments for list. Defaults to {}.
|
14
|
+
# * 'delimiter'<~String> - causes keys with the same string between the prefix
|
15
|
+
# value and the first occurence of delimiter to be rolled up
|
16
|
+
# * 'marker'<~String> - limits object keys to only those that appear
|
17
|
+
# lexicographically after its value.
|
18
|
+
# * 'max-keys'<~Integer> - limits number of object keys returned
|
19
|
+
# * 'prefix'<~String> - limits object keys to those beginning with its value.
|
20
|
+
#
|
21
|
+
# ==== Returns
|
22
|
+
# * response<~Excon::Response>:
|
23
|
+
# * body<~Hash>:
|
24
|
+
# * 'Delimeter'<~String> - Delimiter specified for query
|
25
|
+
# * 'IsTruncated'<~Boolean> - Whether or not the listing is truncated
|
26
|
+
# * 'Marker'<~String> - Marker specified for query
|
27
|
+
# * 'MaxKeys'<~Integer> - Maximum number of keys specified for query
|
28
|
+
# * 'Name'<~String> - Name of the bucket
|
29
|
+
# * 'Prefix'<~String> - Prefix specified for query
|
30
|
+
# * 'Contents'<~Array>:
|
31
|
+
# * 'ETag'<~String>: Etag of object
|
32
|
+
# * 'Key'<~String>: Name of object
|
33
|
+
# * 'LastModified'<~String>: Timestamp of last modification of object
|
34
|
+
# * 'Owner'<~Hash>:
|
35
|
+
# * 'DisplayName'<~String> - Display name of object owner
|
36
|
+
# * 'ID'<~String> - Id of object owner
|
37
|
+
# * 'Size'<~Integer> - Size of object
|
38
|
+
# * 'StorageClass'<~String> - Storage class of object
|
39
|
+
#
|
40
|
+
def get_bucket(bucket_name, options = {})
|
41
|
+
unless bucket_name
|
42
|
+
raise ArgumentError.new('bucket_name is required')
|
43
|
+
end
|
44
|
+
request({
|
45
|
+
:expects => 200,
|
46
|
+
:headers => {},
|
47
|
+
:host => "#{bucket_name}.#{@host}",
|
48
|
+
:idempotent => true,
|
49
|
+
:method => 'GET',
|
50
|
+
:parser => Fog::Parsers::Google::Storage::GetBucket.new,
|
51
|
+
:query => options
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class Mock
|
58
|
+
|
59
|
+
def get_bucket(bucket_name, options = {})
|
60
|
+
unless bucket_name
|
61
|
+
raise ArgumentError.new('bucket_name is required')
|
62
|
+
end
|
63
|
+
response = Excon::Response.new
|
64
|
+
name = /(\w+\.?)*/.match(bucket_name)
|
65
|
+
if bucket_name == name.to_s
|
66
|
+
if bucket = @data[:buckets][bucket_name]
|
67
|
+
contents = bucket[:objects].values.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object|
|
68
|
+
(options['prefix'] && object['Key'][0...options['prefix'].length] != options['prefix']) ||
|
69
|
+
(options['marker'] && object['Key'] <= options['marker'])
|
70
|
+
end.map do |object|
|
71
|
+
data = object.reject {|key, value| !['ETag', 'Key', 'LastModified', 'Size', 'StorageClass'].include?(key)}
|
72
|
+
data.merge!({
|
73
|
+
'LastModified' => Time.parse(data['LastModified']),
|
74
|
+
'Owner' => bucket['Owner'],
|
75
|
+
'Size' => data['Size'].to_i
|
76
|
+
})
|
77
|
+
data
|
78
|
+
end
|
79
|
+
max_keys = options['max-keys'] || 1000
|
80
|
+
size = [max_keys, 1000].min
|
81
|
+
truncated_contents = contents[0...size]
|
82
|
+
|
83
|
+
response.status = 200
|
84
|
+
response.body = {
|
85
|
+
'Contents' => truncated_contents,
|
86
|
+
'IsTruncated' => truncated_contents.size != contents.size,
|
87
|
+
'Marker' => options['marker'],
|
88
|
+
'MaxKeys' => max_keys,
|
89
|
+
'Name' => bucket['Name'],
|
90
|
+
'Prefix' => options['prefix']
|
91
|
+
}
|
92
|
+
if options['max-keys'] && options['max-keys'] < response.body['Contents'].length
|
93
|
+
response.body['IsTruncated'] = true
|
94
|
+
response.body['Contents'] = response.body['Contents'][0...options['max-keys']]
|
95
|
+
end
|
96
|
+
else
|
97
|
+
response.status = 404
|
98
|
+
raise(Excon::Errors.status_error({:expects => 200}, response))
|
99
|
+
end
|
100
|
+
else
|
101
|
+
response.status = 400
|
102
|
+
raise(Excon::Errors.status_error({:expects => 200}, response))
|
103
|
+
end
|
104
|
+
response
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
|
6
|
+
require 'fog/google/parsers/storage/access_control_list'
|
7
|
+
|
8
|
+
# Get access control list for an Google Storage bucket
|
9
|
+
#
|
10
|
+
# ==== Parameters
|
11
|
+
# * bucket_name<~String> - name of bucket to get access control list for
|
12
|
+
#
|
13
|
+
# ==== Returns
|
14
|
+
# * response<~Excon::Response>:
|
15
|
+
# * body<~Hash>:
|
16
|
+
# * 'AccessControlPolicy'<~Hash>
|
17
|
+
# * 'Owner'<~Hash>:
|
18
|
+
# * 'DisplayName'<~String> - Display name of object owner
|
19
|
+
# * 'ID'<~String> - Id of object owner
|
20
|
+
# * 'AccessControlList'<~Array>:
|
21
|
+
# * 'Grant'<~Hash>:
|
22
|
+
# * 'Grantee'<~Hash>:
|
23
|
+
# * 'DisplayName'<~String> - Display name of grantee
|
24
|
+
# * 'ID'<~String> - Id of grantee
|
25
|
+
# or
|
26
|
+
# * 'URI'<~String> - URI of group to grant access for
|
27
|
+
# * 'Permission'<~String> - Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]
|
28
|
+
#
|
29
|
+
def get_bucket_acl(bucket_name)
|
30
|
+
unless bucket_name
|
31
|
+
raise ArgumentError.new('bucket_name is required')
|
32
|
+
end
|
33
|
+
request({
|
34
|
+
:expects => 200,
|
35
|
+
:headers => {},
|
36
|
+
:host => "#{bucket_name}.#{@host}",
|
37
|
+
:idempotent => true,
|
38
|
+
:method => 'GET',
|
39
|
+
:parser => Fog::Parsers::Google::Storage::AccessControlList.new,
|
40
|
+
:query => {'acl' => nil}
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class Mock
|
47
|
+
|
48
|
+
def get_bucket_acl(bucket_name)
|
49
|
+
Fog::Mock.not_implemented
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
|
6
|
+
# Get an object from Google Storage
|
7
|
+
#
|
8
|
+
# ==== Parameters
|
9
|
+
# * bucket_name<~String> - Name of bucket to read from
|
10
|
+
# * object_name<~String> - Name of object to read
|
11
|
+
# * options<~Hash>:
|
12
|
+
# * 'If-Match'<~String> - Returns object only if its etag matches this value, otherwise returns 412 (Precondition Failed).
|
13
|
+
# * 'If-Modified-Since'<~Time> - Returns object only if it has been modified since this time, otherwise returns 304 (Not Modified).
|
14
|
+
# * 'If-None-Match'<~String> - Returns object only if its etag differs from this value, otherwise returns 304 (Not Modified)
|
15
|
+
# * 'If-Unmodified-Since'<~Time> - Returns object only if it has not been modified since this time, otherwise returns 412 (Precodition Failed).
|
16
|
+
# * 'Range'<~String> - Range of object to download
|
17
|
+
# * 'versionId'<~String> - specify a particular version to retrieve
|
18
|
+
#
|
19
|
+
# ==== Returns
|
20
|
+
# * response<~Excon::Response>:
|
21
|
+
# * body<~String> - Contents of object
|
22
|
+
# * headers<~Hash>:
|
23
|
+
# * 'Content-Length'<~String> - Size of object contents
|
24
|
+
# * 'Content-Type'<~String> - MIME type of object
|
25
|
+
# * 'ETag'<~String> - Etag of object
|
26
|
+
# * 'Last-Modified'<~String> - Last modified timestamp for object
|
27
|
+
#
|
28
|
+
def get_object(bucket_name, object_name, options = {}, &block)
|
29
|
+
unless bucket_name
|
30
|
+
raise ArgumentError.new('bucket_name is required')
|
31
|
+
end
|
32
|
+
unless object_name
|
33
|
+
raise ArgumentError.new('object_name is required')
|
34
|
+
end
|
35
|
+
if version_id = options.delete('versionId')
|
36
|
+
query = {'versionId' => version_id}
|
37
|
+
end
|
38
|
+
headers = {}
|
39
|
+
headers['If-Modified-Since'] = options['If-Modified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since']
|
40
|
+
headers['If-Unmodified-Since'] = options['If-Unmodified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since']
|
41
|
+
headers.merge!(options)
|
42
|
+
request({
|
43
|
+
:expects => 200,
|
44
|
+
:headers => headers,
|
45
|
+
:host => "#{bucket_name}.#{@host}",
|
46
|
+
:idempotent => true,
|
47
|
+
:method => 'GET',
|
48
|
+
:path => CGI.escape(object_name),
|
49
|
+
:query => query
|
50
|
+
}, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class Mock
|
56
|
+
|
57
|
+
def get_object(bucket_name, object_name, options = {}, &block)
|
58
|
+
unless bucket_name
|
59
|
+
raise ArgumentError.new('bucket_name is required')
|
60
|
+
end
|
61
|
+
unless object_name
|
62
|
+
raise ArgumentError.new('object_name is required')
|
63
|
+
end
|
64
|
+
response = Excon::Response.new
|
65
|
+
if (bucket = @data[:buckets][bucket_name]) && (object = bucket[:objects][object_name])
|
66
|
+
if options['If-Match'] && options['If-Match'] != object['ETag']
|
67
|
+
response.status = 412
|
68
|
+
elsif options['If-Modified-Since'] && options['If-Modified-Since'] > Time.parse(object['LastModified'])
|
69
|
+
response.status = 304
|
70
|
+
elsif options['If-None-Match'] && options['If-None-Match'] == object['ETag']
|
71
|
+
response.status = 304
|
72
|
+
elsif options['If-Unmodified-Since'] && options['If-Unmodified-Since'] < Time.parse(object['LastModified'])
|
73
|
+
response.status = 412
|
74
|
+
else
|
75
|
+
response.status = 200
|
76
|
+
response.headers = {
|
77
|
+
'Content-Length' => object['Size'],
|
78
|
+
'Content-Type' => object['Content-Type'],
|
79
|
+
'ETag' => object['ETag'],
|
80
|
+
'Last-Modified' => object['LastModified']
|
81
|
+
}
|
82
|
+
unless block_given?
|
83
|
+
response.body = object[:body]
|
84
|
+
else
|
85
|
+
data = StringIO.new(object[:body])
|
86
|
+
remaining = data.length
|
87
|
+
while remaining > 0
|
88
|
+
chunk = data.read([remaining, Excon::CHUNK_SIZE].min)
|
89
|
+
block.call(chunk)
|
90
|
+
remaining -= Excon::CHUNK_SIZE
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
else
|
95
|
+
response.status = 404
|
96
|
+
raise(Excon::Errors.status_error({:expects => 200}, response))
|
97
|
+
end
|
98
|
+
response
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
|
6
|
+
require 'fog/google/parsers/storage/access_control_list'
|
7
|
+
|
8
|
+
# Get access control list for an Google Storage object
|
9
|
+
#
|
10
|
+
# ==== Parameters
|
11
|
+
# * bucket_name<~String> - name of bucket containing object
|
12
|
+
# * object_name<~String> - name of object to get access control list for
|
13
|
+
# * options<~Hash>:
|
14
|
+
# * 'versionId'<~String> - specify a particular version to retrieve
|
15
|
+
#
|
16
|
+
# ==== Returns
|
17
|
+
# * response<~Excon::Response>:
|
18
|
+
# * body<~Hash>:
|
19
|
+
# * 'AccessControlPolicy'<~Hash>
|
20
|
+
# * 'Owner'<~Hash>:
|
21
|
+
# * 'DisplayName'<~String> - Display name of object owner
|
22
|
+
# * 'ID'<~String> - Id of object owner
|
23
|
+
# * 'AccessControlList'<~Array>:
|
24
|
+
# * 'Grant'<~Hash>:
|
25
|
+
# * 'Grantee'<~Hash>:
|
26
|
+
# * 'DisplayName'<~String> - Display name of grantee
|
27
|
+
# * 'ID'<~String> - Id of grantee
|
28
|
+
# or
|
29
|
+
# * 'URI'<~String> - URI of group to grant access for
|
30
|
+
# * 'Permission'<~String> - Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]
|
31
|
+
#
|
32
|
+
def get_object_acl(bucket_name, object_name, options = {})
|
33
|
+
unless bucket_name
|
34
|
+
raise ArgumentError.new('bucket_name is required')
|
35
|
+
end
|
36
|
+
unless object_name
|
37
|
+
raise ArgumentError.new('object_name is required')
|
38
|
+
end
|
39
|
+
query = {'acl' => nil}
|
40
|
+
if version_id = options.delete('versionId')
|
41
|
+
query['versionId'] = version_id
|
42
|
+
end
|
43
|
+
request({
|
44
|
+
:expects => 200,
|
45
|
+
:headers => {},
|
46
|
+
:host => "#{bucket_name}.#{@host}",
|
47
|
+
:idempotent => true,
|
48
|
+
:method => 'GET',
|
49
|
+
:parser => Fog::Parsers::Google::Storage::AccessControlList.new,
|
50
|
+
:path => CGI.escape(object_name),
|
51
|
+
:query => query
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class Mock
|
58
|
+
|
59
|
+
def get_object_acl(bucket_name, object_name)
|
60
|
+
Fog::Mock.not_implemented
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
|
6
|
+
# Get torrent for an Google Storage object
|
7
|
+
#
|
8
|
+
# ==== Parameters
|
9
|
+
# * bucket_name<~String> - name of bucket containing object
|
10
|
+
# * object_name<~String> - name of object to get torrent for
|
11
|
+
#
|
12
|
+
# ==== Returns
|
13
|
+
# * response<~Excon::Response>:
|
14
|
+
# * body<~Hash>:
|
15
|
+
# * 'AccessControlPolicy'<~Hash>
|
16
|
+
# * 'Owner'<~Hash>:
|
17
|
+
# * 'DisplayName'<~String> - Display name of object owner
|
18
|
+
# * 'ID'<~String> - Id of object owner
|
19
|
+
# * 'AccessControlList'<~Array>:
|
20
|
+
# * 'Grant'<~Hash>:
|
21
|
+
# * 'Grantee'<~Hash>:
|
22
|
+
# * 'DisplayName'<~String> - Display name of grantee
|
23
|
+
# * 'ID'<~String> - Id of grantee
|
24
|
+
# * 'Permission'<~String> - Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]
|
25
|
+
#
|
26
|
+
def get_object_torrent(bucket_name, object_name)
|
27
|
+
unless bucket_name
|
28
|
+
raise ArgumentError.new('bucket_name is required')
|
29
|
+
end
|
30
|
+
unless object_name
|
31
|
+
raise ArgumentError.new('object_name is required')
|
32
|
+
end
|
33
|
+
request({
|
34
|
+
:expects => 200,
|
35
|
+
:headers => {},
|
36
|
+
:host => "#{bucket_name}.#{@host}",
|
37
|
+
:idempotent => true,
|
38
|
+
:method => 'GET',
|
39
|
+
:path => CGI.escape(object_name),
|
40
|
+
:query => {'torrent' => nil}
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class Mock
|
47
|
+
|
48
|
+
def get_object_object(bucket_name, object_name)
|
49
|
+
Fog::Mock.not_implemented
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
|
6
|
+
# Get an expiring object url from Google Storage
|
7
|
+
#
|
8
|
+
# ==== Parameters
|
9
|
+
# * bucket_name<~String> - Name of bucket containing object
|
10
|
+
# * object_name<~String> - Name of object to get expiring url for
|
11
|
+
# * expires<~Time> - An expiry time for this url
|
12
|
+
#
|
13
|
+
# ==== Returns
|
14
|
+
# * response<~Excon::Response>:
|
15
|
+
# * body<~String> - url for object
|
16
|
+
#
|
17
|
+
def get_object_url(bucket_name, object_name, expires)
|
18
|
+
unless bucket_name
|
19
|
+
raise ArgumentError.new('bucket_name is required')
|
20
|
+
end
|
21
|
+
unless object_name
|
22
|
+
raise ArgumentError.new('object_name is required')
|
23
|
+
end
|
24
|
+
url({
|
25
|
+
:headers => {},
|
26
|
+
:host => "#{bucket_name}.#{@host}",
|
27
|
+
:method => 'GET',
|
28
|
+
:path => CGI.escape(object_name)
|
29
|
+
}, expires)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class Mock
|
35
|
+
|
36
|
+
def get_object_url(bucket_name, object_name, expires)
|
37
|
+
unless bucket_name
|
38
|
+
raise ArgumentError.new('bucket_name is required')
|
39
|
+
end
|
40
|
+
unless object_name
|
41
|
+
raise ArgumentError.new('object_name is required')
|
42
|
+
end
|
43
|
+
url({
|
44
|
+
:headers => {},
|
45
|
+
:host => "#{bucket_name}.#{@host}",
|
46
|
+
:method => 'GET',
|
47
|
+
:path => CGI.escape(object_name)
|
48
|
+
}, expires)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|