gooddata 2.2.0-java → 2.3.0-java
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 +5 -5
- data/.gdc-ii-config.yaml +42 -1
- data/.github/workflows/build.yml +14 -13
- data/.github/workflows/pre-merge.yml +13 -13
- data/.pronto.yml +1 -0
- data/.rubocop.yml +2 -14
- data/CHANGELOG.md +9 -0
- data/Dockerfile +13 -7
- data/Dockerfile.jruby +5 -5
- data/Dockerfile.ruby +5 -7
- data/Gemfile +4 -2
- data/README.md +5 -4
- data/Rakefile +1 -1
- data/SDK_VERSION +1 -1
- data/VERSION +1 -1
- data/bin/run_brick.rb +7 -0
- data/ci/mysql/pom.xml +6 -1
- data/ci/redshift/pom.xml +3 -4
- data/docker-compose.lcm.yml +42 -1
- data/docker-compose.yml +42 -0
- data/gooddata.gemspec +21 -22
- data/lcm.rake +9 -0
- data/lib/gooddata/bricks/base_pipeline.rb +26 -0
- data/lib/gooddata/bricks/brick.rb +0 -1
- data/lib/gooddata/bricks/middleware/execution_result_middleware.rb +3 -3
- data/lib/gooddata/bricks/pipeline.rb +2 -14
- data/lib/gooddata/cloud_resources/mysql/mysql_client.rb +18 -8
- 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 +1 -1
- 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_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 +28 -2
- 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 +56 -4
- data/lib/gooddata/lcm/actions/synchronize_dataset_mappings.rb +28 -3
- 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 +60 -15
- 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 +14 -9
- 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 +21 -4
- 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/lcm2.rb +45 -4
- data/lib/gooddata/lcm/user_bricks_helper.rb +9 -0
- data/lib/gooddata/mixins/inspector.rb +1 -1
- data/lib/gooddata/models/ldm_layout.rb +38 -0
- data/lib/gooddata/models/project.rb +197 -22
- data/lib/gooddata/models/project_creator.rb +83 -6
- data/lib/gooddata/models/segment.rb +2 -1
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +104 -15
- data/lib/gooddata/rest/connection.rb +5 -3
- data/lib/gooddata/rest/phmap.rb +1 -0
- data/lib/gooddata.rb +1 -0
- data/lib/gooddata_brick_base.rb +35 -0
- data/sonar-project.properties +6 -0
- metadata +60 -55
- data/lib/gooddata/cloud_resources/redshift/drivers/log4j.properties +0 -15
@@ -39,6 +39,9 @@ module GoodData
|
|
39
39
|
opts = { client: GoodData.connection }.merge(opts)
|
40
40
|
dry_run = opts[:dry_run]
|
41
41
|
replacements = opts['maql_replacements'] || opts[:maql_replacements] || {}
|
42
|
+
update_preference = opts[:update_preference]
|
43
|
+
exist_fallback_to_hard_sync_config = !update_preference.nil? && !update_preference[:fallback_to_hard_sync].nil?
|
44
|
+
include_maql_fallback_hard_sync = exist_fallback_to_hard_sync_config && GoodData::Helpers.to_boolean(update_preference[:fallback_to_hard_sync])
|
42
45
|
|
43
46
|
_, project = GoodData.get_client_and_project(opts)
|
44
47
|
|
@@ -48,6 +51,7 @@ module GoodData
|
|
48
51
|
maql_diff_params = [:includeGrain]
|
49
52
|
maql_diff_params << :excludeFactRule if opts[:exclude_fact_rule]
|
50
53
|
maql_diff_params << :includeDeprecated if opts[:include_deprecated]
|
54
|
+
maql_diff_params << :includeMaqlFallbackHardSync if include_maql_fallback_hard_sync
|
51
55
|
|
52
56
|
maql_diff_time = Benchmark.realtime do
|
53
57
|
response = project.maql_diff(blueprint: bp, params: maql_diff_params)
|
@@ -62,7 +66,7 @@ module GoodData
|
|
62
66
|
ca_maql = response['projectModelDiff']['computedAttributesScript'] if response['projectModelDiff']['computedAttributesScript']
|
63
67
|
ca_chunks = ca_maql && ca_maql['maqlDdlChunks']
|
64
68
|
|
65
|
-
maqls = pick_correct_chunks(chunks, opts)
|
69
|
+
maqls = include_maql_fallback_hard_sync ? pick_correct_chunks_hard_sync(chunks, opts) : pick_correct_chunks(chunks, opts)
|
66
70
|
replaced_maqls = apply_replacements_on_maql(maqls, replacements)
|
67
71
|
apply_maqls(ca_chunks, project, replaced_maqls, opts) unless dry_run
|
68
72
|
[replaced_maqls, ca_maql]
|
@@ -72,9 +76,11 @@ module GoodData
|
|
72
76
|
errors = []
|
73
77
|
replaced_maqls.each do |replaced_maql_chunks|
|
74
78
|
begin
|
79
|
+
fallback_hard_sync = replaced_maql_chunks['updateScript']['fallbackHardSync'].nil? ? false : replaced_maql_chunks['updateScript']['fallbackHardSync']
|
75
80
|
replaced_maql_chunks['updateScript']['maqlDdlChunks'].each do |chunk|
|
76
81
|
GoodData.logger.debug(chunk)
|
77
|
-
project.execute_maql(chunk)
|
82
|
+
execute_maql_result = project.execute_maql(chunk)
|
83
|
+
process_fallback_hard_sync_result(execute_maql_result, project) if fallback_hard_sync
|
78
84
|
end
|
79
85
|
rescue => e
|
80
86
|
GoodData.logger.error("Error occured when executing MAQL, project: \"#{project.title}\" reason: \"#{e.message}\", chunks: #{replaced_maql_chunks.inspect}")
|
@@ -140,8 +146,8 @@ module GoodData
|
|
140
146
|
preference = Hash[preference.map { |k, v| [k, GoodData::Helpers.to_boolean(v)] }]
|
141
147
|
|
142
148
|
# will use new parameters instead of the old ones
|
143
|
-
if preference.empty? || [
|
144
|
-
if [
|
149
|
+
if preference.empty? || %i[allow_cascade_drops keep_data].any? { |k| preference.key?(k) }
|
150
|
+
if %i[cascade_drops preserve_data].any? { |k| preference.key?(k) }
|
145
151
|
fail "Please do not mix old parameters (:cascade_drops, :preserve_data) with the new ones (:allow_cascade_drops, :keep_data)."
|
146
152
|
end
|
147
153
|
preference = { allow_cascade_drops: false, keep_data: true }.merge(preference)
|
@@ -174,8 +180,8 @@ module GoodData
|
|
174
180
|
results_from_api = GoodData::Helpers.join(
|
175
181
|
rules,
|
176
182
|
stuff,
|
177
|
-
[
|
178
|
-
[
|
183
|
+
%i[cascade_drops preserve_data],
|
184
|
+
%i[cascade_drops preserve_data],
|
179
185
|
inner: true
|
180
186
|
).sort_by { |l| l[:priority] } || []
|
181
187
|
|
@@ -204,6 +210,53 @@ module GoodData
|
|
204
210
|
end
|
205
211
|
end
|
206
212
|
|
213
|
+
def pick_correct_chunks_hard_sync(chunks, opts = {})
|
214
|
+
preference = GoodData::Helpers.symbolize_keys(opts[:update_preference] || {})
|
215
|
+
preference = Hash[preference.map { |k, v| [k, GoodData::Helpers.to_boolean(v)] }]
|
216
|
+
|
217
|
+
# Old configure using cascade_drops and preserve_data parameters. New configure using allow_cascade_drops and
|
218
|
+
# keep_data parameters. Need translate from new configure to old configure before processing
|
219
|
+
if preference.empty? || %i[allow_cascade_drops keep_data].any? { |k| preference.key?(k) }
|
220
|
+
if %i[cascade_drops preserve_data].any? { |k| preference.key?(k) }
|
221
|
+
fail "Please do not mix old parameters (:cascade_drops, :preserve_data) with the new ones (:allow_cascade_drops, :keep_data)."
|
222
|
+
end
|
223
|
+
|
224
|
+
# Default allow_cascade_drops=false and keep_data=true
|
225
|
+
preference = { allow_cascade_drops: false, keep_data: true }.merge(preference)
|
226
|
+
|
227
|
+
new_preference = {}
|
228
|
+
new_preference[:cascade_drops] = preference[:allow_cascade_drops]
|
229
|
+
new_preference[:preserve_data] = preference[:keep_data]
|
230
|
+
preference = new_preference
|
231
|
+
end
|
232
|
+
preference[:fallback_to_hard_sync] = true
|
233
|
+
|
234
|
+
# Filter chunk with fallbackHardSync = true
|
235
|
+
result = chunks.select do |chunk|
|
236
|
+
chunk['updateScript']['maqlDdlChunks'] && !chunk['updateScript']['fallbackHardSync'].nil? && chunk['updateScript']['fallbackHardSync']
|
237
|
+
end
|
238
|
+
|
239
|
+
# The API model/diff only returns one result for MAQL fallback hard synchronize
|
240
|
+
result = pick_chunks_hard_sync(result[0], preference) if !result.nil? && !result.empty?
|
241
|
+
|
242
|
+
if result.nil? || result.empty?
|
243
|
+
available_chunks = chunks
|
244
|
+
.map do |chunk|
|
245
|
+
{
|
246
|
+
cascade_drops: chunk['updateScript']['cascadeDrops'],
|
247
|
+
preserve_data: chunk['updateScript']['preserveData'],
|
248
|
+
fallback_hard_sync: chunk['updateScript']['fallbackHardSync'].nil? ? false : chunk['updateScript']['fallbackHardSync']
|
249
|
+
}
|
250
|
+
end
|
251
|
+
.map(&:to_s)
|
252
|
+
.join(', ')
|
253
|
+
|
254
|
+
fail "Synchronize LDM cannot proceed. Adjust your update_preferences and try again. Available chunks with preference: #{available_chunks}"
|
255
|
+
end
|
256
|
+
|
257
|
+
result
|
258
|
+
end
|
259
|
+
|
207
260
|
private
|
208
261
|
|
209
262
|
def apply_replacements_on_maql(maqls, replacements = {})
|
@@ -215,6 +268,30 @@ module GoodData
|
|
215
268
|
end
|
216
269
|
end
|
217
270
|
end
|
271
|
+
|
272
|
+
# Fallback hard synchronize although execute result success but some cases there are errors during executing.
|
273
|
+
# In this cases, then export the errors to execution log as warning
|
274
|
+
def process_fallback_hard_sync_result(result, project)
|
275
|
+
messages = result['wTaskStatus']['messages']
|
276
|
+
if !messages.nil? && messages.size.positive?
|
277
|
+
warning_message = GoodData::Helpers.interpolate_error_messages(messages)
|
278
|
+
log_message = "Project #{project.pid} failed to preserve data, truncated data of some datasets. MAQL diff execution messages: \"#{warning_message}\""
|
279
|
+
GoodData.logger.warn(log_message)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# In case fallback hard synchronize, then the API model/diff only returns one result with preserve_data is always false and
|
284
|
+
# cascade_drops is true or false. So pick chunk for fallback hard synchronize, we will ignore the preserve_data parameter
|
285
|
+
# and only check the cascade_drops parameter in preference.
|
286
|
+
def pick_chunks_hard_sync(chunk, preference)
|
287
|
+
# Make sure default values for cascade_drops
|
288
|
+
working_preference = { cascade_drops: false }.merge(preference)
|
289
|
+
if working_preference[:cascade_drops] || chunk['updateScript']['cascadeDrops'] == working_preference[:cascade_drops]
|
290
|
+
[chunk]
|
291
|
+
else
|
292
|
+
[]
|
293
|
+
end
|
294
|
+
end
|
218
295
|
end
|
219
296
|
end
|
220
297
|
end
|
@@ -257,7 +257,8 @@ module GoodData
|
|
257
257
|
res = client.poll_on_code(res['asyncTask']['links']['poll'])
|
258
258
|
failed_count = GoodData::Helpers.get_path(res, %w(clientProjectProvisioningResult failed count), 0)
|
259
259
|
created_count = GoodData::Helpers.get_path(res, %w(clientProjectProvisioningResult created count), 0)
|
260
|
-
return
|
260
|
+
return [].to_enum if (failed_count + created_count).zero?
|
261
|
+
|
261
262
|
Enumerator.new do |y|
|
262
263
|
uri = GoodData::Helpers.get_path(res, %w(clientProjectProvisioningResult links details))
|
263
264
|
loop do
|
@@ -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
|
@@ -210,13 +228,23 @@ module GoodData
|
|
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")
|
@@ -499,7 +588,7 @@ module GoodData
|
|
499
588
|
# @param file [String | Array] File or array of values to be parsed for filters
|
500
589
|
# @param options [Hash] Filter definitions
|
501
590
|
# @return [Array<Hash>]
|
502
|
-
def self.get_values(file, options)
|
591
|
+
def self.get_values(file, options = {})
|
503
592
|
file.is_a?(Array) ? read_array(file, options) : read_file(file, options)
|
504
593
|
end
|
505
594
|
|
@@ -584,12 +673,12 @@ module GoodData
|
|
584
673
|
# Removes MUFs from to_delete unless in user is in users_brick_input
|
585
674
|
# if this does not happen, users that are about to be deleted by users_brick
|
586
675
|
# would have all their filters removed now, which is not desirable
|
587
|
-
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)
|
588
677
|
return [] unless users_brick_input && users_brick_input.any?
|
589
678
|
user_profiles = users_brick_input.map do |user|
|
590
|
-
result =
|
679
|
+
result = user_profile_mapping[user.with_indifferent_access['login']]
|
591
680
|
next unless result
|
592
|
-
result
|
681
|
+
result
|
593
682
|
end.compact
|
594
683
|
return [] unless user_profiles.any?
|
595
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
@@ -83,6 +83,7 @@ module GoodData
|
|
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
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}],
|
86
87
|
['/gdc/md/{id}/variables/item/{id}', %r{/gdc/md/[^\/]+/variables/item/[\d]+}],
|
87
88
|
['/gdc/md/{id}/validate/task/{id}', %r{/gdc/md/[^\/]+/validate/task/[^\/]+}],
|
88
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'
|