gooddata 0.6.43 → 0.6.44
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +4 -4
- data/lib/gooddata/commands/datasets.rb +2 -2
- data/lib/gooddata/core/logging.rb +1 -1
- data/lib/gooddata/exceptions/maql_execution.rb +16 -0
- data/lib/gooddata/extensions/string.rb +3 -3
- data/lib/gooddata/helpers/global_helpers.rb +3 -3
- data/lib/gooddata/helpers/global_helpers_params.rb +1 -1
- data/lib/gooddata/lcm/lcm.rb +7 -9
- data/lib/gooddata/models/blueprint/blueprint_field.rb +2 -2
- data/lib/gooddata/models/blueprint/dataset_blueprint.rb +1 -1
- data/lib/gooddata/models/domain.rb +1 -1
- data/lib/gooddata/models/membership.rb +2 -2
- data/lib/gooddata/models/metadata.rb +1 -1
- data/lib/gooddata/models/metadata/dashboard.rb +1 -1
- data/lib/gooddata/models/metadata/folder.rb +10 -10
- data/lib/gooddata/models/process.rb +3 -5
- data/lib/gooddata/models/profile.rb +4 -4
- data/lib/gooddata/models/project.rb +17 -7
- data/lib/gooddata/models/project_creator.rb +30 -42
- data/lib/gooddata/models/report_data_result.rb +3 -3
- data/lib/gooddata/rest/client.rb +1 -1
- data/lib/gooddata/rest/connection.rb +85 -132
- data/lib/gooddata/version.rb +1 -1
- data/spec/environment/develop.rb +4 -4
- data/spec/integration/blueprint_updates_spec.rb +1 -1
- data/spec/integration/full_project_spec.rb +10 -7
- data/spec/integration/schedule_spec.rb +0 -2
- data/spec/logging_in_logging_out_spec.rb +2 -2
- data/spec/unit/models/project_creator_spec.rb +46 -98
- metadata +3 -2
@@ -94,7 +94,7 @@ module GoodData
|
|
94
94
|
#
|
95
95
|
# @return [Array] Return left headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
96
96
|
def left_headers
|
97
|
-
return nil if @left_headers_cols_nums
|
97
|
+
return nil if @left_headers_cols_nums.zero?
|
98
98
|
top = @left_headers_cols_nums - 1
|
99
99
|
without_top_headers.slice(0, [0, top]).to_a
|
100
100
|
end
|
@@ -103,7 +103,7 @@ module GoodData
|
|
103
103
|
#
|
104
104
|
# @return [Array] Return top headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
105
105
|
def top_headers
|
106
|
-
return nil if @top_headers_rows_nums
|
106
|
+
return nil if @top_headers_rows_nums.zero?
|
107
107
|
top = @top_headers_rows_nums - 1
|
108
108
|
without_left_headers.slice([0, top], 0).to_a
|
109
109
|
end
|
@@ -175,7 +175,7 @@ module GoodData
|
|
175
175
|
# @return [Array] Returns true if data result is empty
|
176
176
|
def empty?
|
177
177
|
row, cols = size
|
178
|
-
row
|
178
|
+
row.zero? && cols.zero?
|
179
179
|
end
|
180
180
|
|
181
181
|
# Allows you to test if a report contains a row.
|
data/lib/gooddata/rest/client.rb
CHANGED
@@ -367,7 +367,7 @@ module GoodData
|
|
367
367
|
@connection.download source_relative_path, target_file_path, options
|
368
368
|
end
|
369
369
|
|
370
|
-
def download_from_user_webdav(source_relative_path, target_file_path, options = { client: GoodData.client
|
370
|
+
def download_from_user_webdav(source_relative_path, target_file_path, options = { client: GoodData.client })
|
371
371
|
download(source_relative_path, target_file_path, options.merge(:directory => options[:directory],
|
372
372
|
:staging_url => user_webdav_path))
|
373
373
|
end
|
@@ -19,9 +19,6 @@ module RestClient
|
|
19
19
|
def follow_redirection(request = nil, result = nil, &block)
|
20
20
|
fail 'Using monkey patched version of RestClient::AbstractResponse#follow_redirection which is guaranteed to be compatible only with RestClient 1.8.0' if RestClient::VERSION != '1.8.0'
|
21
21
|
|
22
|
-
# @args[:cookies] = request.cookies
|
23
|
-
# old_follow_redirection(request, result, &block)
|
24
|
-
|
25
22
|
new_args = @args.dup
|
26
23
|
|
27
24
|
url = headers[:location]
|
@@ -29,7 +26,7 @@ module RestClient
|
|
29
26
|
|
30
27
|
new_args[:url] = url
|
31
28
|
if request
|
32
|
-
fail MaxRedirectsReached if request.max_redirects
|
29
|
+
fail MaxRedirectsReached if request.max_redirects.zero?
|
33
30
|
new_args[:password] = request.password
|
34
31
|
new_args[:user] = request.user
|
35
32
|
new_args[:headers] = request.headers
|
@@ -101,7 +98,8 @@ module GoodData
|
|
101
98
|
'postUserLogin' => {
|
102
99
|
'login' => username,
|
103
100
|
'password' => password,
|
104
|
-
'remember' => 1
|
101
|
+
'remember' => 1,
|
102
|
+
'verify_level' => 2
|
105
103
|
}
|
106
104
|
}
|
107
105
|
res
|
@@ -154,9 +152,11 @@ module GoodData
|
|
154
152
|
|
155
153
|
# backward compatibility
|
156
154
|
alias_method :cookies, :request_params
|
155
|
+
alias_method :headers, :request_params
|
157
156
|
attr_reader :server
|
158
157
|
attr_reader :stats
|
159
158
|
attr_reader :user
|
159
|
+
attr_reader :verify_ssl
|
160
160
|
|
161
161
|
def initialize(opts)
|
162
162
|
super()
|
@@ -168,9 +168,10 @@ module GoodData
|
|
168
168
|
@user = nil
|
169
169
|
@server = nil
|
170
170
|
@opts = opts
|
171
|
+
@verify_ssl = @opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
171
172
|
|
172
|
-
# Initialize
|
173
|
-
|
173
|
+
# Initialize headers
|
174
|
+
reset_headers!
|
174
175
|
|
175
176
|
@at_exit_handler_installed = nil
|
176
177
|
end
|
@@ -197,7 +198,7 @@ module GoodData
|
|
197
198
|
|
198
199
|
# Reset old cookies first
|
199
200
|
if options[:sst_token]
|
200
|
-
|
201
|
+
merge_headers!(:x_gdc_authsst => options[:sst_token])
|
201
202
|
get('/gdc/account/token', @request_params)
|
202
203
|
|
203
204
|
@user = get(get('/gdc/app/account/bootstrap')['bootstrapResource']['accountSetting']['links']['self'])
|
@@ -230,7 +231,7 @@ module GoodData
|
|
230
231
|
|
231
232
|
begin
|
232
233
|
clear_session_id
|
233
|
-
delete
|
234
|
+
delete(url, :x_gdc_authsst => sst_token) if url
|
234
235
|
rescue RestClient::Unauthorized
|
235
236
|
GoodData.logger.info 'Already disconnected'
|
236
237
|
end
|
@@ -239,7 +240,7 @@ module GoodData
|
|
239
240
|
@server = nil
|
240
241
|
@user = nil
|
241
242
|
|
242
|
-
|
243
|
+
reset_headers!
|
243
244
|
end
|
244
245
|
|
245
246
|
def download(what, where, options = {})
|
@@ -272,46 +273,39 @@ module GoodData
|
|
272
273
|
base_url = dir.empty? ? staging_uri : URI.join(staging_uri, "#{dir}/").to_s
|
273
274
|
url = URI.join(base_url, CGI.escape(what)).to_s
|
274
275
|
|
275
|
-
b = proc do
|
276
|
+
b = proc do |f|
|
276
277
|
raw = {
|
277
|
-
:headers =>
|
278
|
-
:user_agent => GoodData.gem_version_string
|
279
|
-
},
|
278
|
+
:headers => @webdav_headers.merge(:x_gdc_authtt => headers[:x_gdc_authtt]),
|
280
279
|
:method => :get,
|
281
280
|
:url => url,
|
282
|
-
:verify_ssl =>
|
283
|
-
}
|
281
|
+
:verify_ssl => verify_ssl
|
282
|
+
}
|
283
|
+
RestClient::Request.execute(raw) do |chunk, _x, response|
|
284
|
+
if response.code.to_s != '200'
|
285
|
+
fail ArgumentError, "Error downloading #{url}. Got response: #{response.code} #{response} #{response.body}"
|
286
|
+
end
|
287
|
+
f.write chunk
|
288
|
+
end
|
289
|
+
end
|
284
290
|
|
291
|
+
GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
|
285
292
|
if where.is_a?(IO) || where.is_a?(StringIO)
|
286
|
-
|
287
|
-
if response.code.to_s != '200'
|
288
|
-
fail ArgumentError, "Error downloading #{url}. Got response: #{response.code} #{response} #{response.body}"
|
289
|
-
end
|
290
|
-
where.write chunk
|
291
|
-
end
|
293
|
+
b.call(where)
|
292
294
|
else
|
293
295
|
# Assume it is a string or file
|
294
296
|
File.open(where, 'w') do |f|
|
295
|
-
|
296
|
-
if response.code.to_s != '200'
|
297
|
-
fail ArgumentError, "Error downloading #{url}. Got response: #{response.code} #{response} #{response.body}"
|
298
|
-
end
|
299
|
-
f.write chunk
|
300
|
-
end
|
297
|
+
b.call(f)
|
301
298
|
end
|
302
299
|
end
|
303
300
|
end
|
304
|
-
|
305
|
-
res = nil
|
306
|
-
GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
|
307
|
-
res = b.call
|
308
|
-
end
|
309
|
-
res
|
310
301
|
end
|
311
302
|
|
312
303
|
def refresh_token(_options = {})
|
313
304
|
begin # rubocop:disable RedundantBegin
|
314
|
-
|
305
|
+
# avoid infinite loop GET fails with 401
|
306
|
+
response = get(TOKEN_PATH, :x_gdc_authsst => sst_token, :dont_reauth => true)
|
307
|
+
# Remove when TT sent in headers. Currently we need to parse from body
|
308
|
+
merge_headers!(:x_gdc_authtt => GoodData::Helpers.get_path(response, %w(userToken token)))
|
315
309
|
rescue Exception => e # rubocop:disable RescueException
|
316
310
|
puts e.message
|
317
311
|
raise e
|
@@ -329,21 +323,7 @@ module GoodData
|
|
329
323
|
#
|
330
324
|
# @param uri [String] Target URI
|
331
325
|
def delete(uri, options = {})
|
332
|
-
|
333
|
-
GoodData.rest_logger.info "DELETE: #{@server.url}#{uri}"
|
334
|
-
profile "DELETE #{uri}" do
|
335
|
-
b = proc do
|
336
|
-
params = fresh_request_params(options[:request_id])
|
337
|
-
begin
|
338
|
-
@server[uri].delete(params)
|
339
|
-
rescue RestClient::Exception => e
|
340
|
-
# log the error if it happens
|
341
|
-
log_error(e, uri, params, options)
|
342
|
-
raise e
|
343
|
-
end
|
344
|
-
end
|
345
|
-
process_response(options, &b)
|
346
|
-
end
|
326
|
+
request(:delete, uri, nil, options)
|
347
327
|
end
|
348
328
|
|
349
329
|
# Helper for logging error
|
@@ -359,17 +339,26 @@ module GoodData
|
|
359
339
|
end
|
360
340
|
end
|
361
341
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
GoodData.rest_logger.info "
|
368
|
-
profile "
|
342
|
+
def request(method, uri, data, options = {}, &user_block)
|
343
|
+
request_id = options[:request_id] || generate_request_id
|
344
|
+
log_info(options.merge(request_id: request_id))
|
345
|
+
payload = data.is_a?(Hash) ? data.to_json : data
|
346
|
+
|
347
|
+
GoodData.rest_logger.info "#{method.to_s.upcase}: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
|
348
|
+
profile "#{method.to_s.upcase} #{uri}" do
|
369
349
|
b = proc do
|
370
|
-
params = fresh_request_params(
|
350
|
+
params = fresh_request_params(request_id).merge(options)
|
371
351
|
begin
|
372
|
-
|
352
|
+
case method
|
353
|
+
when :get
|
354
|
+
@server[uri].get(params, &user_block)
|
355
|
+
when :put
|
356
|
+
@server[uri].put(payload, params)
|
357
|
+
when :delete
|
358
|
+
@server[uri].delete(params)
|
359
|
+
when :post
|
360
|
+
@server[uri].post(payload, params)
|
361
|
+
end
|
373
362
|
rescue RestClient::Exception => e
|
374
363
|
# log the error if it happens
|
375
364
|
log_error(e, uri, params, options)
|
@@ -380,55 +369,32 @@ module GoodData
|
|
380
369
|
end
|
381
370
|
end
|
382
371
|
|
372
|
+
# HTTP GET
|
373
|
+
#
|
374
|
+
# @param uri [String] Target URI
|
375
|
+
def get(uri, options = {}, &user_block)
|
376
|
+
request(:get, uri, nil, options, &user_block)
|
377
|
+
end
|
378
|
+
|
383
379
|
# HTTP PUT
|
384
380
|
#
|
385
381
|
# @param uri [String] Target URI
|
386
382
|
def put(uri, data, options = {})
|
387
|
-
|
388
|
-
payload = data.is_a?(Hash) ? data.to_json : data
|
389
|
-
GoodData.rest_logger.info "PUT: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
|
390
|
-
profile "PUT #{uri}" do
|
391
|
-
b = proc do
|
392
|
-
params = fresh_request_params(options[:request_id])
|
393
|
-
begin
|
394
|
-
@server[uri].put(payload, params)
|
395
|
-
rescue RestClient::Exception => e
|
396
|
-
# log the error if it happens
|
397
|
-
log_error(e, uri, params, options)
|
398
|
-
raise e
|
399
|
-
end
|
400
|
-
end
|
401
|
-
process_response(options, &b)
|
402
|
-
end
|
383
|
+
request(:put, uri, data, options)
|
403
384
|
end
|
404
385
|
|
405
386
|
# HTTP POST
|
406
387
|
#
|
407
388
|
# @param uri [String] Target URI
|
408
389
|
def post(uri, data = nil, options = {})
|
409
|
-
|
410
|
-
GoodData.rest_logger.info "POST: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
|
411
|
-
profile "POST #{uri}" do
|
412
|
-
payload = data.is_a?(Hash) ? data.to_json : data
|
413
|
-
b = proc do
|
414
|
-
params = fresh_request_params(options[:request_id])
|
415
|
-
begin
|
416
|
-
@server[uri].post(payload, params)
|
417
|
-
rescue RestClient::Exception => e
|
418
|
-
# log the error if it happens
|
419
|
-
log_error(e, uri, params, options)
|
420
|
-
raise e
|
421
|
-
end
|
422
|
-
end
|
423
|
-
process_response(options, &b)
|
424
|
-
end
|
390
|
+
request(:post, uri, data, options)
|
425
391
|
end
|
426
392
|
|
427
393
|
# Reader method for SST token
|
428
394
|
#
|
429
395
|
# @return uri [String] SST token
|
430
396
|
def sst_token
|
431
|
-
request_params[:
|
397
|
+
request_params[:x_gdc_authsst]
|
432
398
|
end
|
433
399
|
|
434
400
|
def stats_table(values = stats)
|
@@ -484,7 +450,7 @@ module GoodData
|
|
484
450
|
#
|
485
451
|
# @return uri [String] TT token
|
486
452
|
def tt_token
|
487
|
-
request_params[:
|
453
|
+
request_params[:x_gdc_authtt]
|
488
454
|
end
|
489
455
|
|
490
456
|
# Uploads a file to GoodData server
|
@@ -514,9 +480,9 @@ module GoodData
|
|
514
480
|
raw = {
|
515
481
|
:method => method,
|
516
482
|
:url => url,
|
517
|
-
:headers => @webdav_headers,
|
518
|
-
:verify_ssl =>
|
519
|
-
}
|
483
|
+
:headers => @webdav_headers.merge(:x_gdc_authtt => headers[:x_gdc_authtt]),
|
484
|
+
:verify_ssl => verify_ssl
|
485
|
+
}
|
520
486
|
RestClient::Request.execute(raw)
|
521
487
|
end
|
522
488
|
|
@@ -528,20 +494,12 @@ module GoodData
|
|
528
494
|
def do_stream_file(uri, filename, _options = {})
|
529
495
|
GoodData.logger.info "Uploading file user storage #{uri}"
|
530
496
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
http.use_ssl = true
|
538
|
-
http.verify_mode = (@opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
539
|
-
|
540
|
-
response = nil
|
541
|
-
GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
|
542
|
-
response = http.start { |client| client.request(req) }
|
543
|
-
end
|
544
|
-
response
|
497
|
+
request = RestClient::Request.new(:method => :put,
|
498
|
+
:url => uri.to_s,
|
499
|
+
:verify_ssl => verify_ssl,
|
500
|
+
:headers => @webdav_headers.merge(:x_gdc_authtt => headers[:x_gdc_authtt]),
|
501
|
+
:payload => File.new(filename, 'rb'))
|
502
|
+
request.execute
|
545
503
|
end
|
546
504
|
|
547
505
|
def format_error(e, params)
|
@@ -570,31 +528,32 @@ module GoodData
|
|
570
528
|
def log_info(options)
|
571
529
|
# if info_message given, log it with request_id (given or generated)
|
572
530
|
if options[:info_message]
|
573
|
-
|
574
|
-
GoodData.logger.info "#{options[:info_message]} Request id: #{request_id}"
|
531
|
+
GoodData.logger.info "#{options[:info_message]} Request id: #{options[:request_id]}"
|
575
532
|
end
|
576
|
-
options
|
577
533
|
end
|
578
534
|
|
579
535
|
# request heders with freshly generated request id
|
580
536
|
def fresh_request_params(request_id = nil)
|
581
|
-
|
537
|
+
tt = { :x_gdc_authtt => tt_token }
|
538
|
+
tt.merge(:x_gdc_request => request_id || generate_request_id)
|
582
539
|
end
|
583
540
|
|
584
|
-
def
|
585
|
-
@request_params
|
541
|
+
def merge_headers!(headers)
|
542
|
+
@request_params.merge! headers.slice(:x_gdc_authtt, :x_gdc_authsst)
|
586
543
|
end
|
587
544
|
|
588
545
|
def process_response(options = {}, &block)
|
589
546
|
retries = options[:tries] || 3
|
590
|
-
|
547
|
+
process = options[:process]
|
548
|
+
dont_reauth = options[:dont_reauth]
|
549
|
+
options = options.reject { |k, _| [:process, :dont_reauth].include?(k) }
|
550
|
+
opts = { tries: retries, refresh_token: proc { refresh_token unless dont_reauth } }.merge(options)
|
591
551
|
response = GoodData::Rest::Connection.retryable(opts) do
|
592
552
|
block.call
|
593
553
|
end
|
594
|
-
|
595
|
-
merge_cookies! response.cookies
|
554
|
+
merge_headers! response.headers
|
596
555
|
content_type = response.headers[:content_type]
|
597
|
-
return response if
|
556
|
+
return response if process == false
|
598
557
|
|
599
558
|
if content_type == 'application/json' || content_type == 'application/json;charset=UTF-8'
|
600
559
|
result = response.to_str == '""' ? {} : MultiJson.load(response.to_str)
|
@@ -630,8 +589,8 @@ module GoodData
|
|
630
589
|
res
|
631
590
|
end
|
632
591
|
|
633
|
-
def
|
634
|
-
@request_params = {
|
592
|
+
def reset_headers!
|
593
|
+
@request_params = {}
|
635
594
|
end
|
636
595
|
|
637
596
|
def scrub_params(params, keys)
|
@@ -741,25 +700,19 @@ module GoodData
|
|
741
700
|
method = :get
|
742
701
|
GoodData.logger.debug "#{method}: #{url}"
|
743
702
|
|
744
|
-
|
703
|
+
GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
|
745
704
|
raw = {
|
746
705
|
:method => method,
|
747
706
|
:url => url,
|
748
|
-
:headers => @webdav_headers,
|
749
|
-
:verify_ssl =>
|
750
|
-
}.merge(
|
707
|
+
:headers => @webdav_headers.merge(:x_gdc_authtt => headers[:x_gdc_authtt]),
|
708
|
+
:verify_ssl => verify_ssl
|
709
|
+
}.merge(headers)
|
751
710
|
begin
|
752
711
|
RestClient::Request.execute(raw)
|
753
712
|
rescue RestClient::Exception => e
|
754
713
|
false if e.http_code == 404
|
755
714
|
end
|
756
715
|
end
|
757
|
-
|
758
|
-
res = nil
|
759
|
-
GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
|
760
|
-
res = b.call
|
761
|
-
end
|
762
|
-
res
|
763
716
|
end
|
764
717
|
end
|
765
718
|
end
|
data/lib/gooddata/version.rb
CHANGED
data/spec/environment/develop.rb
CHANGED
@@ -13,19 +13,19 @@ module GoodData
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module ProcessHelper
|
16
|
-
set_const :PROCESS_ID, '
|
17
|
-
set_const :DEPLOY_NAME, '
|
16
|
+
set_const :PROCESS_ID, '98c836cf-bdf6-405e-bb8a-f4dc201588dd'
|
17
|
+
set_const :DEPLOY_NAME, 'gooddata_version.rb'
|
18
18
|
end
|
19
19
|
|
20
20
|
module ProjectHelper
|
21
|
-
set_const :PROJECT_ID, '
|
21
|
+
set_const :PROJECT_ID, 'l11tat2c0v4ae6mtxjv74jk8c37xz5ra'
|
22
22
|
set_const :PROJECT_URL, "/gdc/projects/#{PROJECT_ID}"
|
23
23
|
set_const :PROJECT_TITLE, 'GoodTravis'
|
24
24
|
set_const :PROJECT_SUMMARY, 'No summary'
|
25
25
|
end
|
26
26
|
|
27
27
|
module ScheduleHelper
|
28
|
-
set_const :SCHEDULE_ID, '
|
28
|
+
set_const :SCHEDULE_ID, '57f42cfae4b041699a8eb52a'
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|