keystok 1.0.0
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 +7 -0
- data/.gitignore +20 -0
- data/.rspec +4 -0
- data/.rubocop.yml +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +1 -0
- data/README.md +74 -0
- data/Rakefile +8 -0
- data/keystok.gemspec +34 -0
- data/lib/generators/keystok/install_generator.rb +25 -0
- data/lib/generators/keystok/templates/keystok.rb +6 -0
- data/lib/generators/keystok/templates/keystok.yml.erb +10 -0
- data/lib/keystok/aes_crypto.rb +49 -0
- data/lib/keystok/cache.rb +40 -0
- data/lib/keystok/client.rb +198 -0
- data/lib/keystok/errors.rb +20 -0
- data/lib/keystok/railtie.rb +13 -0
- data/lib/keystok/version.rb +9 -0
- data/lib/keystok.rb +26 -0
- data/spec/fixtures/encrypted_data_00.data +1 -0
- data/spec/fixtures/response_data_00.data +8 -0
- data/spec/functional/aes_crypto_spec.rb +90 -0
- data/spec/functional/cache_spec.rb +119 -0
- data/spec/functional/client_spec.rb +605 -0
- data/spec/functional/keystok_spec.rb +33 -0
- data/spec/integration/rails_integration_spec.rb +82 -0
- data/spec/spec_helper.rb +17 -0
- metadata +233 -0
@@ -0,0 +1,605 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under GitDock Oy license terms.
|
3
|
+
# See https://bitbucket.org/keystok/keystok-client-ruby/raw/master/LICENSE.txt
|
4
|
+
# for details.
|
5
|
+
|
6
|
+
require 'spec_helper'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
describe Keystok::Client do
|
10
|
+
DECRYPTION_KEY =
|
11
|
+
'965391f2bba37b4586431b8690d7044d5cdc73adf7dda539f8dd3a60cb3e9b12'
|
12
|
+
API_HOST = 'https://api.keystok.com'
|
13
|
+
|
14
|
+
def request_url(host = nil, path = nil)
|
15
|
+
host ||= config[:api_host]
|
16
|
+
path ||= request_path
|
17
|
+
"#{host}/#{path}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def override_config_key(key, value = nil)
|
21
|
+
config_tmp = client.instance_variable_get('@config')
|
22
|
+
config_tmp[key] = value
|
23
|
+
client.instance_variable_set('@config', config_tmp)
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_path(key = nil)
|
27
|
+
if key
|
28
|
+
key_path = "/#{key}"
|
29
|
+
else
|
30
|
+
key_path = ''
|
31
|
+
end
|
32
|
+
"apps/#{config[:id]}/deploy#{key_path}?access_token=#{refreshed_token}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def stub_deployment_req(host = nil, path = nil)
|
36
|
+
stub_request(:get, request_url(host, path))
|
37
|
+
.to_return(status: 200, body: example_response, headers: {})
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:config) do
|
41
|
+
{ api_host: 'https://api.keystok-host.com',
|
42
|
+
auth_host: 'https://keystok-host.com',
|
43
|
+
rt: 'token',
|
44
|
+
dk: DECRYPTION_KEY,
|
45
|
+
id: 1,
|
46
|
+
tmp_dir: tmp_dir }
|
47
|
+
end
|
48
|
+
let(:client) { Keystok::Client.new(config) }
|
49
|
+
let(:example_response) do
|
50
|
+
File.open(File.expand_path('../../fixtures/response_data_00.data',
|
51
|
+
__FILE__)).read
|
52
|
+
end
|
53
|
+
let(:keystok_oauth_refresh_url) { 'https://keystok.com/oauth/token' }
|
54
|
+
let(:oauth_refresh_url) { "#{config[:auth_host]}/oauth/token" }
|
55
|
+
let(:refresh_response) do
|
56
|
+
{
|
57
|
+
'access_token' => refreshed_token,
|
58
|
+
'token_type' => 'bearer', 'expires_in' => 124
|
59
|
+
}.to_json
|
60
|
+
end
|
61
|
+
let(:refreshed_token) do
|
62
|
+
'2cb4583cd8a399f51db15da57d0679706ae975d2aa9d3c71f5fdd0255dd6a028'
|
63
|
+
end
|
64
|
+
let(:tmp_dir) { File.expand_path('../../../tmp', __FILE__) }
|
65
|
+
let(:tmp_filepath) { File.join(tmp_dir, 'keystok_cache.data') }
|
66
|
+
|
67
|
+
before do
|
68
|
+
Keystok.logger = Logger.new(nil)
|
69
|
+
# config based url's
|
70
|
+
stub_deployment_req(config[:api_host], request_path)
|
71
|
+
stub_request(:post, oauth_refresh_url)
|
72
|
+
.to_return(status: 200, body: refresh_response,
|
73
|
+
headers: { 'Content-Type' => 'application/json' })
|
74
|
+
# Keystok URL's
|
75
|
+
stub_deployment_req(API_HOST, request_path)
|
76
|
+
stub_request(:post, keystok_oauth_refresh_url)
|
77
|
+
.to_return(status: 200, body: refresh_response,
|
78
|
+
headers: { 'Content-Type' => 'application/json' })
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'allow initialization with empty config' do
|
82
|
+
Keystok::Client.new
|
83
|
+
Keystok::Client.new('')
|
84
|
+
Keystok::Client.new(connection_string: '', tmp_dir: 'tmp')
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'default for' do
|
88
|
+
it "'eager_fetching' if true" do
|
89
|
+
expect(client.instance_variable_get('@config')[:eager_fetching])
|
90
|
+
.to be_true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'access_token' do
|
95
|
+
it 'perform request to auth_host' do
|
96
|
+
client.send(:access_token)
|
97
|
+
a_request(:post, oauth_refresh_url).should have_been_made.once
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'respond with new token' do
|
101
|
+
token = client.send(:access_token)
|
102
|
+
expect(token.class).to eq(OAuth2::AccessToken)
|
103
|
+
expect(token.token.length).to be > 0
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'cached the token' do
|
107
|
+
token_1 = client.send(:access_token)
|
108
|
+
token_2 = client.send(:access_token)
|
109
|
+
expect(token_2).to equal(token_1)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'raise ConfigError when refresh token is nil' do
|
113
|
+
override_config_key(:rt, nil)
|
114
|
+
expect do
|
115
|
+
client.send(:access_token)
|
116
|
+
end.to raise_error(Keystok::Error::ConfigError, 'SDK not configured')
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'connection fail' do
|
120
|
+
context 'Faraday exception' do
|
121
|
+
it 'tries REQUEST_TRY_COUNT times before giving-up' do
|
122
|
+
stub_request(:post, oauth_refresh_url)
|
123
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
124
|
+
begin
|
125
|
+
client.send(:access_token)
|
126
|
+
# rubocop:disable HandleExceptions
|
127
|
+
rescue Faraday::Error::ConnectionFailed
|
128
|
+
# rubocop:enable HandleExceptions
|
129
|
+
# Nothing here becouse we just want to check requests count
|
130
|
+
end
|
131
|
+
a_request(:post, oauth_refresh_url).should have_been_made
|
132
|
+
.times(Keystok::Client::REQUEST_TRY_COUNT)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'is re-raising Faraday exception after 3 attempts' do
|
136
|
+
stub_request(:post, oauth_refresh_url)
|
137
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
138
|
+
expect do
|
139
|
+
client.send(:access_token)
|
140
|
+
end.to raise_error(Faraday::Error::ConnectionFailed)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should log warning on every Faraday exception' do
|
144
|
+
stub_request(:post, oauth_refresh_url)
|
145
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
146
|
+
logger = double(:logger)
|
147
|
+
Keystok.logger = logger
|
148
|
+
expect(logger).to receive(:warn).exactly(3).times
|
149
|
+
.with('Exception during token refresh: ' \
|
150
|
+
'Exception from WebMock')
|
151
|
+
begin
|
152
|
+
client.send(:access_token)
|
153
|
+
# rubocop:disable HandleExceptions
|
154
|
+
rescue Faraday::Error::ConnectionFailed
|
155
|
+
# rubocop:enable HandleExceptions
|
156
|
+
# Nothing here becouse we just want to check requests count
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'configured?' do
|
164
|
+
conf_keys = %w(rt dk id).map(&:to_sym)
|
165
|
+
conf_keys.each do |config_key|
|
166
|
+
it "return false when '#{config_key}' entry is missing" do
|
167
|
+
override_config_key(config_key)
|
168
|
+
expect(client.send(:configured?)).to be_false
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'return true when all required keys are set' do
|
173
|
+
expect(client.send(:configured?)).to be_true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'get' do
|
178
|
+
it 'respond with proper value' do
|
179
|
+
expect(client.get('key_1')).to eq('Value 1')
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'accept symbols' do
|
183
|
+
expect(client.get(:key_1)).to eq('Value 1')
|
184
|
+
end
|
185
|
+
|
186
|
+
it "don't trigger API request when key is in keys store" do
|
187
|
+
2.times { client.get('key_1') }
|
188
|
+
a_request(:get, request_url).should have_been_made.once
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'triggers API request when key is not in keys store' do
|
192
|
+
client.get('key_1')
|
193
|
+
a_request(:get, request_url).should have_been_made.once
|
194
|
+
end
|
195
|
+
|
196
|
+
it "don't trigger API request when key is in keys store" do
|
197
|
+
2.times.each { client.get('key_1') }
|
198
|
+
a_request(:get, request_url).should have_been_made.once
|
199
|
+
end
|
200
|
+
|
201
|
+
it "triggers API request when 'force_reload' is true" do
|
202
|
+
2.times.each { client.get('key_1', true) }
|
203
|
+
a_request(:get, request_url).should have_been_made.times(2)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "triggers API request when 'volatile' is set in config" do
|
207
|
+
override_config_key(:volatile, true)
|
208
|
+
2.times.each { client.get('key_1') }
|
209
|
+
a_request(:get, request_url).should have_been_made.times(2)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "triggers request to 'https://api.keystok.com' when api_host is nil" do
|
213
|
+
override_config_key(:api_host)
|
214
|
+
client.get('key_1')
|
215
|
+
a_request(:get, request_url(API_HOST))
|
216
|
+
.should have_been_made.once
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe 'keys' do
|
221
|
+
before do
|
222
|
+
stub_request(:get, request_url)
|
223
|
+
.to_return(status: 200, body: example_response, headers: {})
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'respond with proper values' do
|
227
|
+
expect(client.keys).to eq('key_1' => 'Value 1', 'key_2' => 'Value 2')
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'triggers API request when keys store is empty' do
|
231
|
+
client.keys
|
232
|
+
a_request(:get, request_url).should have_been_made.once
|
233
|
+
end
|
234
|
+
|
235
|
+
it "don't trigger API request when keys store is not empty" do
|
236
|
+
2.times { client.keys }
|
237
|
+
a_request(:get, request_url).should have_been_made.once
|
238
|
+
end
|
239
|
+
|
240
|
+
it "don't trigger API request when keys store is not empty" do
|
241
|
+
2.times.each { client.keys }
|
242
|
+
a_request(:get, request_url).should have_been_made.once
|
243
|
+
end
|
244
|
+
|
245
|
+
it "triggers API request when 'force_reload' is true" do
|
246
|
+
2.times.each { client.keys(true) }
|
247
|
+
a_request(:get, request_url).should have_been_made.times(2)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "triggers API request when 'volatile' is set in config" do
|
251
|
+
override_config_key(:volatile, true)
|
252
|
+
2.times.each { client.keys(true) }
|
253
|
+
a_request(:get, request_url).should have_been_made.times(2)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe 'check_config' do
|
258
|
+
conf_keys = %w(rt dk id).map(&:to_sym)
|
259
|
+
conf_keys.each do |config_key|
|
260
|
+
it "raise ConfigError when '#{config_key}' entry is missing" do
|
261
|
+
override_config_key(config_key)
|
262
|
+
expect do
|
263
|
+
client.send(:check_config)
|
264
|
+
end.to raise_error(Keystok::Error::ConfigError,
|
265
|
+
"Config key: #{config_key} is missing!")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe 'connection' do
|
271
|
+
it 'initialize Faraday instance' do
|
272
|
+
connection = client.send(:connection)
|
273
|
+
expect(connection.url_prefix.to_s).to eq("#{config[:api_host]}/")
|
274
|
+
end
|
275
|
+
|
276
|
+
it "is using 'https://api.keystok.com' when api_host is nil" do
|
277
|
+
override_config_key(:api_host)
|
278
|
+
connection = client.send(:connection)
|
279
|
+
expect(connection.url_prefix.to_s).to eq('https://api.keystok.com/')
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'SSL verification is enabled' do
|
283
|
+
connection = client.send(:connection)
|
284
|
+
expect(connection.ssl.verify?).to eq(true)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'caches the instance' do
|
288
|
+
connection_1 = client.send(:connection)
|
289
|
+
connection_2 = client.send(:connection)
|
290
|
+
expect(connection_2).to equal(connection_1)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context 'config parsing' do
|
295
|
+
let(:config_hash) { { 'api_host' => 'http://dum.my', 'some_data' => 2 } }
|
296
|
+
describe 'decode_config' do
|
297
|
+
it "returns input if it's a hash" do
|
298
|
+
expect(client.send(:decode_config, config_hash)).to eq(config_hash)
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'decodes connection string and merges it to the config hash' do
|
302
|
+
config_with_connection_string = {
|
303
|
+
connection_string: Base64.urlsafe_encode64(config_hash.to_json)
|
304
|
+
}
|
305
|
+
expect(client.send(:decode_config,
|
306
|
+
config_with_connection_string)).to eq(config_hash)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "raise ConfigError when connection string can't be decoded" do
|
310
|
+
config_with_connection_string = {
|
311
|
+
connection_string: Base64.urlsafe_encode64(config_hash.to_json)
|
312
|
+
}
|
313
|
+
expect(client.send(:decode_config,
|
314
|
+
config_with_connection_string)).to eq(config_hash)
|
315
|
+
end
|
316
|
+
|
317
|
+
it "returns hash if it's a JSON string" do
|
318
|
+
expect(client.send(:decode_config,
|
319
|
+
config_hash.to_json)).to eq(config_hash)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "returns hash if it's a base64 encoded JSON string" do
|
323
|
+
encoded_hash = Base64.urlsafe_encode64(config_hash.to_json)
|
324
|
+
expect(client.send(:decode_config,
|
325
|
+
encoded_hash.to_json)).to eq(config_hash)
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'raise ConfigError exception on unknown input type' do
|
329
|
+
expect do
|
330
|
+
client.send(:decode_config, [:some, :array])
|
331
|
+
end.to raise_error(Keystok::Error::ConfigError,
|
332
|
+
'Unknown config format')
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe 'decode_json_string_config' do
|
337
|
+
it 'respond with hash on JSON string' do
|
338
|
+
expect(client.send(:decode_json_string_config,
|
339
|
+
config_hash.to_json)).to eq(config_hash)
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'responds with nil when parsing JSON is failing' do
|
343
|
+
expect(client.send(:decode_json_string_config,
|
344
|
+
'not_valid_json')).to eq(nil)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe 'decode_string_config' do
|
349
|
+
it "returns hash if it's a JSON string" do
|
350
|
+
expect(client.send(:decode_string_config,
|
351
|
+
config_hash.to_json)).to eq(config_hash)
|
352
|
+
end
|
353
|
+
|
354
|
+
it "returns hash if it's a base64 encoded JSON string" do
|
355
|
+
encoded_hash = Base64.urlsafe_encode64(config_hash.to_json)
|
356
|
+
expect(client.send(:decode_string_config,
|
357
|
+
encoded_hash.to_json)).to eq(config_hash)
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'raise ConfigError exception on unknown input type' do
|
361
|
+
expect do
|
362
|
+
client.send(:decode_string_config, 'not_valid_json')
|
363
|
+
end.to raise_error(Keystok::Error::ConfigError,
|
364
|
+
'Unknown config format')
|
365
|
+
end
|
366
|
+
|
367
|
+
it 'accepts empty string' do
|
368
|
+
expect(client.send(:decode_string_config, '')).to eq({})
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe 'fetch_data' do
|
374
|
+
context 'connection success' do
|
375
|
+
before do
|
376
|
+
stub_request(:get, request_url)
|
377
|
+
.to_return(status: 200, body: example_response, headers: {})
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'is making request to proper url' do
|
381
|
+
client.send(:fetch_data)
|
382
|
+
a_request(:get, request_url).should have_been_made.once
|
383
|
+
end
|
384
|
+
|
385
|
+
context 'is making request to proper url when key is not nil' do
|
386
|
+
it 'and @config[:eager_fetching] is true' do
|
387
|
+
client.send(:fetch_data, :some_key)
|
388
|
+
a_request(:get, request_url).should have_been_made.once
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'and @config[:eager_fetching] is false' do
|
392
|
+
override_config_key(:eager_fetching, false)
|
393
|
+
stub_deployment_req(config[:api_host], request_path(:some_key))
|
394
|
+
client.send(:fetch_data, :some_key)
|
395
|
+
a_request(:get, request_url(config[:api_host],
|
396
|
+
request_path(:some_key)))
|
397
|
+
.should have_been_made.once
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'is returning response data' do
|
402
|
+
expect(client.send(:fetch_data).body).to eq(example_response)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context 'connection fail' do
|
407
|
+
context 'non 200 response status' do
|
408
|
+
before do
|
409
|
+
stub_request(:get, request_url)
|
410
|
+
.to_return(status: 400, body: 'fail', headers: {})
|
411
|
+
end
|
412
|
+
|
413
|
+
it 'tries REQUEST_TRY_COUNT times before giving-up' do
|
414
|
+
client.send(:fetch_data)
|
415
|
+
a_request(:get, request_url).should have_been_made
|
416
|
+
.times(Keystok::Client::REQUEST_TRY_COUNT)
|
417
|
+
end
|
418
|
+
|
419
|
+
it 'is returning non-200 response after 3 attempts' do
|
420
|
+
expect(client.send(:fetch_data).status).to eq(400)
|
421
|
+
end
|
422
|
+
|
423
|
+
it 'should log warning on every non-200 response' do
|
424
|
+
logger = double(:logger)
|
425
|
+
Keystok.logger = logger
|
426
|
+
expect(logger).to receive(:warn).exactly(3).times
|
427
|
+
.with('Keystok API response status: 400')
|
428
|
+
client.send(:fetch_data)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
context 'Faraday exception' do
|
433
|
+
it 'tries REQUEST_TRY_COUNT times before giving-up' do
|
434
|
+
stub_request(:get, request_url)
|
435
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
436
|
+
begin
|
437
|
+
client.send(:fetch_data)
|
438
|
+
# rubocop:disable HandleExceptions
|
439
|
+
rescue Faraday::Error::ConnectionFailed
|
440
|
+
# rubocop:enable HandleExceptions
|
441
|
+
# Nothing here becouse we just want to check requests count
|
442
|
+
end
|
443
|
+
a_request(:get, request_url).should have_been_made
|
444
|
+
.times(Keystok::Client::REQUEST_TRY_COUNT)
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'is re-raising Faraday exception after 3 attempts' do
|
448
|
+
stub_request(:get, request_url)
|
449
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
450
|
+
expect do
|
451
|
+
client.send(:fetch_data)
|
452
|
+
end.to raise_error(Faraday::Error::ConnectionFailed)
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'should log warning on every Faraday exception' do
|
456
|
+
stub_request(:get, request_url)
|
457
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
458
|
+
logger = double(:logger)
|
459
|
+
Keystok.logger = logger
|
460
|
+
expect(logger).to receive(:warn).exactly(3).times
|
461
|
+
.with('Exception during Keystok API data fetch: ' \
|
462
|
+
'Exception from WebMock')
|
463
|
+
begin
|
464
|
+
client.send(:fetch_data)
|
465
|
+
# rubocop:disable HandleExceptions
|
466
|
+
rescue Faraday::Error::ConnectionFailed
|
467
|
+
# rubocop:enable HandleExceptions
|
468
|
+
# Nothing here becouse we just want to check requests count
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
describe 'keys_to_symbols' do
|
476
|
+
it 'convert string hash keys to symbols' do
|
477
|
+
expect(client.send(:keys_to_symbols, 'key_1' => 1, 'key_2' => 2))
|
478
|
+
.to eq(key_1: 1, key_2: 2)
|
479
|
+
end
|
480
|
+
|
481
|
+
it 'leave non-string hash keys untouched' do
|
482
|
+
expect(client.send(:keys_to_symbols, :key_1 => 1, 2 => 2, [3] => 3))
|
483
|
+
.to eq(key_1: 1, 2 => 2, [3] => 3)
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
describe 'load_keys' do
|
488
|
+
before do
|
489
|
+
FileUtils.rm_f(tmp_filepath)
|
490
|
+
end
|
491
|
+
|
492
|
+
after do
|
493
|
+
FileUtils.rm_f(tmp_filepath)
|
494
|
+
end
|
495
|
+
|
496
|
+
context 'connection success' do
|
497
|
+
before do
|
498
|
+
stub_request(:get, request_url)
|
499
|
+
.to_return(status: 200, body: example_response, headers: {})
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'is triggering @keys_store setting' do
|
503
|
+
client.send(:load_keys)
|
504
|
+
expect(client.instance_variable_get('@keys_store'))
|
505
|
+
.to eq('key_1' => 'Value 1', 'key_2' => 'Value 2')
|
506
|
+
end
|
507
|
+
|
508
|
+
it 'is returning loaded keys' do
|
509
|
+
expect(client.send(:load_keys)).to eq('key_1' => 'Value 1',
|
510
|
+
'key_2' => 'Value 2')
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'is writing data to cache' do
|
514
|
+
expect(File.size?(tmp_filepath).to_i).to eq(0)
|
515
|
+
client.send(:load_keys)
|
516
|
+
expect(File.size?(tmp_filepath).to_i).to_not eq(0)
|
517
|
+
end
|
518
|
+
|
519
|
+
it 'is not writing data to cache when no_cache is set in config' do
|
520
|
+
override_config_key(:no_cache, true)
|
521
|
+
expect(File.size?(tmp_filepath).to_i).to eq(0)
|
522
|
+
client.send(:load_keys)
|
523
|
+
expect(File.size?(tmp_filepath).to_i).to eq(0)
|
524
|
+
end
|
525
|
+
|
526
|
+
it 'is discarding old keys' do
|
527
|
+
client.instance_variable_set('@keys_store', 'old' => 'value')
|
528
|
+
expect(client.send(:load_keys)).to eq('key_1' => 'Value 1',
|
529
|
+
'key_2' => 'Value 2')
|
530
|
+
end
|
531
|
+
|
532
|
+
it "when called with key name it passes key to 'fetch' method" do
|
533
|
+
stub_deployment_req(config[:api_host], request_path(:some_key))
|
534
|
+
override_config_key(:eager_fetching, false)
|
535
|
+
expect(client).to receive(:fetch_data).with(:some_key)
|
536
|
+
.and_call_original
|
537
|
+
client.send(:load_keys, :some_key)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
context 'connection fail' do
|
542
|
+
it 'is raising ConnectionError on no cache and response != 200' do
|
543
|
+
stub_request(:get, request_url)
|
544
|
+
.to_return(status: 400, body: 'fail', headers: {})
|
545
|
+
expect do
|
546
|
+
client.send(:load_keys)
|
547
|
+
end.to raise_error(Keystok::Error::ConnectionError,
|
548
|
+
"No cache data and response code:\n" \
|
549
|
+
'400 with body: fail')
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'is raising ConnectionError on no cache and Faraday exception' do
|
553
|
+
stub_request(:get, request_url)
|
554
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
555
|
+
expect do
|
556
|
+
client.send(:load_keys)
|
557
|
+
end.to raise_error(Keystok::Error::ConnectionError,
|
558
|
+
/No cache data and connection error:.*/)
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
context 'load from cache' do
|
563
|
+
it 'loads cached data on response != 200' do
|
564
|
+
stub_request(:get, request_url)
|
565
|
+
.to_return(status: 200, body: example_response, headers: {})
|
566
|
+
client.send(:load_keys)
|
567
|
+
stub_request(:get, request_url)
|
568
|
+
.to_return(status: 400, body: 'fail', headers: {})
|
569
|
+
expect(client.send(:load_keys)).to eq('key_1' => 'Value 1',
|
570
|
+
'key_2' => 'Value 2')
|
571
|
+
end
|
572
|
+
|
573
|
+
it 'loads cached data on Faraday exception' do
|
574
|
+
stub_request(:get, request_url)
|
575
|
+
.to_return(status: 200, body: example_response, headers: {})
|
576
|
+
client.send(:load_keys)
|
577
|
+
stub_request(:get, request_url)
|
578
|
+
.to_raise(Faraday::Error::ConnectionFailed)
|
579
|
+
expect(client.send(:load_keys)).to eq('key_1' => 'Value 1',
|
580
|
+
'key_2' => 'Value 2')
|
581
|
+
end
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
describe 'oauth_client' do
|
586
|
+
it 'initialize oauth client' do
|
587
|
+
oauth_client = client.send(:oauth_client)
|
588
|
+
expect(oauth_client.id).to eq(nil)
|
589
|
+
expect(oauth_client.secret).to eq(nil)
|
590
|
+
expect(oauth_client.site).to eq(config[:auth_host])
|
591
|
+
end
|
592
|
+
|
593
|
+
it "is using 'https://keystok.com' when auth_host is nil" do
|
594
|
+
override_config_key(:auth_host)
|
595
|
+
oauth_client = client.send(:oauth_client)
|
596
|
+
expect(oauth_client.site).to eq('https://keystok.com')
|
597
|
+
end
|
598
|
+
|
599
|
+
it 'caches the instance' do
|
600
|
+
oauth_client_1 = client.send(:oauth_client)
|
601
|
+
oauth_client_2 = client.send(:oauth_client)
|
602
|
+
expect(oauth_client_2).to equal(oauth_client_1)
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under GitDock Oy license terms.
|
3
|
+
# See https://bitbucket.org/keystok/keystok-client-ruby/raw/master/LICENSE.txt
|
4
|
+
# for details.
|
5
|
+
|
6
|
+
require 'spec_helper'
|
7
|
+
|
8
|
+
describe Keystok do
|
9
|
+
describe 'logger' do
|
10
|
+
before do
|
11
|
+
@rails = Rails
|
12
|
+
Kernel.silence_warnings do
|
13
|
+
# rubocop: disable ConstantName
|
14
|
+
Rails = nil
|
15
|
+
# rubocop: enable ConstantName
|
16
|
+
end
|
17
|
+
load 'keystok.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
Kernel.silence_warnings do
|
22
|
+
# rubocop: disable ConstantName
|
23
|
+
Rails = @rails
|
24
|
+
# rubocop: enable ConstantName
|
25
|
+
end
|
26
|
+
load 'keystok.rb'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'create default logger' do
|
30
|
+
expect(Keystok.logger.respond_to?(:warn)).to eq(true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|