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 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