fog-aliyun 0.3.13 → 0.3.19

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +109 -0
  3. data/Gemfile +0 -1
  4. data/fog-aliyun.gemspec +2 -0
  5. data/lib/fog/aliyun/models/storage/directories.rb +30 -53
  6. data/lib/fog/aliyun/models/storage/directory.rb +96 -17
  7. data/lib/fog/aliyun/models/storage/file.rb +127 -125
  8. data/lib/fog/aliyun/models/storage/files.rb +62 -156
  9. data/lib/fog/aliyun/requests/storage/abort_multipart_upload.rb +22 -0
  10. data/lib/fog/aliyun/requests/storage/complete_multipart_upload.rb +21 -0
  11. data/lib/fog/aliyun/requests/storage/copy_object.rb +14 -19
  12. data/lib/fog/aliyun/requests/storage/delete_bucket.rb +3 -10
  13. data/lib/fog/aliyun/requests/storage/delete_multiple_objects.rb +20 -0
  14. data/lib/fog/aliyun/requests/storage/delete_object.rb +10 -11
  15. data/lib/fog/aliyun/requests/storage/get_bucket.rb +26 -125
  16. data/lib/fog/aliyun/requests/storage/get_bucket_location.rb +33 -0
  17. data/lib/fog/aliyun/requests/storage/get_object.rb +29 -11
  18. data/lib/fog/aliyun/requests/storage/get_object_acl.rb +30 -0
  19. data/lib/fog/aliyun/requests/storage/get_object_http_url.rb +8 -11
  20. data/lib/fog/aliyun/requests/storage/get_object_https_url.rb +8 -11
  21. data/lib/fog/aliyun/requests/storage/get_service.rb +13 -0
  22. data/lib/fog/aliyun/requests/storage/head_object.rb +25 -14
  23. data/lib/fog/aliyun/requests/storage/initiate_multipart_upload.rb +19 -0
  24. data/lib/fog/aliyun/requests/storage/list_buckets.rb +6 -24
  25. data/lib/fog/aliyun/requests/storage/list_objects.rb +10 -67
  26. data/lib/fog/aliyun/requests/storage/put_bucket.rb +2 -8
  27. data/lib/fog/aliyun/requests/storage/put_object.rb +16 -142
  28. data/lib/fog/aliyun/requests/storage/upload_part.rb +24 -0
  29. data/lib/fog/aliyun/storage.rb +41 -27
  30. data/lib/fog/aliyun/version.rb +1 -1
  31. metadata +39 -6
  32. data/lib/fog/aliyun/requests/storage/delete_container.rb +0 -31
  33. data/lib/fog/aliyun/requests/storage/get_container.rb +0 -56
  34. data/lib/fog/aliyun/requests/storage/get_containers.rb +0 -65
  35. data/lib/fog/aliyun/requests/storage/put_container.rb +0 -30
@@ -20,71 +20,30 @@ module Fog
20
20
 
21
21
  model Fog::Aliyun::Storage::File
22
22
 
23
- # check_directory_key have two functions:
24
- # 1. trim the directory_key suffix '/'
25
- # 2. checking whether the directory_key is a bucket.
26
- # If so, it will return directly to avoid to create a new redundant folder named with directory_key.
27
- # This point will be applied to multi-bucket and make bucket as a directory scenario.
28
- def check_directory_key(directory_key)
29
- bucket_name = nil
30
- if directory_key.is_a? Array
31
- directory_key = directory_key[0]
32
- end
33
- if directory_key != ''
34
- # trim the suffix '/'
35
- directory_key = directory_key.chomp('/')
36
- # The bucket name can not contain '/', so if directory_key, return directory.
37
- if directory_key.include? '/'
38
- directory_key
39
- else
40
- data = service.get_bucket(directory_key)
41
- if data.class == Hash && data.key?('Code') && !data['Code'].nil? && !data['Code'].empty?
42
- directory_key
43
- else
44
- bucket_name = directory_key
45
- directory_key = ''
46
- end
47
- end
48
- end
49
- return bucket_name, directory_key
50
- end
51
-
52
23
  def all(options = {})
53
24
  requires :directory
54
- bucket_name, directory_key = check_directory_key(directory.key)
55
- remap_attributes(options, {
56
- :delimiter => 'delimiter',
57
- :marker => 'marker',
58
- :max_keys => 'max-keys',
59
- :prefix => 'prefix'
60
- })
61
- prefix_value = options['prefix']
62
- prefix_value = directory_key + '/' + prefix if directory_key != '' && directory_key != '.' && !directory_key.nil?
63
- options['prefix'] = prefix_value
64
- options['bucket'] = bucket_name
65
- files = service.list_objects(options)['Contents']
66
- return if files.nil?
67
- data = []
68
- i = 0
69
- files.each do |file|
70
- next unless file['Key'][0][-1] != '/'
71
- content_length = file['Size'][0].to_i
72
- key = file['Key'][0]
73
- lastModified = file['LastModified'][0]
74
- last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
75
- type = file['Type'][0]
76
- data[i] = { content_length: content_length,
77
- key: key,
78
- last_modified: last_modified,
79
- etag: file['ETag'][0],
80
- object_type: type }
81
- i += 1
25
+ options = {
26
+ 'delimiter': delimiter,
27
+ 'marker': marker,
28
+ 'max-keys': max_keys.to_i,
29
+ 'prefix': prefix
30
+ }.merge!(options)
31
+ options = options.reject {|key,value| value.nil? || value.to_s.empty?}
32
+ merge_attributes(options)
33
+ parent = directory.collection.get(
34
+ directory.key,
35
+ options
36
+ )
37
+ if parent
38
+ merge_attributes(parent.files.attributes)
39
+ load(parent.files.map {|file| file.attributes})
40
+ else
41
+ nil
82
42
  end
83
-
84
- load(data)
85
43
  end
86
44
 
87
- alias each_file_this_page each
45
+ alias_method :each_file_this_page, :each
46
+
88
47
  def each
89
48
  if !block_given?
90
49
  self
@@ -92,7 +51,7 @@ module Fog
92
51
  subset = dup.all
93
52
 
94
53
  subset.each_file_this_page { |f| yield f }
95
- while subset.length == (subset.limit || 10_000)
54
+ while subset.is_truncated
96
55
  subset = subset.all(marker: subset.last.key)
97
56
  subset.each_file_this_page { |f| yield f }
98
57
  end
@@ -101,124 +60,71 @@ module Fog
101
60
  end
102
61
  end
103
62
 
104
- def get(key)
63
+ def get(key, options = {}, &block)
105
64
  requires :directory
106
- bucket_name, directory_key = check_directory_key(directory.key)
107
- object = if directory_key == ''
108
- key
109
- else
110
- directory_key + '/' + key
111
- end
112
65
  begin
113
- data = service.get_object(object, nil, bucket: bucket_name)
114
- lastModified = data['headers'][:last_modified]
115
- last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
116
-
117
- date = data['headers'][:date]
118
- date = (Time.parse(date).localtime if !date.nil? && date != '')
119
- file_data = {
120
- body: data[:body],
121
- content_length: data['headers'][:content_length].to_i,
122
- key: key,
123
- last_modified: last_modified,
124
- content_type: data['headers'][:content_type],
125
- etag: data['headers'][:etag],
126
- date: date,
127
- connection: data['headers'][:connection],
128
- accept_ranges: data['headers'][:accept_ranges],
129
- server: data['headers'][:server],
130
- object_type: data['headers'][:x_oss_object_type]
131
- }
132
-
66
+ data = service.get_object(directory.key, key, options, &block)
67
+ normalize_headers(data)
68
+ file_data = data.headers.merge({
69
+ :body => data.body,
70
+ :key => key
71
+ })
133
72
  new(file_data)
134
- rescue AliyunOssSdk::ServerError => error
135
- case error.error_code
136
- when %r{NoSuchKey},%r{SymlinkTargetNotExist}
137
- nil
138
- else
139
- raise(error)
73
+ rescue Exception => error
74
+ case error.http_code.to_i
75
+ when 404
76
+ nil
77
+ else
78
+ raise(error)
140
79
  end
141
80
  end
142
81
  end
143
82
 
144
- def get_url(key)
83
+ # @param options[Hash] No need to use
84
+ def get_url(key, options = {})
145
85
  requires :directory
146
- bucket_name, directory_key = check_directory_key(directory.key)
147
- object = if directory_key == ''
148
- key
149
- else
150
- directory_key + '/' + key
151
- end
152
- service.get_object_http_url_public(object, 3600, bucket: bucket_name)
86
+ service.get_object_http_url_public(directory.key, key, 3600)
153
87
  end
154
88
 
89
+ # @param options[Hash] No need to use
155
90
  def get_http_url(key, expires, options = {})
156
91
  requires :directory
157
- bucket_name, directory_key = check_directory_key(directory.key)
158
- object = if directory_key == ''
159
- key
160
- else
161
- directory_key + '/' + key
162
- end
163
- expires = expires.nil? ? 0 : expires.to_i
164
- service.get_object_http_url_public(object, expires, options.merge(bucket: bucket_name))
92
+ service.get_object_http_url_public(directory.key, key, expires)
165
93
  end
166
94
 
95
+ # @param options[Hash] No need to use
167
96
  def get_https_url(key, expires, options = {})
168
97
  requires :directory
169
- bucket_name, directory_key = check_directory_key(directory.key)
170
- object = if directory_key == ''
171
- key
172
- else
173
- directory_key + '/' + key
174
- end
175
- expires = expires.nil? ? 0 : expires.to_i
176
- service.get_object_https_url_public(object, expires, options.merge(bucket: bucket_name))
98
+ service.get_object_https_url_public(directory.key, key, expires)
177
99
  end
178
100
 
179
- def head(key, _options = {})
101
+ def head(key, options = {})
180
102
  requires :directory
181
- bucket_name, directory_key = check_directory_key(directory.key)
182
- object = if directory_key == ''
183
- key
184
- else
185
- directory_key + '/' + key
186
- end
187
- data = service.head_object(object, bucket: bucket_name).data
188
- return nil if data[:status] == 404
189
- lastModified = data[:headers]['Last-Modified']
190
- last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
191
-
192
- date = data[:headers]['Date']
193
- date = (Time.parse(date).localtime if !date.nil? && date != '')
194
-
195
- file_data = {
196
- content_length: data[:headers]['Content-Length'].to_i,
197
- key: key,
198
- last_modified: last_modified,
199
- content_type: data[:headers]['Content-Type'],
200
- etag: data[:headers]['ETag'],
201
- date: date,
202
- connection: data[:headers]['Connection'],
203
- accept_ranges: data[:headers]['Accept-Ranges'],
204
- server: data[:headers]['Server'],
205
- object_type: data[:headers]['x-oss-object-type']
206
- }
207
- new(file_data)
208
- rescue Fog::Aliyun::Storage::NotFound
209
- nil
103
+ begin
104
+ data = service.head_object(directory.key, key, options)
105
+ normalize_headers(data)
106
+ file_data = data.headers.merge({
107
+ :key => key
108
+ })
109
+ new(file_data)
110
+ rescue Exception => error
111
+ case error.http_code.to_i
112
+ when 404
113
+ nil
114
+ else
115
+ raise(error)
116
+ end
117
+ end
210
118
  end
211
119
 
212
120
  def new(attributes = {})
213
121
  requires :directory
214
- # Sometimes, the v will be a Array, like "Prefix"=>[{}], "Marker"=>[xxxx], "MaxKeys"=>["100"], "IsTruncated"=>["false"]
215
- # and there needs to parse them
216
- for k, v in attributes
217
- if !v.nil? && (v.is_a? Array) && (v.size > 0)
218
- attributes[k] = v[0]
219
- end
220
- end
221
- super({ directory: directory }.merge!(attributes))
122
+ super({ :directory => directory }.merge!(attributes))
123
+ end
124
+
125
+ def normalize_headers(data)
126
+ data.headers[:last_modified] = Time.parse(data.headers[:last_modified])
127
+ data.headers[:etag] = data.headers[:etag].gsub('"','')
222
128
  end
223
129
  end
224
130
  end
@@ -0,0 +1,22 @@
1
+
2
+ module Fog
3
+ module Aliyun
4
+ class Storage
5
+ class Real
6
+ #
7
+ # Abort a multipart upload
8
+ #
9
+ # @param [String] bucket_name Name of bucket to abort multipart upload on
10
+ # @param [String] object_name Name of object to abort multipart upload on
11
+ # @param [String] upload_id Id of upload to add part to
12
+ #
13
+ # @see https://help.aliyun.com/document_detail/31996.html
14
+ #
15
+ def abort_multipart_upload(bucket_name, object_name, upload_id)
16
+ @oss_protocol.abort_multipart_upload(bucket_name, object_name, upload_id)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Fog
3
+ module Aliyun
4
+ class Storage
5
+ class Real
6
+ # Complete a multipart upload
7
+ #
8
+ # @param [String] bucket_name Name of bucket to complete multipart upload for
9
+ # @param [String] object_name Name of object to complete multipart upload for
10
+ # @param [String] upload_id Id of upload to add part to
11
+ # @param [Array] parts Array of etag and number as Strings for parts
12
+ #
13
+ # @see https://help.aliyun.com/document_detail/31995.html
14
+ #
15
+ def complete_multipart_upload(bucket_name, object_name, upload_id, parts)
16
+ @oss_protocol.complete_multipart_upload(bucket_name, object_name, upload_id, parts)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -7,26 +7,21 @@ module Fog
7
7
  # Copy object
8
8
  #
9
9
  # ==== Parameters
10
- # * source_bucket<~String> - Name of source bucket
11
- # * source_object<~String> - Name of source object
12
- # * target_bucket<~String> - Name of bucket to create copy in
13
- # * target_object<~String> - Name for new copy of object
10
+ # * source_bucket_name<~String> - Name of source bucket
11
+ # * source_object_name<~String> - Name of source object
12
+ # * target_bucket_name<~String> - Name of bucket to create copy in
13
+ # * target_object_name<~String> - Name for new copy of object
14
14
  # * options<~Hash> - Additional headers options={}
15
- def copy_object(source_bucket, source_object, target_bucket, target_object, options = {})
16
- options = options.reject { |_key, value| value.nil? }
17
- bucket = options[:bucket]
18
- bucket ||= @aliyun_oss_bucket
19
- source_bucket ||= bucket
20
- target_bucket ||= bucket
21
- headers = { 'x-oss-copy-source' => "/#{source_bucket}/#{source_object}" }
22
- resource = target_bucket + '/' + target_object
23
- request(expects: [200, 203],
24
- headers: headers,
25
- method: 'PUT',
26
- path: target_object,
27
- bucket: target_bucket,
28
- resource: resource,
29
- location: get_bucket_location(bucket))
15
+ def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {})
16
+ headers = { 'x-oss-copy-source' => "/#{source_bucket_name}#{object_to_path(source_object_name)}" }.merge!(options)
17
+ resources = {
18
+ :bucket => target_bucket_name,
19
+ :object => target_object_name
20
+ }
21
+ http_options = {
22
+ :headers => headers
23
+ }
24
+ @oss_http.put(resources, http_options)
30
25
  end
31
26
  end
32
27
  end
@@ -7,17 +7,10 @@ module Fog
7
7
  # Delete an existing bucket
8
8
  #
9
9
  # ==== Parameters
10
- # * bucket<~String> - Name of bucket to delete
10
+ # * bucket_name<~String> - Name of bucket to delete
11
11
  #
12
- def delete_bucket(bucket)
13
- resource = bucket + '/'
14
- request(
15
- expects: 204,
16
- method: 'DELETE',
17
- bucket: bucket,
18
- resource: resource,
19
- location: get_bucket_location(bucket)
20
- )
12
+ def delete_bucket(bucket_name)
13
+ @oss_protocol.delete_bucket(bucket_name)
21
14
  end
22
15
  end
23
16
  end
@@ -0,0 +1,20 @@
1
+ module Fog
2
+ module Aliyun
3
+ class Storage
4
+ class Real
5
+
6
+ # Delete multiple objects from OSS
7
+ #
8
+ # @param bucket_name [String] Name of bucket containing object to delete
9
+ # @param object_names [Array] Array of object names to delete
10
+ #
11
+ # @see https://help.aliyun.com/document_detail/31983.html
12
+
13
+ def delete_multiple_objects(bucket_name, object_names, options = {})
14
+ bucket = @oss_client.get_bucket(bucket_name)
15
+ bucket.batch_delete_objects(object_names, options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -7,18 +7,17 @@ module Fog
7
7
  # Delete an existing object
8
8
  #
9
9
  # ==== Parameters
10
- # * object<~String> - Name of object to delete
10
+ # * bucket_name<~String> - Name of bucket to delete
11
+ # * object_name<~String> - Name of object to delete
11
12
  #
12
- def delete_object(object, options = {})
13
- bucket_name = options[:bucket]
14
- bucket_name ||= @aliyun_oss_bucket
15
- bucket = @oss_client.get_bucket(bucket_name)
16
- bucket.delete_object(object)
17
- end
18
-
19
- def abort_multipart_upload(bucket_name, object, upload_id)
20
- bucket = @oss_client.get_bucket(bucket_name)
21
- bucket.abort_upload(upload_id, object)
13
+ def delete_object(bucket_name, object_name, options = {})
14
+ # TODO Support versionId
15
+ # if version_id = options.delete('versionId')
16
+ # query = {'versionId' => version_id}
17
+ # else
18
+ # query = {}
19
+ # end
20
+ @oss_http.delete({:bucket => bucket_name, :object => object_name}, {:headers => options})
22
21
  end
23
22
  end
24
23
  end
@@ -4,147 +4,48 @@ module Fog
4
4
  module Aliyun
5
5
  class Storage
6
6
  class Real
7
- def get_bucket(bucket, options = {})
8
- prefix = options['prefix']
9
- marker = options['marker']
10
- # Set the GetBucket max limitation to 1000
11
- maxKeys = options['max-keys'] || 1000
12
- maxKeys = [maxKeys, 1000].min
13
- delimiter = options['delimiter']
14
- path = ''
15
- if prefix
16
- path += '/?prefix=' + prefix
17
- path += '&marker=' + marker if marker
18
- path += '&max-keys=' + maxKeys.to_s if maxKeys
19
- path += '&delimiter=' + delimiter if delimiter
20
-
21
- elsif marker
22
- path += '/?marker=' + marker
23
- path += '&max-keys=' + maxKeys.to_s if maxKeys
24
- path += '&delimiter=' + delimiter if delimiter
7
+ def bucket_exists?(bucket_name)
8
+ @oss_client.bucket_exists?(bucket_name)
9
+ end
25
10
 
26
- elsif maxKeys
27
- path += '/?max-keys=' + maxKeys.to_s
28
- path += '&delimiter=' + delimiter if delimiter
29
- elsif delimiter
30
- path += '/?delimiter=' + delimiter
11
+ def get_bucket(bucket_name, options = {})
12
+ unless bucket_name
13
+ raise ArgumentError.new('bucket_name is required')
31
14
  end
32
15
 
33
- resource = bucket + '/'
34
- ret = request(
35
- expects: [200, 203, 404],
36
- method: 'GET',
37
- bucket: bucket,
38
- resource: resource,
39
- location: get_bucket_location(bucket),
40
- path: path
41
- )
42
- xml = ret.data[:body]
43
- XmlSimple.xml_in(xml)
44
- end
16
+ # Set the GetBucket max limitation to 1000
17
+ maxKeys = options[:max_keys] || 1000
18
+ maxKeys = maxKeys.to_i
19
+ maxKeys = [maxKeys, 1000].min
45
20
 
46
- def get_bucket_location(bucket)
47
- attribute = '?location'
48
- resource = bucket + '/' + attribute
49
- ret = request(
50
- expects: [200, 203, 403, 404],
51
- method: 'GET',
52
- path: attribute,
53
- bucket: bucket,
54
- resource: resource
55
- )
56
- # If there is an error, it will return a Hash with error code, host id and others
57
- # If can not get a valid location, will return one using region
58
- location = XmlSimple.xml_in(ret.data[:body])
59
- if location.class == Hash && location.key?('HostId')
60
- value = location['HostId']
61
- location = value[0].split('.')[1]
62
- end
63
- location ||= 'oss-' + @aliyun_region_id
21
+ options[:limit] = maxKeys
22
+ options.delete(:max_keys)
23
+
24
+ @oss_protocol.list_objects(bucket_name, options)
64
25
  end
65
26
 
66
- def get_bucket_acl(bucket)
67
- attribute = '?acl'
68
- resource = bucket + '/' + attribute
69
- ret = request(
70
- expects: [200, 203],
71
- method: 'GET',
72
- path: attribute,
73
- bucket: bucket,
74
- resource: resource,
75
- location: get_bucket_location(bucket)
76
- )
77
- XmlSimple.xml_in(ret.data[:body])['AccessControlList'][0]['Grant'][0]
27
+ def get_bucket_acl(bucket_name)
28
+ @oss_protocol.get_bucket_acl(bucket_name)
78
29
  end
79
30
 
80
- def get_bucket_CORSRules(bucket)
81
- attribute = '?cors'
82
- resource = bucket + '/' + attribute
83
- ret = request(
84
- expects: [200, 203, 404],
85
- method: 'GET',
86
- path: attribute,
87
- bucket: bucket,
88
- resource: resource,
89
- location: get_bucket_location(bucket)
90
- )
91
- XmlSimple.xml_in(ret.data[:body])['CORSRule'][0] if ret.data[:status] != 404
31
+ def get_bucket_CORSRules(bucket_name)
32
+ @oss_protocol.get_bucket_cors(bucket_name)
92
33
  end
93
34
 
94
- def get_bucket_lifecycle(bucket)
95
- attribute = '?lifecycle'
96
- resource = bucket + '/' + attribute
97
- ret = request(
98
- expects: [200, 203, 404],
99
- method: 'GET',
100
- path: attribute,
101
- bucket: bucket,
102
- resource: resource,
103
- location: get_bucket_location(bucket)
104
- )
105
- XmlSimple.xml_in(ret.data[:body])['Rule'][0] if ret.data[:status] != 404
35
+ def get_bucket_lifecycle(bucket_name)
36
+ @oss_protocol.get_bucket_lifecycle(bucket_name)
106
37
  end
107
38
 
108
- def get_bucket_logging(bucket)
109
- attribute = '?logging'
110
- resource = bucket + '/' + attribute
111
- ret = request(
112
- expects: [200, 203],
113
- method: 'GET',
114
- path: attribute,
115
- bucket: bucket,
116
- resource: resource,
117
- location: get_bucket_location(bucket)
118
- )
119
- XmlSimple.xml_in(ret.data[:body])['LoggingEnabled'][0]['TargetPrefix']
39
+ def get_bucket_logging(bucket_name)
40
+ @oss_protocol.get_bucket_logging(bucket_name)
120
41
  end
121
42
 
122
- def get_bucket_referer(bucket)
123
- attribute = '?referer'
124
- resource = bucket + '/' + attribute
125
- ret = request(
126
- expects: [200, 203],
127
- method: 'GET',
128
- path: attribute,
129
- bucket: bucket,
130
- resource: resource,
131
- location: get_bucket_location(bucket)
132
- )
133
- XmlSimple.xml_in(ret.data[:body])
43
+ def get_bucket_referer(bucket_name)
44
+ @oss_protocol.get_bucket_referer(bucket_name)
134
45
  end
135
46
 
136
- def get_bucket_website(bucket)
137
- attribute = '?website'
138
- resource = bucket + '/' + attribute
139
- ret = request(
140
- expects: [200, 203, 404],
141
- method: 'GET',
142
- path: attribute,
143
- bucket: bucket,
144
- resource: resource,
145
- location: get_bucket_location(bucket)
146
- )
147
- XmlSimple.xml_in(ret.data[:body]) if ret.data[:status] != 404
47
+ def get_bucket_website(bucket_name)
48
+ @oss_protocol.get_bucket_website(bucket_name)
148
49
  end
149
50
  end
150
51
  end