swift_client 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4555d9e6b744150b80127f8a144e358666a4d70c
4
- data.tar.gz: f6da1e97fa79dc31ee538f5c3fa08981d9e76c06
3
+ metadata.gz: cb7d0291c3fcc0d03fd4aa4711c8c7c4a06b46bf
4
+ data.tar.gz: 8caa6d7f8e4e21ce1567f7d968e6197fd83760f4
5
5
  SHA512:
6
- metadata.gz: 34f5162ea5b2b2fcfa3f5647eaf8c2d31dbf8947678a32cb8f6c0134f299c63a6c1b89b5c85a19c82d660bb0510ac48bbdd25e5247aa41b00a632b99e9d29ec2
7
- data.tar.gz: 570eaee9130d6c3bd43af82dabe763ab8af06b60add3fc577d805ddeb28623889c50de51c1bd28efad0e6edc2f2e04b8dd6461e760a4eb0a6674cb20e92d5b7c
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
 
@@ -0,0 +1,11 @@
1
+
2
+ class SwiftClient::NullCache
3
+ def get(key)
4
+ nil
5
+ end
6
+
7
+ def set(key, value)
8
+ true
9
+ end
10
+ end
11
+
@@ -1,5 +1,5 @@
1
1
 
2
2
  class SwiftClient
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
 
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
- self.auth_token = response.headers["X-Auth-Token"]
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
- self.auth_token = response.parsed_response["access"]["token"]["id"]
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
- self.auth_token = response.headers["X-Subject-Token"]
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)
@@ -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.3
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-03-14 00:00:00.000000000 Z
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