gooddata 0.6.43 → 0.6.44
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/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
|