swift_client 0.1.3 → 0.1.4
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/README.md +6 -0
- data/lib/swift_client/null_cache.rb +11 -0
- data/lib/swift_client/version.rb +1 -1
- data/lib/swift_client.rb +51 -7
- data/test/swift_client_test.rb +42 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb7d0291c3fcc0d03fd4aa4711c8c7c4a06b46bf
|
4
|
+
data.tar.gz: 8caa6d7f8e4e21ce1567f7d968e6197fd83760f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88d70e38c7d901e1625c03d12e7a9e016f7d26a3687c1ad3282cc7c29847a3cdfc168ce275453cfd69aff8e27a7ece108c25d2438c3e989beae693d8c17688dd
|
7
|
+
data.tar.gz: eada405a14079e11075ba3a378461c2975da0ef2107609dcf706dca2373da5fde6eea263376873bab01455e38d84d2dd512feacc9a15b84c9395ef55ae0b2bbc
|
data/README.md
CHANGED
@@ -146,6 +146,12 @@ SwiftClient offers the following requests:
|
|
146
146
|
* paginate_objects(container_name, query = {}) -> Enumerator
|
147
147
|
* public_url(object_name, container_name) -> HTTParty::Response
|
148
148
|
* temp_url(object_name, container_name, options = {}) -> HTTParty::Response
|
149
|
+
* bulk_delete(entries) -> entries
|
150
|
+
|
151
|
+
## bulk_delete
|
152
|
+
|
153
|
+
Takes an array containing container_name/object_name entries.
|
154
|
+
Automatically slices and sends 1_000 items per request.
|
149
155
|
|
150
156
|
## Contributing
|
151
157
|
|
data/lib/swift_client/version.rb
CHANGED
data/lib/swift_client.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
require "swift_client/version"
|
3
|
+
require "swift_client/null_cache"
|
3
4
|
|
4
5
|
require "httparty"
|
5
6
|
require "mime-types"
|
@@ -25,12 +26,13 @@ class SwiftClient
|
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
|
-
attr_accessor :options, :auth_token, :storage_url
|
29
|
+
attr_accessor :options, :auth_token, :storage_url, :cache_store
|
29
30
|
|
30
31
|
def initialize(options = {})
|
31
32
|
raise(OptionError, "Setting expires_in connection wide is deprecated") if options[:expires_in]
|
32
33
|
|
33
34
|
self.options = options
|
35
|
+
self.cache_store = options[:cache_store] || SwiftClient::NullCache.new
|
34
36
|
|
35
37
|
authenticate
|
36
38
|
end
|
@@ -158,8 +160,25 @@ class SwiftClient
|
|
158
160
|
"#{storage_url}/#{container_name}/#{object_name}?temp_url_sig=#{signature}&temp_url_expires=#{expires}"
|
159
161
|
end
|
160
162
|
|
163
|
+
def bulk_delete(items)
|
164
|
+
items.each_slice(1_000) do |slice|
|
165
|
+
request :delete, "/?bulk-delete", :body => slice.join("\n"), :headers => { "Content-Type" => "text/plain" }
|
166
|
+
end
|
167
|
+
|
168
|
+
items
|
169
|
+
end
|
170
|
+
|
161
171
|
private
|
162
172
|
|
173
|
+
def cache_key
|
174
|
+
auth_keys = [:auth_url, :username, :access_key, :user_id, :user_domain, :user_domain_id, :domain_name,
|
175
|
+
:domain_id, :token, :project_id, :project_name, :project_domain_name, :project_domain_id, :tenant_name]
|
176
|
+
|
177
|
+
auth_key = auth_keys.collect { |key| options[key] }.inspect
|
178
|
+
|
179
|
+
Digest::SHA1.hexdigest(auth_key)
|
180
|
+
end
|
181
|
+
|
163
182
|
def find_header_key(headers, key)
|
164
183
|
headers.keys.detect { |k| k.downcase == key.downcase }
|
165
184
|
end
|
@@ -187,12 +206,38 @@ class SwiftClient
|
|
187
206
|
end
|
188
207
|
|
189
208
|
def authenticate
|
209
|
+
return if authenticate_from_cache
|
210
|
+
|
190
211
|
return authenticate_v3 if options[:auth_url] =~ /v3/
|
191
212
|
return authenticate_v2 if options[:auth_url] =~ /v2/
|
192
213
|
|
193
214
|
authenticate_v1
|
194
215
|
end
|
195
216
|
|
217
|
+
def authenticate_from_cache
|
218
|
+
cached_auth_token = cache_store.get("swift_client:auth_token:#{cache_key}")
|
219
|
+
cached_storage_url = cache_store.get("swift_client:storage_url:#{cache_key}")
|
220
|
+
|
221
|
+
return false if cached_auth_token.nil? || cached_storage_url.nil?
|
222
|
+
|
223
|
+
if cached_auth_token != auth_token || cached_storage_url != storage_url
|
224
|
+
self.auth_token = cached_auth_token
|
225
|
+
self.storage_url = cached_storage_url
|
226
|
+
|
227
|
+
return true
|
228
|
+
end
|
229
|
+
|
230
|
+
false
|
231
|
+
end
|
232
|
+
|
233
|
+
def set_authentication_details(auth_token, storage_url)
|
234
|
+
cache_store.set("swift_client:auth_token:#{cache_key}", auth_token)
|
235
|
+
cache_store.set("swift_client:storage_url:#{cache_key}", storage_url)
|
236
|
+
|
237
|
+
self.auth_token = auth_token
|
238
|
+
self.storage_url = storage_url
|
239
|
+
end
|
240
|
+
|
196
241
|
def authenticate_v1
|
197
242
|
[:auth_url, :username, :api_key].each do |key|
|
198
243
|
raise(AuthenticationError, "#{key} missing") unless options[key]
|
@@ -202,8 +247,7 @@ class SwiftClient
|
|
202
247
|
|
203
248
|
raise(AuthenticationError, "#{response.code}: #{response.message}") unless response.success?
|
204
249
|
|
205
|
-
|
206
|
-
self.storage_url = options[:storage_url] || response.headers["X-Storage-Url"]
|
250
|
+
set_authentication_details response.headers["X-Auth-Token"], options[:storage_url] || response.headers["X-Storage-Url"]
|
207
251
|
end
|
208
252
|
|
209
253
|
def authenticate_v2
|
@@ -231,8 +275,7 @@ class SwiftClient
|
|
231
275
|
|
232
276
|
raise(AuthenticationError, "#{response.code}: #{response.message}") unless response.success?
|
233
277
|
|
234
|
-
|
235
|
-
self.storage_url = options[:storage_url]
|
278
|
+
set_authentication_details response.parsed_response["access"]["token"]["id"], options[:storage_url]
|
236
279
|
end
|
237
280
|
|
238
281
|
def authenticate_v3
|
@@ -277,10 +320,11 @@ class SwiftClient
|
|
277
320
|
|
278
321
|
raise(AuthenticationError, "#{response.code}: #{response.message}") unless response.success?
|
279
322
|
|
280
|
-
|
281
|
-
self.storage_url = options[:storage_url] || storage_url_from_v3_response(response)
|
323
|
+
storage_url = options[:storage_url] || storage_url_from_v3_response(response)
|
282
324
|
|
283
325
|
raise(AuthenticationError, "storage_url missing") unless storage_url
|
326
|
+
|
327
|
+
set_authentication_details response.headers["X-Subject-Token"], storage_url
|
284
328
|
end
|
285
329
|
|
286
330
|
def storage_url_from_v3_response(response)
|
data/test/swift_client_test.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
|
2
2
|
require File.expand_path("../test_helper", __FILE__)
|
3
3
|
|
4
|
+
class MemoryCache
|
5
|
+
def initialize
|
6
|
+
@cache = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def set(key, value)
|
10
|
+
@cache[key] = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(key)
|
14
|
+
@cache[key]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
4
18
|
class SwiftClientTest < MiniTest::Test
|
5
19
|
def setup
|
6
20
|
stub_request(:get, "https://example.com/auth/v1.0").with(:headers => { "X-Auth-Key" => "secret", "X-Auth-User" => "account:username" }).to_return(:status => 200, :body => "", :headers => { "X-Auth-Token" => "Token", "X-Storage-Url" => "https://example.com/v1/AUTH_account" })
|
@@ -11,6 +25,22 @@ class SwiftClientTest < MiniTest::Test
|
|
11
25
|
assert_equal "https://example.com/v1/AUTH_account", @swift_client.storage_url
|
12
26
|
end
|
13
27
|
|
28
|
+
def test_authenticate_from_cache
|
29
|
+
cache = MemoryCache.new
|
30
|
+
cache.set("swift_client:auth_token:49f42f2927701ba93a5bf9750da8fedfa197fa82", "Cached token")
|
31
|
+
cache.set("swift_client:storage_url:49f42f2927701ba93a5bf9750da8fedfa197fa82", "https://cache.example.com/v1/AUTH_account")
|
32
|
+
|
33
|
+
@swift_client = SwiftClient.new(:auth_url => "https://example.com/auth/v1.0", :username => "account:username", :api_key => "secret", :temp_url_key => "Temp url key", :cache_store => cache)
|
34
|
+
|
35
|
+
assert_equal "Cached token", @swift_client.auth_token
|
36
|
+
assert_equal "https://cache.example.com/v1/AUTH_account", @swift_client.storage_url
|
37
|
+
|
38
|
+
@swift_client.send(:authenticate) # Re-authenticate
|
39
|
+
|
40
|
+
assert_equal "Token", @swift_client.auth_token
|
41
|
+
assert_equal "https://example.com/v1/AUTH_account", @swift_client.storage_url
|
42
|
+
end
|
43
|
+
|
14
44
|
def test_v3_authentication_unscoped_with_password
|
15
45
|
stub_request(:post, "https://auth.example.com/v3/auth/tokens").with(:body => JSON.dump("auth" => { "identity" => { "methods" => ["password"], "password" => { "user" => { "name" => "username", "password" => "secret", "domain" => { "name" => "example.com" }}}}})).to_return(:status => 200, :body => JSON.dump("token" => "..."), :headers => { "X-Subject-Token" => "Token", "Content-Type" => "application/json" })
|
16
46
|
|
@@ -134,6 +164,18 @@ class SwiftClientTest < MiniTest::Test
|
|
134
164
|
assert_equal containers, @swift_client.get_containers.parsed_response
|
135
165
|
end
|
136
166
|
|
167
|
+
def test_bulk_delete
|
168
|
+
objects = [
|
169
|
+
"container1/object1",
|
170
|
+
"container1/object2",
|
171
|
+
"container2/object1"
|
172
|
+
]
|
173
|
+
|
174
|
+
stub_request(:delete, "https://example.com/v1/AUTH_account/?bulk-delete").with(:body => objects.join("\n"), :headers => { "Content-Type" => "text/plain", "X-Auth-Token" => "Token" }).to_return(:status => 200,:body => "", :headers => { "Content-Type" => "application/json" })
|
175
|
+
|
176
|
+
assert @swift_client.bulk_delete(objects)
|
177
|
+
end
|
178
|
+
|
137
179
|
def test_paginate_containers
|
138
180
|
containers = [
|
139
181
|
{ "count" => 1, "bytes" => 1, "name" => "container-1" },
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swift_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Vetter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- README.md
|
123
123
|
- Rakefile
|
124
124
|
- lib/swift_client.rb
|
125
|
+
- lib/swift_client/null_cache.rb
|
125
126
|
- lib/swift_client/version.rb
|
126
127
|
- swift_client.gemspec
|
127
128
|
- test/swift_client_test.rb
|