gooddata 2.1.19-java → 2.3.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gdc-ii-config.yaml +42 -1
- data/.github/workflows/build.yml +67 -0
- data/.github/workflows/pre-merge.yml +72 -0
- data/.pronto.yml +1 -0
- data/.rubocop.yml +2 -14
- data/CHANGELOG.md +47 -0
- data/Dockerfile +27 -14
- data/Dockerfile.jruby +5 -15
- data/Dockerfile.ruby +5 -7
- data/Gemfile +4 -2
- data/README.md +6 -6
- data/Rakefile +1 -1
- data/SDK_VERSION +1 -1
- data/VERSION +1 -1
- data/bin/run_brick.rb +7 -0
- data/ci/mssql/pom.xml +62 -0
- data/ci/mysql/pom.xml +62 -0
- data/ci/redshift/pom.xml +4 -5
- data/docker-compose.lcm.yml +42 -4
- data/docker-compose.yml +42 -0
- data/gooddata.gemspec +21 -21
- data/k8s/charts/lcm-bricks/Chart.yaml +1 -1
- data/lcm.rake +11 -8
- data/lib/gooddata/bricks/base_pipeline.rb +26 -0
- data/lib/gooddata/bricks/brick.rb +0 -1
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +35 -9
- data/lib/gooddata/bricks/middleware/execution_result_middleware.rb +3 -3
- data/lib/gooddata/bricks/pipeline.rb +2 -14
- data/lib/gooddata/cloud_resources/blobstorage/blobstorage_client.rb +98 -0
- data/lib/gooddata/cloud_resources/mssql/drivers/.gitkeepme +0 -0
- data/lib/gooddata/cloud_resources/mssql/mssql_client.rb +122 -0
- data/lib/gooddata/cloud_resources/mysql/drivers/.gitkeepme +0 -0
- data/lib/gooddata/cloud_resources/mysql/mysql_client.rb +121 -0
- data/lib/gooddata/cloud_resources/postgresql/postgresql_client.rb +0 -1
- data/lib/gooddata/cloud_resources/redshift/drivers/.gitkeepme +0 -0
- data/lib/gooddata/cloud_resources/redshift/redshift_client.rb +0 -2
- data/lib/gooddata/cloud_resources/snowflake/snowflake_client.rb +18 -1
- data/lib/gooddata/helpers/data_helper.rb +9 -4
- data/lib/gooddata/lcm/actions/base_action.rb +157 -0
- data/lib/gooddata/lcm/actions/collect_data_product.rb +2 -1
- data/lib/gooddata/lcm/actions/collect_meta.rb +3 -1
- data/lib/gooddata/lcm/actions/collect_projects_warning_status.rb +53 -0
- data/lib/gooddata/lcm/actions/collect_segment_clients.rb +14 -0
- data/lib/gooddata/lcm/actions/initialize_continue_on_error_option.rb +87 -0
- data/lib/gooddata/lcm/actions/migrate_gdc_date_dimension.rb +31 -4
- data/lib/gooddata/lcm/actions/provision_clients.rb +34 -5
- data/lib/gooddata/lcm/actions/synchronize_cas.rb +24 -4
- data/lib/gooddata/lcm/actions/synchronize_clients.rb +112 -11
- data/lib/gooddata/lcm/actions/synchronize_dataset_mappings.rb +89 -0
- data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +48 -11
- data/lib/gooddata/lcm/actions/synchronize_kd_dashboard_permission.rb +103 -0
- data/lib/gooddata/lcm/actions/synchronize_ldm.rb +79 -23
- data/lib/gooddata/lcm/actions/synchronize_ldm_layout.rb +98 -0
- data/lib/gooddata/lcm/actions/synchronize_pp_dashboard_permission.rb +108 -0
- data/lib/gooddata/lcm/actions/synchronize_schedules.rb +31 -1
- data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +26 -18
- data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +30 -4
- data/lib/gooddata/lcm/actions/synchronize_users.rb +11 -10
- data/lib/gooddata/lcm/actions/update_metric_formats.rb +202 -0
- data/lib/gooddata/lcm/data/delete_from_lcm_release.sql.erb +5 -0
- data/lib/gooddata/lcm/exceptions/lcm_execution_warning.rb +15 -0
- data/lib/gooddata/lcm/helpers/check_helper.rb +19 -0
- data/lib/gooddata/lcm/helpers/release_table_helper.rb +42 -8
- data/lib/gooddata/lcm/lcm2.rb +50 -4
- data/lib/gooddata/lcm/user_bricks_helper.rb +9 -0
- data/lib/gooddata/mixins/inspector.rb +1 -1
- data/lib/gooddata/mixins/md_object_query.rb +1 -0
- data/lib/gooddata/models/data_source.rb +5 -1
- data/lib/gooddata/models/dataset_mapping.rb +36 -0
- data/lib/gooddata/models/ldm_layout.rb +38 -0
- data/lib/gooddata/models/metadata/label.rb +26 -27
- data/lib/gooddata/models/project.rb +230 -30
- data/lib/gooddata/models/project_creator.rb +83 -6
- data/lib/gooddata/models/schedule.rb +13 -1
- data/lib/gooddata/models/segment.rb +2 -1
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +162 -68
- data/lib/gooddata/rest/connection.rb +5 -3
- data/lib/gooddata/rest/phmap.rb +2 -0
- data/lib/gooddata.rb +1 -0
- data/lib/gooddata_brick_base.rb +35 -0
- data/sonar-project.properties +6 -0
- metadata +96 -65
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +0 -37
- data/lib/gooddata/cloud_resources/redshift/drivers/log4j.properties +0 -15
@@ -19,6 +19,9 @@ using NilExtensions
|
|
19
19
|
|
20
20
|
module GoodData
|
21
21
|
module UserFilterBuilder
|
22
|
+
@all_domain_users = {}
|
23
|
+
@mutex = Mutex.new
|
24
|
+
|
22
25
|
# Main Entry function. Gets values and processes them to get filters
|
23
26
|
# that are suitable for other function to process.
|
24
27
|
# Values can be read from file or provided inline as an array.
|
@@ -48,11 +51,26 @@ module GoodData
|
|
48
51
|
end
|
49
52
|
|
50
53
|
def self.read_file(file, options = {})
|
51
|
-
memo =
|
52
|
-
|
54
|
+
memo = Hash[]
|
55
|
+
if row_based?(options)
|
56
|
+
read_data_without_header(file, memo, options)
|
57
|
+
else
|
58
|
+
read_data_with_header(file, memo, options)
|
59
|
+
end
|
60
|
+
memo
|
61
|
+
end
|
53
62
|
|
54
|
-
|
55
|
-
|
63
|
+
def self.read_data_without_header(file, memo, options)
|
64
|
+
CSV.foreach(file, headers: false, return_headers: false) do |row|
|
65
|
+
key, data = process_line(row, options)
|
66
|
+
memo[key] = [] unless memo.key?(key)
|
67
|
+
memo[key].concat(data)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.read_data_with_header(file, memo, options)
|
72
|
+
CSV.foreach(file, headers: true, return_headers: false) do |row|
|
73
|
+
key, data = process_line(row, options)
|
56
74
|
memo[key] = [] unless memo.key?(key)
|
57
75
|
memo[key].concat(data)
|
58
76
|
end
|
@@ -203,20 +221,30 @@ module GoodData
|
|
203
221
|
# so it precaches the values and still be able to function for larger ones even
|
204
222
|
# though that would mean tons of requests
|
205
223
|
def self.get_small_labels(labels_cache)
|
206
|
-
labels_cache.values.select { |label| label
|
224
|
+
labels_cache.values.select { |label| label &.values_count &. < 100_000 }
|
207
225
|
end
|
208
226
|
|
209
227
|
# Creates a MAQL expression(s) based on the filter defintion.
|
210
228
|
# Takes the filter definition looks up any necessary values and provides API executable MAQL
|
211
229
|
# @param labels_cache e.g. { 'label_uri': label_object }
|
212
230
|
# @param lookups_cache e.g. { 'label_uri': { "jirka@gooddata.com": 'value_uri' }}
|
213
|
-
|
231
|
+
# rubocop:disable Metrics/ParameterLists
|
232
|
+
def self.create_expression(filter, labels_cache, lookups_cache, attr_cache, options = {}, login)
|
214
233
|
values = filter[:values]
|
215
234
|
# Do not create MUF for label when all its values is NULL (https://jira.intgdc.com/browse/TMA-1361)
|
216
235
|
non_null_values = values.select { |value| !value.nil? && value.downcase != 'null' }
|
217
236
|
return ['TRUE', []] if non_null_values.empty?
|
218
237
|
|
219
238
|
label = labels_cache[filter[:label]]
|
239
|
+
if label.nil?
|
240
|
+
err_message = "Unable to apply filter values: #{values} since the project: #{options[:project].pid} doesn't have label: #{filter[:label]} for login: #{login}"
|
241
|
+
if options[:ignore_missing_values]
|
242
|
+
GoodData.logger.warn(err_message)
|
243
|
+
return ['TRUE', []]
|
244
|
+
else
|
245
|
+
fail err_message
|
246
|
+
end
|
247
|
+
end
|
220
248
|
errors = []
|
221
249
|
|
222
250
|
element_uris_by_values = Hash[values.map do |v|
|
@@ -262,6 +290,7 @@ module GoodData
|
|
262
290
|
end
|
263
291
|
[expression, errors]
|
264
292
|
end
|
293
|
+
# rubocop:enable Metrics/ParameterLists
|
265
294
|
|
266
295
|
# Encapuslates the creation of filter
|
267
296
|
def self.create_user_filter(expression, related)
|
@@ -273,6 +302,66 @@ module GoodData
|
|
273
302
|
}
|
274
303
|
end
|
275
304
|
|
305
|
+
def self.create_user_profile_mapping(filters, project_users, options = {})
|
306
|
+
domain = options[:domain]
|
307
|
+
found_list = {}
|
308
|
+
missing_list = []
|
309
|
+
|
310
|
+
# Get the list of user login from filters
|
311
|
+
login_list = filters.flat_map do |filter|
|
312
|
+
filter[:login]
|
313
|
+
end
|
314
|
+
|
315
|
+
# Then find user login in the users_brick_input
|
316
|
+
users_brick_input = options[:users_brick_input]
|
317
|
+
if users_brick_input&.any?
|
318
|
+
users_brick_input.map do |user|
|
319
|
+
login_list << user.with_indifferent_access['login']
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
login_list.uniq.flat_map do |login|
|
324
|
+
user = project_users.find { |u| u.login == login }
|
325
|
+
if user
|
326
|
+
found_list[login] = user.profile_url
|
327
|
+
else
|
328
|
+
missing_list << login
|
329
|
+
end
|
330
|
+
end
|
331
|
+
# rubocop:disable Metrics/BlockNesting
|
332
|
+
unless missing_list.empty? || domain.nil?
|
333
|
+
if missing_list.size < 100
|
334
|
+
missing_list.each do |login|
|
335
|
+
user = domain.find_user_by_login(login)
|
336
|
+
found_list[login] = user.links['self'] if user
|
337
|
+
end
|
338
|
+
else
|
339
|
+
if @all_domain_users[domain.name].nil?
|
340
|
+
@mutex.lock
|
341
|
+
if @all_domain_users[domain.name].nil?
|
342
|
+
domain_users = domain.users
|
343
|
+
@all_domain_users[domain.name] = domain_users
|
344
|
+
GoodData.logger.info("action=lcm_get_domain_users domain=#{domain.name} number_users=#{domain_users.size} number_missing_users=#{missing_list.size} use_cache=false")
|
345
|
+
else
|
346
|
+
domain_users = @all_domain_users[domain.name]
|
347
|
+
GoodData.logger.info("action=lcm_get_domain_users domain=##{domain.name} number_users=#{domain_users.size} number_missing_users=#{missing_list.size} use_cache=true")
|
348
|
+
end
|
349
|
+
@mutex.unlock
|
350
|
+
else
|
351
|
+
domain_users = @all_domain_users[domain.name]
|
352
|
+
GoodData.logger.info("action=lcm_get_domain_users domain=##{domain.name} number_users=#{domain_users.size} number_missing_users=#{missing_list.size} use_cache=true")
|
353
|
+
end
|
354
|
+
|
355
|
+
missing_list.each do |login|
|
356
|
+
user = domain_users.find { |u| u.login == login }
|
357
|
+
found_list[login] = user.links['self'] if user
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
# rubocop:enable Metrics/BlockNesting
|
362
|
+
found_list
|
363
|
+
end
|
364
|
+
|
276
365
|
# Resolves and creates maql statements from filter definitions.
|
277
366
|
# This method does not perform any modifications on API but
|
278
367
|
# collects all the information that is needed to do so.
|
@@ -283,7 +372,7 @@ module GoodData
|
|
283
372
|
#
|
284
373
|
# @param filters [Array<Hash>] Filters definition
|
285
374
|
# @return [Array] first is list of MAQL statements
|
286
|
-
def self.maqlify_filters(filters,
|
375
|
+
def self.maqlify_filters(filters, user_profile_mapping, options = {})
|
287
376
|
fail_early = options[:fail_early] == false ? false : true
|
288
377
|
users_cache = options[:users_cache]
|
289
378
|
labels_cache = create_label_cache(filters, options)
|
@@ -291,11 +380,10 @@ module GoodData
|
|
291
380
|
lookups_cache = create_lookups_cache(small_labels)
|
292
381
|
attrs_cache = create_attrs_cache(filters, options)
|
293
382
|
create_filter_proc = proc do |login, f|
|
294
|
-
expression, errors = create_expression(f, labels_cache, lookups_cache, attrs_cache, options)
|
383
|
+
expression, errors = create_expression(f, labels_cache, lookups_cache, attrs_cache, options, login)
|
295
384
|
safe_login = login.downcase
|
296
385
|
profiles_uri = if options[:type] == :muf
|
297
|
-
|
298
|
-
project_user.nil? ? ('/gdc/account/profile/' + safe_login) : project_user.profile_url
|
386
|
+
user_profile_mapping[safe_login].nil? ? ('/gdc/account/profile/' + safe_login) : user_profile_mapping[safe_login]
|
299
387
|
elsif options[:type] == :variable
|
300
388
|
(users_cache[login] && users_cache[login].uri)
|
301
389
|
else
|
@@ -393,7 +481,8 @@ module GoodData
|
|
393
481
|
|
394
482
|
project_users = project.users
|
395
483
|
filters = normalize_filters(user_filters)
|
396
|
-
|
484
|
+
user_profile_mapping = create_user_profile_mapping(filters, project_users, options)
|
485
|
+
user_filters, errors = maqlify_filters(filters, user_profile_mapping, options.merge(users_must_exist: users_must_exist, type: :muf))
|
397
486
|
if !ignore_missing_values && !errors.empty?
|
398
487
|
errors = errors.map do |e|
|
399
488
|
e.merge(pid: project.pid)
|
@@ -404,7 +493,7 @@ module GoodData
|
|
404
493
|
filters = user_filters.map { |data| client.create(MandatoryUserFilter, data, project: project) }
|
405
494
|
to_create, to_delete = resolve_user_filters(filters, project.data_permissions)
|
406
495
|
|
407
|
-
to_delete = sanitize_filters_to_delete(to_delete, options[:users_brick_input],
|
496
|
+
to_delete = sanitize_filters_to_delete(to_delete, options[:users_brick_input], user_profile_mapping) unless options[:no_sanitize]
|
408
497
|
|
409
498
|
if options[:do_not_touch_filters_that_are_not_mentioned]
|
410
499
|
GoodData.logger.warn("Data permissions computed: #{to_create.count} to create")
|
@@ -421,68 +510,73 @@ module GoodData
|
|
421
510
|
results: create_results + delete_results }
|
422
511
|
end
|
423
512
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
'userFilters'
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
513
|
+
if to_create.empty?
|
514
|
+
create_results = []
|
515
|
+
else
|
516
|
+
create_results = to_create.each_slice(100).flat_map do |batch|
|
517
|
+
batch.pmapcat do |related_uri, group|
|
518
|
+
group.each(&:save)
|
519
|
+
res = client.get("/gdc/md/#{project.pid}/userfilters?users=#{related_uri}")
|
520
|
+
items = res['userFilters']['items'].empty? ? [] : res['userFilters']['items'].first['userFilters']
|
521
|
+
|
522
|
+
payload = {
|
523
|
+
'userFilters' => {
|
524
|
+
'items' => [{
|
525
|
+
'user' => related_uri,
|
526
|
+
'userFilters' => items.concat(group.map(&:uri))
|
527
|
+
}]
|
528
|
+
}
|
436
529
|
}
|
437
|
-
|
438
|
-
res = client.post("/gdc/md/#{project.pid}/userfilters", payload)
|
530
|
+
res = client.post("/gdc/md/#{project.pid}/userfilters", payload)
|
439
531
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
532
|
+
# turn the errors from hashes into array of hashes
|
533
|
+
update_result = res['userFiltersUpdateResult'].flat_map do |k, v|
|
534
|
+
v.map { |r| { status: k.to_sym, user: r, type: :create } }
|
535
|
+
end
|
444
536
|
|
445
|
-
|
446
|
-
|
537
|
+
update_result.map do |result|
|
538
|
+
result[:status] == :failed ? result.merge(GoodData::Helpers.symbolize_keys(result[:user])) : result
|
539
|
+
end
|
447
540
|
end
|
448
541
|
end
|
542
|
+
project_log_formatter.log_user_filter_results(create_results, to_create)
|
543
|
+
create_errors = create_results.select { |r| r[:status] == :failed }
|
544
|
+
fail "Creating MUFs resulted in errors: #{create_errors}" if create_errors.any?
|
449
545
|
end
|
450
546
|
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
res = client.post("/gdc/md/#{project.pid}/userfilters", payload)
|
473
|
-
results.concat(res['userFiltersUpdateResult']
|
547
|
+
if to_delete.empty?
|
548
|
+
delete_results = []
|
549
|
+
elsif !options[:do_not_touch_filters_that_are_not_mentioned]
|
550
|
+
delete_results = to_delete.each_slice(100).flat_map do |batch|
|
551
|
+
batch.flat_map do |related_uri, group|
|
552
|
+
results = []
|
553
|
+
if related_uri
|
554
|
+
res = client.get("/gdc/md/#{project.pid}/userfilters?users=#{related_uri}")
|
555
|
+
items = res['userFilters']['items'].empty? ? [] : res['userFilters']['items'].first['userFilters']
|
556
|
+
payload = {
|
557
|
+
'userFilters' => {
|
558
|
+
'items' => [
|
559
|
+
{
|
560
|
+
'user' => related_uri,
|
561
|
+
'userFilters' => items - group.map(&:uri)
|
562
|
+
}
|
563
|
+
]
|
564
|
+
}
|
565
|
+
}
|
566
|
+
res = client.post("/gdc/md/#{project.pid}/userfilters", payload)
|
567
|
+
results.concat(res['userFiltersUpdateResult']
|
474
568
|
.flat_map { |k, v| v.map { |r| { status: k.to_sym, user: r, type: :delete } } }
|
475
569
|
.map { |result| result[:status] == :failed ? result.merge(GoodData::Helpers.symbolize_keys(result[:user])) : result })
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
end
|
481
|
-
end
|
570
|
+
end
|
571
|
+
group.peach(&:delete)
|
572
|
+
results
|
573
|
+
end
|
482
574
|
|
483
|
-
|
484
|
-
|
485
|
-
|
575
|
+
project_log_formatter.log_user_filter_results(delete_results, to_delete)
|
576
|
+
delete_errors = delete_results.select { |r| r[:status] == :failed } if delete_results
|
577
|
+
fail "Deleting MUFs resulted in errors: #{delete_errors}" if delete_errors&.any?
|
578
|
+
end
|
579
|
+
end
|
486
580
|
|
487
581
|
{ created: to_create, deleted: to_delete, results: create_results + (delete_results || []) }
|
488
582
|
end
|
@@ -494,7 +588,7 @@ module GoodData
|
|
494
588
|
# @param file [String | Array] File or array of values to be parsed for filters
|
495
589
|
# @param options [Hash] Filter definitions
|
496
590
|
# @return [Array<Hash>]
|
497
|
-
def self.get_values(file, options)
|
591
|
+
def self.get_values(file, options = {})
|
498
592
|
file.is_a?(Array) ? read_array(file, options) : read_file(file, options)
|
499
593
|
end
|
500
594
|
|
@@ -579,12 +673,12 @@ module GoodData
|
|
579
673
|
# Removes MUFs from to_delete unless in user is in users_brick_input
|
580
674
|
# if this does not happen, users that are about to be deleted by users_brick
|
581
675
|
# would have all their filters removed now, which is not desirable
|
582
|
-
def self.sanitize_filters_to_delete(to_delete, users_brick_input,
|
676
|
+
def self.sanitize_filters_to_delete(to_delete, users_brick_input, user_profile_mapping)
|
583
677
|
return [] unless users_brick_input && users_brick_input.any?
|
584
678
|
user_profiles = users_brick_input.map do |user|
|
585
|
-
result =
|
679
|
+
result = user_profile_mapping[user.with_indifferent_access['login']]
|
586
680
|
next unless result
|
587
|
-
result
|
681
|
+
result
|
588
682
|
end.compact
|
589
683
|
return [] unless user_profiles.any?
|
590
684
|
to_delete.reject do |_, value|
|
@@ -68,6 +68,8 @@ module GoodData
|
|
68
68
|
RETRY_TIME_COEFFICIENT = 1.5
|
69
69
|
RETRYABLE_ERRORS << Net::ReadTimeout if Net.const_defined?(:ReadTimeout)
|
70
70
|
|
71
|
+
RETRYABLE_ERRORS << OpenSSL::SSL::SSLErrorWaitReadable if OpenSSL::SSL.const_defined?(:SSLErrorWaitReadable)
|
72
|
+
|
71
73
|
class << self
|
72
74
|
def construct_login_payload(username, password)
|
73
75
|
res = {
|
@@ -304,12 +306,12 @@ module GoodData
|
|
304
306
|
end
|
305
307
|
|
306
308
|
def refresh_token(_options = {})
|
307
|
-
begin # rubocop:disable RedundantBegin
|
309
|
+
begin # rubocop:disable Style/RedundantBegin
|
308
310
|
# avoid infinite loop GET fails with 401
|
309
311
|
response = get(TOKEN_PATH, :x_gdc_authsst => sst_token, :dont_reauth => true)
|
310
312
|
# Remove when TT sent in headers. Currently we need to parse from body
|
311
313
|
merge_headers!(:x_gdc_authtt => GoodData::Helpers.get_path(response, %w(userToken token)))
|
312
|
-
rescue Exception => e # rubocop:disable RescueException
|
314
|
+
rescue Exception => e # rubocop:disable Style/RescueException
|
313
315
|
raise e
|
314
316
|
end
|
315
317
|
end
|
@@ -688,7 +690,7 @@ ERR
|
|
688
690
|
execution_id = request_id
|
689
691
|
|
690
692
|
GoodData.gd_logger.update_store(domain, method, duration, endpoint)
|
691
|
-
GoodData.gd_logger.add Logger::
|
693
|
+
GoodData.gd_logger.add Logger::DEBUG, { endpoint: endpoint, duration: duration, domain: domain,
|
692
694
|
execution_id: execution_id, time_stamp: time_stamp }, "rest_call"
|
693
695
|
end
|
694
696
|
end
|
data/lib/gooddata/rest/phmap.rb
CHANGED
@@ -82,6 +82,8 @@ module GoodData
|
|
82
82
|
|
83
83
|
['/gdc/internal/projects/{id}/objects/setPermissions', %r{/gdc/internal/projects/[^\/]+/objects/setPermissions}],
|
84
84
|
['/gdc/internal/projects/{id}/roles', %r{/gdc/internal/projects/[^\/]+/roles}],
|
85
|
+
['/gdc/dataload/projects/{id}/modelMapping/datasets/bulk/upsert', %r{/gdc/dataload/projects/[^\/]+/modelMapping/datasets/bulk/upsert}],
|
86
|
+
['/gdc/dataload/internal/projects/{id}/ldmLayout', %r{/gdc/dataload/internal/projects/[^\/]+/ldmLayout}],
|
85
87
|
['/gdc/md/{id}/variables/item/{id}', %r{/gdc/md/[^\/]+/variables/item/[\d]+}],
|
86
88
|
['/gdc/md/{id}/validate/task/{id}', %r{/gdc/md/[^\/]+/validate/task/[^\/]+}],
|
87
89
|
['/gdc/md/{id}/using2/{id}/{id}', %r{/gdc/md/[^\/]+/using2/[\d]+/[\d]+}],
|
data/lib/gooddata.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010-2022 GoodData Corporation. All rights reserved.
|
5
|
+
# This source code is licensed under the BSD-style license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
require 'pmap'
|
9
|
+
$pmap_default_thread_count = 20 # rubocop:disable GlobalVars
|
10
|
+
|
11
|
+
# GoodData Module
|
12
|
+
module GoodData
|
13
|
+
end
|
14
|
+
|
15
|
+
# Modules
|
16
|
+
require_relative 'gooddata/core/core'
|
17
|
+
require_relative 'gooddata/models/models'
|
18
|
+
require_relative 'gooddata/exceptions/exceptions'
|
19
|
+
require_relative 'gooddata/helpers/helpers'
|
20
|
+
|
21
|
+
# Files
|
22
|
+
require_relative 'gooddata/bricks/utils'
|
23
|
+
require_relative 'gooddata/bricks/brick'
|
24
|
+
require_relative 'gooddata/bricks/base_pipeline'
|
25
|
+
require_relative 'gooddata/bricks/middleware/base_middleware'
|
26
|
+
require_relative 'gooddata/bricks/middleware/bench_middleware'
|
27
|
+
require_relative 'gooddata/bricks/middleware/logger_middleware'
|
28
|
+
require_relative 'gooddata/bricks/middleware/decode_params_middleware'
|
29
|
+
require_relative 'gooddata/bricks/middleware/aws_middleware'
|
30
|
+
require_relative 'gooddata/bricks/middleware/dwh_middleware'
|
31
|
+
require_relative 'gooddata/bricks/middleware/bench_middleware'
|
32
|
+
|
33
|
+
# CSV Downloader
|
34
|
+
require_relative 'gooddata/core/logging'
|
35
|
+
require_relative 'gooddata/connection'
|