gooddata 1.0.2-java → 1.1.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 (149) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/CONTRIBUTING.md +12 -0
  4. data/README.md +5 -2
  5. data/Rakefile +0 -1
  6. data/dev-gooddata-sso.pub.encrypted +40 -0
  7. data/gooddata.gemspec +3 -3
  8. data/lib/gooddata/connection.rb +23 -13
  9. data/lib/gooddata/helpers/data_helper.rb +0 -1
  10. data/lib/gooddata/lcm/actions/apply_custom_maql.rb +8 -1
  11. data/lib/gooddata/lcm/actions/associate_clients.rb +8 -1
  12. data/lib/gooddata/lcm/actions/base_action.rb +10 -0
  13. data/lib/gooddata/lcm/actions/collect_ca_metrics.rb +7 -1
  14. data/lib/gooddata/lcm/actions/collect_client_projects.rb +3 -0
  15. data/lib/gooddata/lcm/actions/collect_clients.rb +3 -1
  16. data/lib/gooddata/lcm/actions/collect_data_product.rb +10 -2
  17. data/lib/gooddata/lcm/actions/collect_dynamic_schedule_params.rb +12 -1
  18. data/lib/gooddata/lcm/actions/collect_ldm_objects.rb +6 -2
  19. data/lib/gooddata/lcm/actions/collect_meta.rb +1 -1
  20. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +8 -1
  21. data/lib/gooddata/lcm/actions/collect_segments.rb +6 -5
  22. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +1 -1
  23. data/lib/gooddata/lcm/actions/collect_users_brick_users.rb +10 -4
  24. data/lib/gooddata/lcm/actions/create_segment_masters.rb +12 -2
  25. data/lib/gooddata/lcm/actions/ensure_data_product.rb +10 -0
  26. data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +5 -1
  27. data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +3 -0
  28. data/lib/gooddata/lcm/actions/execute_schedules.rb +10 -0
  29. data/lib/gooddata/lcm/actions/import_object_collections.rb +1 -1
  30. data/lib/gooddata/lcm/actions/provision_clients.rb +12 -2
  31. data/lib/gooddata/lcm/actions/purge_clients.rb +2 -0
  32. data/lib/gooddata/lcm/actions/rename_existing_client_projects.rb +3 -0
  33. data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +4 -1
  34. data/lib/gooddata/lcm/actions/synchronize_cas.rb +7 -1
  35. data/lib/gooddata/lcm/actions/synchronize_clients.rb +11 -1
  36. data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +7 -1
  37. data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +12 -7
  38. data/lib/gooddata/lcm/actions/synchronize_label_types.rb +4 -1
  39. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +18 -7
  40. data/lib/gooddata/lcm/actions/synchronize_meta.rb +9 -0
  41. data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +11 -1
  42. data/lib/gooddata/lcm/actions/synchronize_processes.rb +7 -1
  43. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +4 -1
  44. data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +6 -0
  45. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +60 -15
  46. data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +7 -1
  47. data/lib/gooddata/lcm/actions/synchronize_users.rb +106 -3
  48. data/lib/gooddata/lcm/actions/update_release_table.rb +19 -0
  49. data/lib/gooddata/lcm/helpers/check_helper.rb +21 -6
  50. data/lib/gooddata/lcm/lcm2.rb +35 -22
  51. data/lib/gooddata/lcm/types/class/gd_logger.rb +23 -0
  52. data/lib/gooddata/lcm/types/class/gd_product.rb +23 -0
  53. data/lib/gooddata/lcm/types/class/gd_project.rb +23 -0
  54. data/lib/gooddata/lcm/types/class/smart_hash.rb +23 -0
  55. data/lib/gooddata/lcm/types/complex/segment.rb +1 -1
  56. data/lib/gooddata/lcm/types/scalar/integer.rb +2 -2
  57. data/lib/gooddata/lcm/types/special/any.rb +18 -0
  58. data/lib/gooddata/models/blueprint/dataset_blueprint.rb +1 -1
  59. data/lib/gooddata/models/blueprint/to_manifest.rb +1 -3
  60. data/lib/gooddata/models/blueprint/to_wire.rb +2 -1
  61. data/lib/gooddata/models/from_wire.rb +13 -1
  62. data/lib/gooddata/models/metadata/folder.rb +22 -0
  63. data/lib/gooddata/models/metadata/metric.rb +5 -8
  64. data/lib/gooddata/models/model.rb +1 -1
  65. data/lib/gooddata/models/process.rb +42 -32
  66. data/lib/gooddata/models/project.rb +19 -36
  67. data/lib/gooddata/models/project_creator.rb +3 -1
  68. data/lib/gooddata/models/project_role.rb +3 -4
  69. data/lib/gooddata/models/schedule.rb +0 -2
  70. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +9 -1
  71. data/lib/gooddata/models/user_filters/user_filter.rb +1 -2
  72. data/lib/gooddata/models/user_filters/user_filter_builder.rb +18 -6
  73. data/lib/gooddata/rest/client.rb +1 -2
  74. data/lib/gooddata/rest/connection.rb +12 -46
  75. data/lib/gooddata/rest/phmap.rb +101 -56
  76. data/lib/gooddata/version.rb +1 -1
  77. data/rubydev_public.gpg.encrypted +51 -0
  78. data/rubydev_secret_keys.gpg.encrypted +109 -0
  79. data/spec/data/user_filters.csv +2 -0
  80. data/spec/environment/default.rb +2 -2
  81. data/spec/environment/development.rb +1 -1
  82. data/spec/environment/staging.rb +2 -3
  83. data/spec/environment/testing.rb +4 -4
  84. data/spec/integration/connection_spec.rb +37 -0
  85. data/spec/integration/core/connection_spec.rb +1 -1
  86. data/spec/integration/core/logging_spec.rb +8 -6
  87. data/spec/integration/core/project_spec.rb +1 -1
  88. data/spec/integration/mandatory_user_filter_spec.rb +53 -0
  89. data/spec/integration/mixins/id_to_uri_spec.rb +17 -5
  90. data/spec/integration/models/label_spec.rb +9 -0
  91. data/spec/integration/models/metric_spec.rb +24 -0
  92. data/spec/integration/models/process_spec.rb +35 -0
  93. data/spec/integration/models/project_role_spec.rb +1 -1
  94. data/spec/integration/models/schedule_spec.rb +0 -8
  95. data/spec/integration/schedule_spec.rb +4 -6
  96. data/spec/integration/user_filters_spec.rb +20 -16
  97. data/spec/integration/user_group_spec.rb +1 -1
  98. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/can_assign_a_custom_logger.yml +2287 -0
  99. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/client_logs_when_given_custom_message.yml +2287 -0
  100. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/has_the_request_id_logged_when_I_passed_it.yml +2287 -0
  101. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logging_off/Disables_logging.yml +2287 -0
  102. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logging_on/Enables_logging.yml +2287 -0
  103. data/spec/integration/vcr_cassettes/GoodData_-_project/_project/Returns_project_assigned.yml +354 -0
  104. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_nil.yml +299 -0
  105. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_directly.yml +354 -0
  106. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_using_project_ID.yml +354 -0
  107. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_using_project_URL.yml +354 -0
  108. data/spec/integration/vcr_cassettes/GoodData_-_project/_with_project/Uses_project_specified.yml +354 -0
  109. data/spec/integration/vcr_cassettes/GoodData_Metric/all.yml +2065 -0
  110. data/spec/integration/vcr_cassettes/GoodData_Metric/should_be_able_to_update_folders.yml +119 -0
  111. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/all.yml +9812 -0
  112. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_get_json_containing_correct_id.yml +174 -0
  113. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_return_nil_for_unknown_id.yml +58 -0
  114. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_throw_BadRequest_for_-1.yml +63 -0
  115. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_connect/Connects_using_username_and_password.yml +299 -0
  116. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_disconnect/Connects_using_username_and_password.yml +299 -0
  117. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_generate_request_id/Generates_a_non-empty_string.yml +2287 -0
  118. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_/Should_list_user_groups_as_Array.yml +56 -0
  119. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_add_members/Should_add_member.yml +315 -0
  120. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_members/Should_return_members_as_array.yml +54 -0
  121. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_remove_members/Should_remove_existing_members.yml +258 -0
  122. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_save/updates_existing_group.yml +159 -0
  123. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_set_members/Should_set_new_members.yml +158 -0
  124. data/spec/integration/vcr_cassettes/GoodData_UserGroup/all.yml +809 -0
  125. data/spec/spec_helper.rb +46 -2
  126. data/spec/unit/actions/associate_clients_spec.rb +2 -1
  127. data/spec/unit/actions/collect_data_product_spec.rb +3 -1
  128. data/spec/unit/actions/collect_segment_clients_spec.rb +1 -0
  129. data/spec/unit/actions/create_segment_masters_spec.rb +1 -0
  130. data/spec/unit/actions/ensure_data_product_spec.rb +1 -0
  131. data/spec/unit/actions/ensure_technical_users_domain_spec.rb +2 -0
  132. data/spec/unit/actions/ensure_technical_users_project_spec.rb +4 -0
  133. data/spec/unit/actions/provision_clients_spec.rb +2 -1
  134. data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +0 -6
  135. data/spec/unit/actions/synchronize_ldm_spec.rb +20 -7
  136. data/spec/unit/actions/synchronize_user_filters_spec.rb +21 -0
  137. data/spec/unit/helpers/check_helper_production_spec.rb +34 -0
  138. data/spec/unit/helpers/check_helper_spec.rb +97 -9
  139. data/spec/unit/lcm/lcm2_spec.rb +67 -3
  140. data/spec/unit/models/blueprint/to_wire_spec.rb +1 -0
  141. data/spec/unit/models/dataset_blueprint.rb +14 -0
  142. data/spec/unit/models/from_wire_spec.rb +20 -0
  143. data/spec/unit/models/model_spec.rb +10 -0
  144. data/spec/unit/models/to_manifest_spec.rb +29 -0
  145. data/spec/unit/models/user_filters/user_filter_builder_spec.rb +44 -6
  146. data/spec/unit/rest/phmap_spec.rb +117 -0
  147. data/spec/vcr_configurer.rb +63 -0
  148. metadata +283 -24
  149. data/lib/gooddata/lcm/actions/ensure_segments.rb +0 -32
@@ -264,6 +264,9 @@ module GoodData
264
264
  to_process = if process.path
265
265
  to_process.delete if to_process
266
266
  GoodData::Process.deploy_from_appstore(process.path, name: process.name, client: to_project.client, project: to_project)
267
+ elsif process.component
268
+ to_process.delete if to_process
269
+ GoodData::Process.deploy_component(GoodData::Helpers.symbolize_keys(process.to_hash), project: to_project, client: to_project.client)
267
270
  else
268
271
  Dir.mktmpdir('etl_transfer') do |dir|
269
272
  dir = Pathname(dir)
@@ -1172,22 +1175,15 @@ module GoodData
1172
1175
  # @return [String] Returns token that you can use as input for object_import
1173
1176
  def objects_export(objs, options = {})
1174
1177
  fail 'Nothing to migrate. You have to pass list of objects, ids or uris that you would like to migrate' if objs.nil?
1175
- objs = Array(objs)
1178
+ objs = Array(objs).map { |o| o.respond_to?(:uri) ? o.uri : o }
1176
1179
  if objs.empty?
1177
1180
  GoodData.logger.warn 'Nothing to migrate.'
1178
1181
  return
1179
1182
  end
1180
1183
 
1181
- objs = objs.pmap { |obj| [obj, objects(obj)] }
1182
- if objs.any? { |_, obj| obj.nil? }
1183
- object = objs.select { |_, obj| obj.nil? }.map { |o, _| o }.join(', ')
1184
- error_message = "Exporting objects failed with messages. " \
1185
- "Object #{object} could not be found."
1186
- fail ObjectsExportError, error_message
1187
- end
1188
1184
  export_payload = {
1189
1185
  :partialMDExport => {
1190
- :uris => objs.map { |_, obj| obj.uri },
1186
+ :uris => objs,
1191
1187
  :exportAttributeProperties => '1',
1192
1188
  :crossDataCenterExport => '1'
1193
1189
  }
@@ -1259,32 +1255,21 @@ module GoodData
1259
1255
  if projects.is_a?(Array)
1260
1256
  projects.each_slice(batch_size).flat_map do |batch|
1261
1257
  batch.pmap do |proj|
1262
- begin
1263
- target_project = client.projects(proj)
1264
- target_project.objects_import(token, options)
1265
- {
1266
- project: target_project,
1267
- result: true
1268
- }
1269
- rescue RestClient::Exception => e
1270
- {
1271
- project: proj,
1272
- exception: e,
1273
- result: false,
1274
- reason: GoodData::Helpers.interpolate_error_message(MultiJson.load(e.response))
1275
- }
1276
- rescue GoodData::ObjectsImportError => e
1277
- {
1278
- project: target_project,
1279
- result: false,
1280
- reason: e.message
1281
- }
1282
- end
1258
+ target_project = client.projects(proj)
1259
+ target_project.objects_import(token, options)
1260
+ {
1261
+ project: target_project,
1262
+ result: true
1263
+ }
1283
1264
  end
1284
1265
  end
1285
1266
  else
1286
1267
  target_project = client.projects(projects)
1287
1268
  target_project.objects_import(token, options)
1269
+ [{
1270
+ project: target_project,
1271
+ result: true
1272
+ }]
1288
1273
  end
1289
1274
  end
1290
1275
 
@@ -1464,12 +1449,10 @@ module GoodData
1464
1449
  #
1465
1450
  # @return [Array<GoodData::ProjectRole>] List of roles
1466
1451
  def roles
1467
- url = "/gdc/projects/#{pid}/roles"
1468
-
1469
- tmp = client.get(url)
1470
- tmp['projectRoles']['roles'].pmap do |role_url|
1471
- json = client.get role_url
1472
- client.create(GoodData::ProjectRole, json, project: self)
1452
+ url = "/gdc/internal/projects/#{pid}/roles"
1453
+ res = client.get url
1454
+ res['internalProjectRoles']['roles'].map do |r|
1455
+ client.create(GoodData::ProjectRole, r, project: self)
1473
1456
  end
1474
1457
  end
1475
1458
 
@@ -42,7 +42,9 @@ module GoodData
42
42
  _, project = GoodData.get_client_and_project(opts)
43
43
 
44
44
  bp = ProjectBlueprint.new(spec)
45
- response = project.maql_diff(blueprint: bp, params: [:includeGrain])
45
+ maql_diff_params = [:includeGrain]
46
+ maql_diff_params << :excludeFactRule if opts[:exclude_fact_rule]
47
+ response = project.maql_diff(blueprint: bp, params: maql_diff_params)
46
48
 
47
49
  GoodData.logger.debug("projectModelDiff") { response.pretty_inspect }
48
50
  chunks = response['projectModelDiff']['updateScripts']
@@ -33,6 +33,7 @@ module GoodData
33
33
  d[:updated] = data[:updated] || d[:created] || Time.now
34
34
  d[:title] = data[:title]
35
35
  d[:summary] = data[:summary]
36
+ d[:uri] = data[:uri]
36
37
  end
37
38
  new_data = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d|
38
39
  d['projectRole']['links']['self'] = data[:uri] if data[:uri]
@@ -54,7 +55,7 @@ module GoodData
54
55
  #
55
56
  # @return [Array<GoodData::Profile>] List of users
56
57
  def users
57
- url = data['links']['roleUsers']
58
+ url = uri + '/users'
58
59
  tmp = client.get url
59
60
  tmp['associatedUsers']['users'].pmap do |user_url|
60
61
  url = user_url
@@ -67,9 +68,7 @@ module GoodData
67
68
  #
68
69
  # @return [string] URI of this project role
69
70
  def uri
70
- return @json['projectRole']['links']['self'] if @json['projectRole']['links']['self']
71
- return nil unless @json['projectRole']['links']['roleUsers']
72
- @json['projectRole']['links']['roleUsers'].split('/')[0...-1].join('/')
71
+ @json['projectRole']['meta']['uri']
73
72
  end
74
73
 
75
74
  def ==(other)
@@ -77,7 +77,6 @@ module GoodData
77
77
  else
78
78
  fail 'Executable has to be provided' if executable.blank?
79
79
  end
80
- fail 'Trigger schedule has to be provided' if trigger.blank?
81
80
 
82
81
  schedule = c.create(GoodData::Schedule, GoodData::Helpers.stringify_keys(GoodData::Helpers.deep_dup(SCHEDULE_TEMPLATE)), client: c, project: project)
83
82
 
@@ -403,7 +402,6 @@ module GoodData
403
402
  #
404
403
  # @return [Boolean] True if saved
405
404
  def save
406
- fail 'trigger schedule has to be provided' if cron.blank? && trigger_id.blank?
407
405
  fail 'A timezone has to be provided' if timezone.blank?
408
406
  fail 'Schedule type has to be provided' if schedule_type.blank?
409
407
  rewrite_deprecated_params
@@ -28,7 +28,7 @@ module GoodData
28
28
  result = c.get("/gdc/md/#{project.pid}/userfilters?count=#{count}&offset=#{offset}")
29
29
  result['userFilters']['items'].each do |item|
30
30
  item['userFilters'].each do |f|
31
- user_lookup[f] = item['user']
31
+ user_lookup[f] = user_lookup[f] ? Array(user_lookup[f]).concat([item['user']]) : item['user']
32
32
  end
33
33
  end
34
34
  break if result['userFilters']['length'] < offset
@@ -72,5 +72,13 @@ module GoodData
72
72
  res = client.post(project.md['obj'], data)
73
73
  @json[:uri] = res['uri']
74
74
  end
75
+
76
+ def related
77
+ if related_uri.is_a? Array
78
+ related_uri.map { |u| super u }
79
+ else
80
+ super
81
+ end
82
+ end
75
83
  end
76
84
  end
@@ -30,8 +30,7 @@ module GoodData
30
30
  # Returns the the object of this filter is related to. It can be either project or a user
31
31
  #
32
32
  # @return [GoodData::Project | GoodData::Profile] Related object
33
- def related
34
- uri = related_uri
33
+ def related(uri = related_uri)
35
34
  return unless uri
36
35
  level == :project ? client.projects(uri) : client.create(GoodData::Profile, client.get(uri))
37
36
  end
@@ -5,6 +5,7 @@
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
7
  require_relative '../project_log_formatter'
8
+ require 'active_support/core_ext/hash/indifferent_access'
8
9
 
9
10
  module GoodData
10
11
  module UserFilterBuilder
@@ -270,10 +271,10 @@ module GoodData
270
271
  attrs_cache = create_attrs_cache(filters, options)
271
272
  create_filter_proc = proc do |login, f|
272
273
  expression, errors = create_expression(f, labels_cache, lookups_cache, attrs_cache, options)
274
+ safe_login = login.downcase
273
275
  profiles_uri = if options[:type] == :muf
274
276
  project_user = project_users.find { |u| u.login == login }
275
-
276
- project_user.nil? ? ('/gdc/account/profile/' + login) : project_user.profile_url
277
+ project_user.nil? ? ('/gdc/account/profile/' + safe_login) : project_user.profile_url
277
278
  elsif options[:type] == :variable
278
279
  (users_cache[login] && users_cache[login].uri)
279
280
  else
@@ -384,7 +385,14 @@ module GoodData
384
385
  else
385
386
  GoodData.logger.warn("Data permissions computed: #{to_create.count} to create and #{to_delete.count} to delete")
386
387
  end
387
- return { created: to_create, deleted: to_delete } if dry_run
388
+
389
+ if dry_run
390
+ create_results = to_create.map { |x| { status: 'dry_run', user: x.first, type: 'create' } }
391
+ delete_results = to_delete.map { |x| { status: 'dry_run', user: x.first, type: 'delete' } }
392
+ return { created: {},
393
+ deleted: {},
394
+ results: create_results + delete_results }
395
+ end
388
396
 
389
397
  create_results = to_create.each_slice(100).flat_map do |batch|
390
398
  batch.pmapcat do |related_uri, group|
@@ -414,6 +422,8 @@ module GoodData
414
422
  end
415
423
 
416
424
  project_log_formatter.log_user_filter_results(create_results, to_create)
425
+ create_errors = create_results.select { |r| r[:status] == :failed }
426
+ fail "Creating MUFs resulted in errors: #{create_errors}" if create_errors.any?
417
427
 
418
428
  delete_results = unless options[:do_not_touch_filters_that_are_not_mentioned]
419
429
  to_delete.each_slice(100).flat_map do |batch|
@@ -444,6 +454,8 @@ module GoodData
444
454
  end
445
455
 
446
456
  project_log_formatter.log_user_filter_results(delete_results, to_delete)
457
+ delete_errors = delete_results.select { |r| r[:status] == :failed } if delete_results
458
+ fail "Deleting MUFs resulted in errors: #{delete_errors}" if delete_errors && delete_errors.any?
447
459
 
448
460
  { created: to_create, deleted: to_delete, results: create_results + (delete_results || []) }
449
461
  end
@@ -541,13 +553,13 @@ module GoodData
541
553
  # if this does not happen, users that are about to be deleted by users_brick
542
554
  # would have all their filters removed now, which is not desirable
543
555
  def self.sanitize_filters_to_delete(to_delete, users_brick_input, project_users)
544
- return to_delete unless users_brick_input && users_brick_input.any?
556
+ return [] unless users_brick_input && users_brick_input.any?
545
557
  user_profiles = users_brick_input.map do |user|
546
- result = project_users.find { |u| u.login == user['login'] }
558
+ result = project_users.find { |u| u.login == user.with_indifferent_access['login'] }
547
559
  next unless result
548
560
  result.profile_url
549
561
  end.compact
550
- return to_delete unless user_profiles.any?
562
+ return [] unless user_profiles.any?
551
563
  to_delete.reject do |_, value|
552
564
  user_profiles.none? { |profile| profile == value.first.json[:related] }
553
565
  end
@@ -111,8 +111,7 @@ module GoodData
111
111
  end
112
112
 
113
113
  def connect_sso(sso)
114
- client = Client.new(sso)
115
- client
114
+ @@instance = Client.new(sso) # rubocop:disable ClassVars
116
115
  end
117
116
 
118
117
  def disconnect
@@ -17,48 +17,6 @@ require_relative '../helpers/global_helpers'
17
17
 
18
18
  require_relative 'phmap'
19
19
 
20
- module RestClient
21
- module AbstractResponse
22
- alias_method :old_follow_redirection, :follow_redirection
23
- def follow_redirection(request = nil, result = nil, &block)
24
- if RestClient::VERSION != '1.8.0'
25
- fail 'Using monkey patched version of RestClient::AbstractResponse#' \
26
- 'follow_redirection which is guaranteed to be compatible only ' \
27
- 'with RestClient 1.8.0'
28
- end
29
-
30
- new_args = @args.dup
31
-
32
- url = headers[:location]
33
- url = URI.parse(request.url).merge(url).to_s if url !~ /^http/
34
-
35
- new_args[:url] = url
36
- if request
37
- fail MaxRedirectsReached if request.max_redirects.zero?
38
- new_args[:password] = request.password
39
- new_args[:user] = request.user
40
- new_args[:headers] = request.headers
41
- new_args[:max_redirects] = request.max_redirects - 1
42
-
43
- # TODO: figure out what to do with original :cookie, :cookies values
44
- new_args[:cookies] = get_redirection_cookies(request, result, new_args)
45
- end
46
-
47
- Request.execute(new_args, &block)
48
- end
49
-
50
- # Returns cookies which should be passed when following redirect
51
- #
52
- # @param request [RestClient::Request] Original request
53
- # @param result [Net::HTTPResponse] Response
54
- # @param args [Hash] Original arguments
55
- # @return [Hash] Cookies to be passsed when following redirect
56
- def get_redirection_cookies(request, _result, _args)
57
- request.cookies
58
- end
59
- end
60
- end
61
-
62
20
  module GoodData
63
21
  module Rest
64
22
  class RestRetryError < StandardError
@@ -210,13 +168,23 @@ module GoodData
210
168
 
211
169
  # Reset old cookies first
212
170
  if options[:sst_token]
213
- merge_headers!(:x_gdc_authsst => options[:sst_token])
171
+ headers = {
172
+ :x_gdc_authsst => options[:sst_token],
173
+ :x_gdc_authtt => options[:tt_token]
174
+ }
175
+ merge_headers!(headers)
214
176
  get('/gdc/account/token', @request_params)
215
177
 
216
178
  @user = get(get('/gdc/app/account/bootstrap')['bootstrapResource']['accountSetting']['links']['self'])
217
179
  GoodData.logger.info("Connected using SST to server #{@server.url} to profile \"#{@user['accountSetting']['login']}\"")
218
180
  @auth = {}
219
181
  refresh_token :dont_reauth => true
182
+ elsif options[:headers][:x_gdc_authsst]
183
+ @request_params = options[:headers]
184
+ @user = get('/gdc/app/account/bootstrap')['bootstrapResource']
185
+ GoodData.logger.info("Connected using SST to server #{@server.url} to profile \"#{@user['accountSetting']['login']}\"")
186
+ @auth = {}
187
+ refresh_token :dont_reauth => true
220
188
  else
221
189
  GoodData.logger.info("Connected using username \"#{username}\" to server #{@server.url}")
222
190
  credentials = Connection.construct_login_payload(username, password)
@@ -656,9 +624,7 @@ ERR
656
624
  placeholders = true
657
625
 
658
626
  if placeholders
659
- PH_MAP.each do |pm|
660
- break if title.gsub!(pm[1], pm[0])
661
- end
627
+ title = self.class.map_placeholders(title)
662
628
  end
663
629
 
664
630
  stat = stats[title]
@@ -7,74 +7,119 @@
7
7
  module GoodData
8
8
  module Rest
9
9
  class Connection
10
+ def self.map_placeholders(title)
11
+ PH_MAP.each do |pm|
12
+ break if title.gsub!(pm[1], pm[0])
13
+ end
14
+ title
15
+ end
16
+
10
17
  # PH_MAP for wildcarding of URLs in reports
11
18
  PH_MAP = [
12
- ['/gdc/account/profile/{id}', %r{/gdc/account/profile/[\w]+}],
13
- ['/gdc/account/login/{id}', %r{/gdc/account/login/[\w]+}],
14
- ['/gdc/account/domains/{id}/users?login={login}', %r{/gdc/account/domains/[\w\d-]+/users\?login=[^&$]+}],
15
- ['/gdc/account/domains/{id}', %r{/gdc/account/domains/[\w\d-]+}],
19
+ ['/gdc/projects/{id}/execute', %r{/gdc/projects/[^\/]+/execute}],
20
+
21
+ ['/gdc/dataload/projects/{id}/outputStage', %r{/gdc/dataload/projects/[^\/]+/outputStage}],
22
+
23
+ ['/gdc/datawarehouse/instances/{id}', %r{/gdc/datawarehouse/instances/[^\/]+}],
24
+ ['/gdc/datawarehouse/executions/{id}', %r{/gdc/datawarehouse/executions/[^\/]+}],
16
25
 
17
- ['/gdc/projects/{id}/execute', %r{/gdc/projects/[\w]+/execute}],
26
+ # domain dataproducts' clients
27
+ ['/gdc/domains/{id}/dataproducts/{data_product}/clients?segment={segment}',
28
+ %r{\/gdc\/domains\/[^\/]+\/dataproducts\/[^\/]+\/clients\?.*segment=[^\/]+}],
29
+ ['/gdc/domains/{id}/dataproducts/{data_product}/clients/{client}', %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/clients/[^\/]+}],
30
+ ['/gdc/domains/{id}/dataproducts/{data_product}/clients', %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/clients}],
18
31
 
19
- ['/gdc/datawarehouse/instances/{id}', %r{/gdc/datawarehouse/instances/[\w]+}],
20
- ['/gdc/datawarehouse/executions/{id}', %r{/gdc/datawarehouse/executions/[\w]+}],
32
+ # domain dataproducts' segments
33
+ ['/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}',
34
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/segments/[^\/]+/synchronizeClients/results/[^\/]+/details\?offset=[\d]+&limit=[\d]+}],
35
+ ['/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}/synchronizeClients/results/{result}',
36
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/segments/[^\/]+/synchronizeClients/results/[^\/]+}],
37
+ ['/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}', %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/segments/[^\/]+}],
38
+ ['/gdc/domains/{id}/dataproducts/{data_product}/segments', %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/segments}],
21
39
 
40
+ # domain dataproducts' provision & update
41
+ ['/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects/results/{result}/details?offset={offset}&limit={limit}',
42
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/provisionClientProjects/results/[^\/]+/details\?offset=[\d]+&limit=[\d]+}],
43
+ ['/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects/results/{result}',
44
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/provisionClientProjects/results/[^\/]+}],
45
+ ['/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects',
46
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/provisionClientProjects}],
47
+ ['/gdc/domains/{id}/dataproducts/{data_product}/updateClients?deleteExtraInSegments={segments}',
48
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/updateClients\?deleteExtraInSegments=[^\/]+}],
49
+ ['/gdc/domains/{id}/dataproducts/{data_product}/updateClients',
50
+ %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+/updateClients}],
51
+
52
+ # domain dataproduct
53
+ ['/gdc/domains/{id}/dataproducts/{data_product}', %r{/gdc/domains/[^\/]+/dataproducts/[^\/]+}],
54
+ ['/gdc/domains/{id}/dataproducts', %r{/gdc/domains/[^\/]+/dataproducts}],
55
+
56
+ # domain segments
22
57
  ['/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}',
23
- %r{/gdc/domains/[\w-]+/segments/[\w-]+/synchronizeClients/results/[\w]+/details/\?offset=[\d]+&limit=[\d]+}],
58
+ %r{/gdc/domains/[^\/]+/segments/[^\/]+/synchronizeClients/results/[^\/]+/details\?offset=[\d]+&limit=[\d]+}],
24
59
  ['/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}',
25
- %r{/gdc/domains/[\w-]+/segments/[\w-]+/synchronizeClients/results/[\w]+}],
26
- ['/gdc/domains/{id}/segments/{segment}/', %r{/gdc/domains/[\w-]+/segments/[\w-]+/}],
27
- ['/gdc/domains/{id}/segments/{segment}', %r{/gdc/domains/[\w-]+/segments/[\w-]+}],
28
- ['/gdc/domains/{id}/clients?segment={segment}', %r{/gdc/domains/[\w-]+/clients\?segment=[\w-]+}],
29
- ['/gdc/domains/{id}/clients/{client_id}/settings/lcm.title', %r{/gdc/domains/[\w-]+/clients/[\w-]+/settings/lcm.title}],
30
- ['/gdc/domains/{id}/clients/{client_id}/settings/lcm.token', %r{/gdc/domains/[\w-]+/clients/[\w-]+/settings/lcm.token}],
31
- ['/gdc/domains/{id}/clients/{client_id}', %r{/gdc/domains/[\w-]+/clients/[\w-]+}],
60
+ %r{/gdc/domains/[^\/]+/segments/[^\/]+/synchronizeClients/results/[^\/]+}],
61
+ ['/gdc/domains/{id}/segments/{segment}/', %r{/gdc/domains/[^\/]+/segments/[^\/]+/}],
62
+ ['/gdc/domains/{id}/segments/{segment}', %r{/gdc/domains/[^\/]+/segments/[^\/]+}],
63
+
64
+ # domain clients
65
+ ['/gdc/domains/{id}/clients?segment={segment}', %r{/gdc/domains/[^\/]+/clients\?segment=[^\/]+}],
66
+ ['/gdc/domains/{id}/clients/{client_id}/settings/lcm.title', %r{/gdc/domains/[^\/]+/clients/[^\/]+/settings/lcm.title}],
67
+ ['/gdc/domains/{id}/clients/{client_id}/settings/lcm.token', %r{/gdc/domains/[^\/]+/clients/[^\/]+/settings/lcm.token}],
68
+ ['/gdc/domains/{id}/clients/{client_id}', %r{/gdc/domains/[^\/]+/clients/[^\/]+}],
32
69
  ['/gdc/domains/{id}/provisionClientProjects/results/{result}/details?offset={offset}&limit={limit}',
33
- %r{/gdc/domains/[\w-]+/provisionClientProjects/results/[\w]+/details/\?offset=[\d]+&limit=[\d]+}],
34
- ['/gdc/domains/{id}/provisionClientProjects/results/{result}', %r{/gdc/domains/[\w-]+/provisionClientProjects/results/[\w]+}],
35
- ['/gdc/domains/{id}/provisionClientProjects', %r{/gdc/domains/[\w-]+/provisionClientProjects}],
36
- ['/gdc/domains/{id}/updateClients', %r{/gdc/domains/[\w-]+/updateClients}],
37
- ['/gdc/domains/{id}/', %r{/gdc/domains/[\w-]+/}],
70
+ %r{/gdc/domains/[^\/]+/provisionClientProjects/results/[^\/]+/details\?offset=[\d]+&limit=[\d]+}],
71
+ ['/gdc/domains/{id}/provisionClientProjects/results/{result}', %r{/gdc/domains/[^\/]+/provisionClientProjects/results/[^\/]+}],
72
+ ['/gdc/domains/{id}/provisionClientProjects', %r{/gdc/domains/[^\/]+/provisionClientProjects}],
73
+ ['/gdc/domains/{id}/updateClients', %r{/gdc/domains/[^\/]+/updateClients}],
74
+ ['/gdc/domains/{id}/', %r{/gdc/domains/[^\/]+/}],
38
75
 
39
- ['/gdc/exporter/result/{id}/{id}', %r{/gdc/exporter/result/[\w]+/[\w]+}],
76
+ ['/gdc/exporter/result/{id}/{id}', %r{/gdc/exporter/result/[^\/]+/[^\/]+}],
40
77
 
41
78
  ['/gdc/internal/lcm/domains/{id}/dataproducts/{data_product}/segments/{segment}/syncProcesses/{process}',
42
- %r{/gdc/internal/lcm/domains/[\w-]+/dataproducts/[\w-]+/segments/[\w-]+/syncProcesses/[\w]+}],
79
+ %r{/gdc/internal/lcm/domains/[^\/]+/dataproducts/[^\/]+/segments/[^\/]+/syncProcesses/[^\/]+}],
43
80
  ['/gdc/internal/lcm/domains/{id}/dataproducts/{data_product}/segments/{segment}/syncProcesses',
44
- %r{/gdc/internal/lcm/domains/[\w-]+/dataproducts/[\w-]+/segments/[\w-]+/syncProcesses}],
45
-
46
- ['/gdc/internal/projects/{id}/objects/setPermissions', %r{/gdc/internal/projects/[\w]+/objects/setPermissions}],
47
-
48
- ['/gdc/md/{id}/variables/item/{id}', %r{/gdc/md/[\w]+/variables/item/[\d]+}],
49
- ['/gdc/md/{id}/validate/task/{id}', %r{/gdc/md/[\w]+/validate/task/[\w]+}],
50
- ['/gdc/md/{id}/using2/{id}/{id}', %r{/gdc/md/[\w]+/using2/[\d]+/[\d]+}],
51
- ['/gdc/md/{id}/using2/{id}', %r{/gdc/md/[\w]+/using2/[\d]+}],
52
- ['/gdc/md/{id}/userfilters?users={users}', %r{/gdc/md/[\w]+/userfilters\?users=[/\w]+}],
53
- ['/gdc/md/{id}/userfilters?count={count}&offset={offset}', %r{/gdc/md/[\w]+/userfilters\?count=[\d]+&offset=[\d]+}],
54
- ['/gdc/md/{id}/usedby2/{id}/{id}', %r{/gdc/md/[\w]+/usedby2/[\d]+/[\d]+}],
55
- ['/gdc/md/{id}/usedby2/{id}', %r{/gdc/md/[\w]+/usedby2/[\d]+}],
56
- ['/gdc/md/{id}/tasks/{id}/status', %r{/gdc/md/[\w]+/tasks/[\w]+/status}],
57
- ['/gdc/md/{id}/obj/{id}/validElements', %r{/gdc/md/[\w]+/obj/[\d]+/validElements(/)?(\?.*)?}],
58
- ['/gdc/md/{id}/obj/{id}/elements', %r{/gdc/md/[\w]+/obj/[\d]+/elements(/)?(\?.*)?}],
59
- ['/gdc/md/{id}/obj/{id}', %r{/gdc/md/[\w]+/obj/[\d]+}],
60
- ['/gdc/md/{id}/etltask/{id}', %r{/gdc/md/[\w]+/etltask/[\w]+}],
61
- ['/gdc/md/{id}/dataResult/{id}', %r{/gdc/md/[\w]+/dataResult/[\d]+}],
62
- ['/gdc/md/{id}', %r{/gdc/md/[\w]+}],
63
-
64
- ['/gdc/projects/{id}/users/{id}/roles', %r{/gdc/projects/[\w]+/users/[\w]+/roles}],
65
- ['/gdc/projects/{id}/users/{id}/permissions', %r{/gdc/projects/[\w]+/users/[\w]+/permissions}],
66
- ['/gdc/projects/{id}/users', %r{/gdc/projects/[\w]+/users}],
67
- ['/gdc/projects/{id}/schedules/{id}/executions/{id}', %r{/gdc/projects/[\w]+/schedules/[\w]+/executions/[\w]+}],
68
- ['/gdc/projects/{id}/schedules/{id}', %r{/gdc/projects/[\w]+/schedules/[\w]+}],
69
- ['/gdc/projects/{id}/roles/{id}', %r{/gdc/projects/[\w]+/roles/[\d]+}],
70
- ['/gdc/projects/{id}/model/view/{id}', %r{/gdc/projects/[\w]+/model/view/[\w]+}],
71
- ['/gdc/projects/{id}/model/view', %r{/gdc/projects/[\w]+/model/view}],
72
- ['/gdc/projects/{id}/model/diff/{id}', %r{/gdc/projects/[\w]+/model/diff/[\w]+}],
73
- ['/gdc/projects/{id}/model/diff', %r{/gdc/projects/[\w]+/model/diff}],
74
- ['/gdc/projects/{id}/dataload/processes/{id}/executions/{id}', %r{/gdc/projects/[\w]+/dataload/processes/[\w-]+/executions/[\w-]+}],
75
- ['/gdc/projects/{id}/dataload/processes/{id}', %r{/gdc/projects/[\w]+/dataload/processes/[\w-]+}],
76
- ['/gdc/projects/{id}/', %r{/gdc/projects/[\w]+/}],
77
- ['/gdc/projects/{id}', %r{/gdc/projects/[\w]+}]
81
+ %r{/gdc/internal/lcm/domains/[^\/]+/dataproducts/[^\/]+/segments/[^\/]+/syncProcesses}],
82
+
83
+ ['/gdc/internal/projects/{id}/objects/setPermissions', %r{/gdc/internal/projects/[^\/]+/objects/setPermissions}],
84
+
85
+ ['/gdc/md/{id}/variables/item/{id}', %r{/gdc/md/[^\/]+/variables/item/[\d]+}],
86
+ ['/gdc/md/{id}/validate/task/{id}', %r{/gdc/md/[^\/]+/validate/task/[^\/]+}],
87
+ ['/gdc/md/{id}/using2/{id}/{id}', %r{/gdc/md/[^\/]+/using2/[\d]+/[\d]+}],
88
+ ['/gdc/md/{id}/using2/{id}', %r{/gdc/md/[^\/]+/using2/[\d]+}],
89
+ ['/gdc/md/{id}/userfilters?users={users}', %r{\/gdc\/md\/[^\/]+\/userfilters\?users=[\/\w+@.]+}],
90
+ ['/gdc/md/{id}/userfilters?count={count}&offset={offset}', %r{/gdc/md/[^\/]+/userfilters\?count=[\d]+&offset=[\d]+}],
91
+ ['/gdc/md/{id}/usedby2/{id}/{id}', %r{/gdc/md/[^\/]+/usedby2/[\d]+/[\d]+}],
92
+ ['/gdc/md/{id}/usedby2/{id}', %r{/gdc/md/[^\/]+/usedby2/[\d]+}],
93
+ ['/gdc/md/{id}/tasks/{id}/status', %r{/gdc/md/[^\/]+/tasks/[^\/]+/status}],
94
+ ['/gdc/md/{id}/obj/{id}/validElements', %r{/gdc/md/[^\/]+/obj/[\d]+/validElements(/)?(\?.*)?}],
95
+ ['/gdc/md/{id}/obj/{id}/elements', %r{/gdc/md/[^\/]+/obj/[\d]+/elements(/)?(\?.*)?}],
96
+ ['/gdc/md/{id}/obj/{id}', %r{/gdc/md/[^\/]+/obj/[\d]+}],
97
+ ['/gdc/md/{id}/etltask/{id}', %r{/gdc/md/[^\/]+/etltask/[^\/]+}],
98
+ ['/gdc/md/{id}/dataResult/{id}', %r{/gdc/md/[^\/]+/dataResult/[\d]+}],
99
+ ['/gdc/md/{id}', %r{/gdc/md/[^\/]+}],
100
+
101
+ ['/gdc/projects/{id}/users/{id}/roles', %r{/gdc/projects/[^\/]+/users/[^\/]+/roles}],
102
+ ['/gdc/projects/{id}/users/{id}/permissions', %r{/gdc/projects/[^\/]+/users/[^\/]+/permissions}],
103
+ ['/gdc/projects/{id}/users', %r{/gdc/projects/[^\/]+/users}],
104
+ ['/gdc/projects/{id}/schedules/{id}/executions/{id}', %r{/gdc/projects/[^\/]+/schedules/[^\/]+/executions/[^\/]+}],
105
+ ['/gdc/projects/{id}/schedules/{id}', %r{/gdc/projects/[^\/]+/schedules/[^\/]+}],
106
+ ['/gdc/projects/{id}/roles/{id}', %r{/gdc/projects/[^\/]+/roles/[\d]+}],
107
+ ['/gdc/projects/{id}/model/view/{id}', %r{/gdc/projects/[^\/]+/model/view/[^\/]+}],
108
+ ['/gdc/projects/{id}/model/view', %r{/gdc/projects/[^\/]+/model/view}],
109
+ ['/gdc/projects/{id}/model/diff/{id}', %r{/gdc/projects/[^\/]+/model/diff/[^\/]+}],
110
+ ['/gdc/projects/{id}/model/diff', %r{/gdc/projects/[^\/]+/model/diff}],
111
+ ['/gdc/projects/{id}/dataload/metadata/{project}', %r{/gdc/projects/[^\/]+/dataload/metadata/[^\/]+}],
112
+ ['/gdc/projects/{id}/dataload/processes/{id}/executions/{id}', %r{/gdc/projects/[^\/]+/dataload/processes/[^\/]+/executions/[^\/]+}],
113
+ ['/gdc/projects/{id}/dataload/processes/{id}', %r{/gdc/projects/[^\/]+/dataload/processes/[^\/]+}],
114
+ ['/gdc/projects/{id}/', %r{/gdc/projects/[^\/]+/}],
115
+ ['/gdc/projects/{id}', %r{/gdc/projects/[^\/]+}],
116
+
117
+ ['/gdc/userGroups/{id}', %r{/gdc/userGroups/[^\/]+}],
118
+
119
+ ['/gdc/account/profile/{id}', %r{/gdc/account/profile/[^\/]+}],
120
+ ['/gdc/account/login/{id}', %r{/gdc/account/login/[^\/]+}],
121
+ ['/gdc/account/domains/{id}/users?login={login}', %r{/gdc/account/domains/[^\/]+/users\?login=[^&$]+}],
122
+ ['/gdc/account/domains/{id}', %r{/gdc/account/domains/[^\/]+}]
78
123
  ]
79
124
  end
80
125
  end