gooddata 2.1.19-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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gdc-ii-config.yaml +42 -1
  3. data/.github/workflows/build.yml +67 -0
  4. data/.github/workflows/pre-merge.yml +72 -0
  5. data/.pronto.yml +1 -0
  6. data/.rubocop.yml +2 -14
  7. data/CHANGELOG.md +47 -0
  8. data/Dockerfile +27 -14
  9. data/Dockerfile.jruby +5 -15
  10. data/Dockerfile.ruby +5 -7
  11. data/Gemfile +4 -2
  12. data/README.md +6 -6
  13. data/Rakefile +1 -1
  14. data/SDK_VERSION +1 -1
  15. data/VERSION +1 -1
  16. data/bin/run_brick.rb +7 -0
  17. data/ci/mssql/pom.xml +62 -0
  18. data/ci/mysql/pom.xml +62 -0
  19. data/ci/redshift/pom.xml +4 -5
  20. data/docker-compose.lcm.yml +42 -4
  21. data/docker-compose.yml +42 -0
  22. data/gooddata.gemspec +21 -21
  23. data/k8s/charts/lcm-bricks/Chart.yaml +1 -1
  24. data/lcm.rake +11 -8
  25. data/lib/gooddata/bricks/base_pipeline.rb +26 -0
  26. data/lib/gooddata/bricks/brick.rb +0 -1
  27. data/lib/gooddata/bricks/middleware/aws_middleware.rb +35 -9
  28. data/lib/gooddata/bricks/middleware/execution_result_middleware.rb +3 -3
  29. data/lib/gooddata/bricks/pipeline.rb +2 -14
  30. data/lib/gooddata/cloud_resources/blobstorage/blobstorage_client.rb +98 -0
  31. data/lib/gooddata/cloud_resources/mssql/drivers/.gitkeepme +0 -0
  32. data/lib/gooddata/cloud_resources/mssql/mssql_client.rb +122 -0
  33. data/lib/gooddata/cloud_resources/mysql/drivers/.gitkeepme +0 -0
  34. data/lib/gooddata/cloud_resources/mysql/mysql_client.rb +121 -0
  35. data/lib/gooddata/cloud_resources/postgresql/postgresql_client.rb +0 -1
  36. data/lib/gooddata/cloud_resources/redshift/drivers/.gitkeepme +0 -0
  37. data/lib/gooddata/cloud_resources/redshift/redshift_client.rb +0 -2
  38. data/lib/gooddata/cloud_resources/snowflake/snowflake_client.rb +18 -1
  39. data/lib/gooddata/helpers/data_helper.rb +9 -4
  40. data/lib/gooddata/lcm/actions/base_action.rb +157 -0
  41. data/lib/gooddata/lcm/actions/collect_data_product.rb +2 -1
  42. data/lib/gooddata/lcm/actions/collect_meta.rb +3 -1
  43. data/lib/gooddata/lcm/actions/collect_projects_warning_status.rb +53 -0
  44. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +14 -0
  45. data/lib/gooddata/lcm/actions/initialize_continue_on_error_option.rb +87 -0
  46. data/lib/gooddata/lcm/actions/migrate_gdc_date_dimension.rb +31 -4
  47. data/lib/gooddata/lcm/actions/provision_clients.rb +34 -5
  48. data/lib/gooddata/lcm/actions/synchronize_cas.rb +24 -4
  49. data/lib/gooddata/lcm/actions/synchronize_clients.rb +112 -11
  50. data/lib/gooddata/lcm/actions/synchronize_dataset_mappings.rb +89 -0
  51. data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +48 -11
  52. data/lib/gooddata/lcm/actions/synchronize_kd_dashboard_permission.rb +103 -0
  53. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +79 -23
  54. data/lib/gooddata/lcm/actions/synchronize_ldm_layout.rb +98 -0
  55. data/lib/gooddata/lcm/actions/synchronize_pp_dashboard_permission.rb +108 -0
  56. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +31 -1
  57. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +26 -18
  58. data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +30 -4
  59. data/lib/gooddata/lcm/actions/synchronize_users.rb +11 -10
  60. data/lib/gooddata/lcm/actions/update_metric_formats.rb +202 -0
  61. data/lib/gooddata/lcm/data/delete_from_lcm_release.sql.erb +5 -0
  62. data/lib/gooddata/lcm/exceptions/lcm_execution_warning.rb +15 -0
  63. data/lib/gooddata/lcm/helpers/check_helper.rb +19 -0
  64. data/lib/gooddata/lcm/helpers/release_table_helper.rb +42 -8
  65. data/lib/gooddata/lcm/lcm2.rb +50 -4
  66. data/lib/gooddata/lcm/user_bricks_helper.rb +9 -0
  67. data/lib/gooddata/mixins/inspector.rb +1 -1
  68. data/lib/gooddata/mixins/md_object_query.rb +1 -0
  69. data/lib/gooddata/models/data_source.rb +5 -1
  70. data/lib/gooddata/models/dataset_mapping.rb +36 -0
  71. data/lib/gooddata/models/ldm_layout.rb +38 -0
  72. data/lib/gooddata/models/metadata/label.rb +26 -27
  73. data/lib/gooddata/models/project.rb +230 -30
  74. data/lib/gooddata/models/project_creator.rb +83 -6
  75. data/lib/gooddata/models/schedule.rb +13 -1
  76. data/lib/gooddata/models/segment.rb +2 -1
  77. data/lib/gooddata/models/user_filters/user_filter_builder.rb +162 -68
  78. data/lib/gooddata/rest/connection.rb +5 -3
  79. data/lib/gooddata/rest/phmap.rb +2 -0
  80. data/lib/gooddata.rb +1 -0
  81. data/lib/gooddata_brick_base.rb +35 -0
  82. data/sonar-project.properties +6 -0
  83. metadata +96 -65
  84. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +0 -37
  85. data/lib/gooddata/cloud_resources/redshift/drivers/log4j.properties +0 -15
@@ -17,6 +17,7 @@ require_relative 'actions/actions'
17
17
  require_relative 'dsl/dsl'
18
18
  require_relative 'helpers/helpers'
19
19
  require_relative 'exceptions/lcm_execution_error'
20
+ require_relative 'exceptions/lcm_execution_warning'
20
21
 
21
22
  using TrueExtensions
22
23
  using FalseExtensions
@@ -96,10 +97,14 @@ module GoodData
96
97
  CollectComputedAttributeMetrics,
97
98
  ImportObjectCollections,
98
99
  SynchronizeComputedAttributes,
100
+ SynchronizeDataSetMapping,
101
+ SynchronizeLdmLayout,
99
102
  SynchronizeProcesses,
100
103
  SynchronizeSchedules,
101
104
  SynchronizeColorPalette,
102
105
  SynchronizeUserGroups,
106
+ SynchronizePPDashboardPermissions,
107
+ SynchronizeKDDashboardPermissions,
103
108
  SynchronizeNewSegments,
104
109
  UpdateReleaseTable
105
110
  ],
@@ -121,11 +126,19 @@ module GoodData
121
126
  CollectClients,
122
127
  AssociateClients,
123
128
  RenameExistingClientProjects,
129
+ InitializeContinueOnErrorOption,
124
130
  ProvisionClients,
131
+ UpdateMetricFormats,
125
132
  EnsureTechnicalUsersDomain,
126
133
  EnsureTechnicalUsersProject,
127
134
  CollectDymanicScheduleParams,
128
- SynchronizeETLsInSegment
135
+ SynchronizeDataSetMapping,
136
+ SynchronizeLdmLayout,
137
+ SynchronizeUserGroups,
138
+ SynchronizePPDashboardPermissions,
139
+ SynchronizeKDDashboardPermissions,
140
+ SynchronizeETLsInSegment,
141
+ CollectProjectsWarningStatus
129
142
  ],
130
143
 
131
144
  rollout: [
@@ -135,12 +148,20 @@ module GoodData
135
148
  CollectSegmentClients,
136
149
  EnsureTechnicalUsersDomain,
137
150
  EnsureTechnicalUsersProject,
151
+ InitializeContinueOnErrorOption,
138
152
  SynchronizeLdm,
153
+ SynchronizeDataSetMapping,
154
+ SynchronizeLdmLayout,
139
155
  MigrateGdcDateDimension,
140
156
  SynchronizeClients,
157
+ SynchronizeUserGroups,
158
+ SynchronizePPDashboardPermissions,
159
+ SynchronizeKDDashboardPermissions,
160
+ UpdateMetricFormats,
141
161
  SynchronizeComputedAttributes,
142
162
  CollectDymanicScheduleParams,
143
- SynchronizeETLsInSegment
163
+ SynchronizeETLsInSegment,
164
+ CollectProjectsWarningStatus
144
165
  ],
145
166
 
146
167
  users: [
@@ -335,7 +356,7 @@ module GoodData
335
356
  # Invoke action
336
357
  begin
337
358
  out = run_action action, params
338
- rescue Exception => e # rubocop:disable RescueException
359
+ rescue Exception => e # rubocop:disable Style/RescueException
339
360
  errors << {
340
361
  action: action,
341
362
  err: e,
@@ -357,7 +378,7 @@ module GoodData
357
378
  params.merge!(new_params)
358
379
 
359
380
  # Print action result
360
- print_action_result(action, res)
381
+ print_action_result(action, res) if action.send(:print_result, params)
361
382
 
362
383
  # Store result for final summary
363
384
  results << res
@@ -384,9 +405,28 @@ module GoodData
384
405
  end
385
406
  end
386
407
 
408
+ process_sync_failed_projects(params) if GoodData::LCM2::Helpers.collect_synced_status(params) && strict_mode
409
+
387
410
  result
388
411
  end
389
412
 
413
+ def process_sync_failed_projects(params)
414
+ sync_failed_list = params[:sync_failed_list]
415
+ sync_project_list = sync_failed_list[:project_client_mappings]
416
+ sync_failed_project_list = sync_failed_list[:failed_detailed_projects]
417
+
418
+ if sync_project_list && sync_failed_project_list && sync_project_list.size.positive? && sync_failed_project_list.size.positive?
419
+ failed_project = sync_failed_project_list[0]
420
+ summary_message = "Existing errors during execution. See log for details"
421
+ error_message = failed_project[:message]
422
+ if sync_project_list.size == sync_failed_project_list.size
423
+ raise GoodData::LcmExecutionError.new(summary_message, error_message)
424
+ else
425
+ raise GoodData::LcmExecutionWarning.new(summary_message, error_message)
426
+ end
427
+ end
428
+ end
429
+
390
430
  def run_action(action, params)
391
431
  begin
392
432
  GoodData.gd_logger.start_action action, GoodData.gd_logger
@@ -396,6 +436,12 @@ module GoodData
396
436
  BaseAction.check_params(action.const_get('PARAMS'), params)
397
437
  params.setup_filters(action.const_get('PARAMS'))
398
438
  out = action.send(:call, params)
439
+ rescue Exception => e # rubocop:disable Style/RescueException
440
+ # Log to splunk
441
+ GoodData.gd_logger.error("action=#{action} status=failed message=#{e} exception=#{e.backtrace}")
442
+ # Log to execution log
443
+ GoodData.logger.error("Execution #{action} failed. Error: #{e}. Detail:#{e.backtrace}")
444
+ raise e
399
445
  ensure
400
446
  params.clear_filters
401
447
  GoodData.gd_logger.end_action GoodData.gd_logger
@@ -26,6 +26,15 @@ module GoodData
26
26
 
27
27
  goodot_id.empty? ? client.id : goodot_id
28
28
  end
29
+
30
+ def non_working_clients(domain_clients, working_client_ids)
31
+ non_working_clients = []
32
+ domain_clients.each do |c|
33
+ non_working_clients << c unless working_client_ids.include?(c.client_id.to_s)
34
+ end
35
+
36
+ non_working_clients
37
+ end
29
38
  end
30
39
  end
31
40
  end
@@ -10,7 +10,7 @@ module GoodData
10
10
  module Mixin
11
11
  # When an RSpec test like this fails,
12
12
  #
13
- # @my_array.should == [@some_model, @some_model2]
13
+ # expect(@my_array).to == [@some_model, @some_model2]
14
14
  #
15
15
  # RSpec will call inspect on each of the objects to "help" you figure out
16
16
  # what went wrong. Well, inspect will usually dump a TON OF SHIT and make trying
@@ -54,6 +54,7 @@ module GoodData
54
54
  y << (klass ? client.create(klass, item, project: project) : item)
55
55
  end
56
56
  break if result['objects']['paging']['count'] < page_limit
57
+
57
58
  offset += page_limit
58
59
  end
59
60
  end
@@ -34,7 +34,7 @@ module GoodData
34
34
  c.create(DataSource, ds_data)
35
35
  end
36
36
  else
37
- c.create(DataSource, c.get("#{DATA_SOURCES_URL}/#{id}"))
37
+ c.create(DataSource, c.get(DATA_SOURCES_URL + '/' + id))
38
38
  end
39
39
  end
40
40
 
@@ -177,6 +177,10 @@ module GoodData
177
177
  @json['dataSource']['connectionInfo'][type]
178
178
  end
179
179
 
180
+ def type
181
+ @json['dataSource']['connectionInfo'].first[0].upcase
182
+ end
183
+
180
184
  private
181
185
 
182
186
  def build_connection_info
@@ -0,0 +1,36 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+ #
4
+ # Copyright (c) 2010-2021 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
+ module GoodData
9
+ class DatasetMapping
10
+ DATASET_MAPPING_GET_URI = '/gdc/dataload/projects/%<project_id>s/modelMapping/datasets'
11
+ DATASET_MAPPING_UPDATE_URI = '/gdc/dataload/projects/%<project_id>s/modelMapping/datasets/bulk/upsert'
12
+
13
+ class << self
14
+ def [](opts = { :client => GoodData.connection, :project => GoodData.project })
15
+ client, project = GoodData.get_client_and_project(opts)
16
+ get_uri = DATASET_MAPPING_GET_URI % { project_id: project.pid }
17
+ res = client.get(get_uri)
18
+ res
19
+ end
20
+
21
+ alias_method :get, :[]
22
+ end
23
+
24
+ def initialize(data)
25
+ @data = data
26
+ end
27
+
28
+ def save(opts)
29
+ client, project = GoodData.get_client_and_project(opts)
30
+
31
+ post_uri = DATASET_MAPPING_UPDATE_URI % { project_id: project.pid }
32
+ res = client.post(post_uri, @data, opts)
33
+ res
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+ #
4
+ # Copyright (c) 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
+ module GoodData
9
+ class LdmLayout
10
+ DEFAULT_EMPTY_LDM_LAYOUT = {
11
+ "ldmLayout" => {
12
+ "layout" => []
13
+ }
14
+ }
15
+
16
+ LDM_LAYOUT_URI = '/gdc/dataload/internal/projects/%<project_id>s/ldmLayout'
17
+
18
+ class << self
19
+ def get(opts = { :client => GoodData.connection, :project => GoodData.project })
20
+ client, project = GoodData.get_client_and_project(opts)
21
+ get_uri = LDM_LAYOUT_URI % { project_id: project.pid }
22
+
23
+ client.get(get_uri)
24
+ end
25
+ end
26
+
27
+ def initialize(data)
28
+ @data = data
29
+ end
30
+
31
+ def save(opts)
32
+ client, project = GoodData.get_client_and_project(opts)
33
+ post_uri = LDM_LAYOUT_URI % { project_id: project.pid }
34
+
35
+ client.post(post_uri, @data, opts)
36
+ end
37
+ end
38
+ end
@@ -40,22 +40,20 @@ module GoodData
40
40
  end
41
41
  end
42
42
 
43
- # Gets valid elements using /validElements? API
43
+ # Gets valid elements of a label for a specific paging (:offset and :limit) or get validElements of a specific value (:filter).
44
+ # In the case filter a specific value, because the API /validElements only filter by partial match, we need to filter again at client side for exact match.
44
45
  # @return [Array] Results
45
46
  def get_valid_elements(*args)
46
- results, params = valid_elements(*args)
47
- # TMA-775 - the validElements API can possibly return more matches than requested (usually 1)
48
- # so we do a preliminary first request to check and then increase the limit if needed
49
- if results['validElements']['paging']['total'].to_i != params[:limit]
47
+ if args && !args.empty? && args.first[:filter]
48
+ params = args.first
50
49
  params[:limit] = 100_000
51
50
  results, = valid_elements params
52
- if params[:filter]
53
- results['validElements']['items'] = results['validElements']['items'].reject do |i|
54
- i['element']['title'] != params[:filter]
55
- end
51
+ results['validElements']['items'] = results['validElements']['items'].select do |i|
52
+ i['element']['title'] == params[:filter]
56
53
  end
54
+ else
55
+ results, = valid_elements(*args)
57
56
  end
58
-
59
57
  results
60
58
  end
61
59
 
@@ -74,24 +72,25 @@ module GoodData
74
72
  # @option options [Number] :limit limits the number of values to certain number. Default is 100
75
73
  # @return [Array]
76
74
  def values(options = {})
77
- Enumerator.new do |y|
78
- offset = options[:offset] || 0
79
- page_limit = options[:limit] || 100
80
- loop do
81
- results = get_valid_elements(limit: page_limit, offset: offset)
82
-
83
- elements = results['validElements']
84
- elements['items'].map do |el|
85
- v = el['element']
86
- y << {
87
- :value => v['title'],
88
- :uri => v['uri']
89
- }
90
- end
91
- break if elements['items'].count < page_limit
92
- offset += page_limit
75
+ all_values = []
76
+ offset = options[:offset] || 0
77
+ page_limit = options[:limit] || 100
78
+ loop do
79
+ results = get_valid_elements(limit: page_limit, offset: offset)
80
+
81
+ elements = results['validElements']
82
+ elements['items'].map do |el|
83
+ v = el['element']
84
+ all_values << {
85
+ :value => v['title'],
86
+ :uri => v['uri']
87
+ }
93
88
  end
89
+ break if elements['items'].count < page_limit
90
+
91
+ offset += page_limit
94
92
  end
93
+ all_values
95
94
  end
96
95
 
97
96
  def values_count
@@ -136,7 +135,7 @@ module GoodData
136
135
  if status_url
137
136
  results = client.poll_on_response(status_url) do |body|
138
137
  status = body['taskState'] && body['taskState']['status']
139
- status == 'RUNNING' || status == 'PREPARED'
138
+ status == 'RUNNING' || status == 'PREPARED' || body['uri']
140
139
  end
141
140
  end
142
141