fog 0.3.1 → 0.3.2

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.
Files changed (49) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.rdoc +1 -0
  3. data/fog.gemspec +44 -1
  4. data/lib/fog.rb +2 -1
  5. data/lib/fog/bin.rb +2 -0
  6. data/lib/fog/google.rb +22 -0
  7. data/lib/fog/google/bin.rb +20 -0
  8. data/lib/fog/google/models/storage/directories.rb +43 -0
  9. data/lib/fog/google/models/storage/directory.rb +48 -0
  10. data/lib/fog/google/models/storage/file.rb +87 -0
  11. data/lib/fog/google/models/storage/files.rb +94 -0
  12. data/lib/fog/google/parsers/storage/access_control_list.rb +46 -0
  13. data/lib/fog/google/parsers/storage/copy_object.rb +22 -0
  14. data/lib/fog/google/parsers/storage/get_bucket.rb +46 -0
  15. data/lib/fog/google/parsers/storage/get_bucket_logging.rb +40 -0
  16. data/lib/fog/google/parsers/storage/get_bucket_object_versions.rb +88 -0
  17. data/lib/fog/google/parsers/storage/get_bucket_versioning.rb +24 -0
  18. data/lib/fog/google/parsers/storage/get_request_payment.rb +20 -0
  19. data/lib/fog/google/parsers/storage/get_service.rb +32 -0
  20. data/lib/fog/google/requests/storage/copy_object.rb +72 -0
  21. data/lib/fog/google/requests/storage/delete_bucket.rb +46 -0
  22. data/lib/fog/google/requests/storage/delete_object.rb +50 -0
  23. data/lib/fog/google/requests/storage/get_bucket.rb +110 -0
  24. data/lib/fog/google/requests/storage/get_bucket_acl.rb +55 -0
  25. data/lib/fog/google/requests/storage/get_object.rb +104 -0
  26. data/lib/fog/google/requests/storage/get_object_acl.rb +66 -0
  27. data/lib/fog/google/requests/storage/get_object_torrent.rb +55 -0
  28. data/lib/fog/google/requests/storage/get_object_url.rb +54 -0
  29. data/lib/fog/google/requests/storage/get_service.rb +53 -0
  30. data/lib/fog/google/requests/storage/head_object.rb +64 -0
  31. data/lib/fog/google/requests/storage/put_bucket.rb +68 -0
  32. data/lib/fog/google/requests/storage/put_bucket_acl.rb +80 -0
  33. data/lib/fog/google/requests/storage/put_object.rb +71 -0
  34. data/lib/fog/google/requests/storage/put_object_url.rb +54 -0
  35. data/lib/fog/google/storage.rb +192 -0
  36. data/spec/google/models/storage/directories_spec.rb +49 -0
  37. data/spec/google/models/storage/directory_spec.rb +83 -0
  38. data/spec/google/models/storage/file_spec.rb +121 -0
  39. data/spec/google/models/storage/files_spec.rb +141 -0
  40. data/spec/google/requests/storage/copy_object_spec.rb +61 -0
  41. data/spec/google/requests/storage/delete_bucket_spec.rb +35 -0
  42. data/spec/google/requests/storage/delete_object_spec.rb +38 -0
  43. data/spec/google/requests/storage/get_bucket_spec.rb +110 -0
  44. data/spec/google/requests/storage/get_object_spec.rb +58 -0
  45. data/spec/google/requests/storage/get_service_spec.rb +32 -0
  46. data/spec/google/requests/storage/head_object_spec.rb +26 -0
  47. data/spec/google/requests/storage/put_bucket_spec.rb +21 -0
  48. data/spec/google/requests/storage/put_object_spec.rb +43 -0
  49. 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