gooddata 0.6.51 → 0.6.52

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +13 -1
  4. data/CONTRIBUTING.md +25 -0
  5. data/PULL_REQUEST_TEMPLATE.md +5 -0
  6. data/README.md +7 -4
  7. data/gooddata.gemspec +2 -3
  8. data/lib/gooddata.rb +1 -0
  9. data/lib/gooddata/bricks/base_downloader.rb +6 -6
  10. data/lib/gooddata/bricks/middleware/aws_middleware.rb +15 -5
  11. data/lib/gooddata/bricks/middleware/dwh_middleware.rb +15 -3
  12. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +13 -4
  13. data/lib/gooddata/bricks/middleware/logger_middleware.rb +3 -0
  14. data/lib/gooddata/exceptions/no_project_error.rb +5 -1
  15. data/lib/gooddata/goodzilla/goodzilla.rb +7 -6
  16. data/lib/gooddata/helpers/data_helper.rb +4 -4
  17. data/lib/gooddata/helpers/global_helpers_params.rb +61 -39
  18. data/lib/gooddata/lcm/actions/apply_custom_maql.rb +9 -0
  19. data/lib/gooddata/lcm/actions/associate_clients.rb +23 -4
  20. data/lib/gooddata/lcm/actions/collect_attrs.rb +56 -0
  21. data/lib/gooddata/lcm/actions/collect_ca_metrics.rb +53 -0
  22. data/lib/gooddata/lcm/actions/collect_clients.rb +25 -3
  23. data/lib/gooddata/lcm/actions/collect_meta.rb +83 -0
  24. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +12 -4
  25. data/lib/gooddata/lcm/actions/collect_segments.rb +4 -4
  26. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +74 -0
  27. data/lib/gooddata/lcm/actions/create_segment_masters.rb +16 -30
  28. data/lib/gooddata/lcm/actions/ensure_release_table.rb +0 -3
  29. data/lib/gooddata/lcm/actions/ensure_segments.rb +1 -4
  30. data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +5 -5
  31. data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +8 -5
  32. data/lib/gooddata/lcm/actions/hello_world.rb +0 -3
  33. data/lib/gooddata/lcm/actions/import_object_collections.rb +60 -0
  34. data/lib/gooddata/lcm/actions/print_actions.rb +0 -3
  35. data/lib/gooddata/lcm/actions/print_modes.rb +0 -3
  36. data/lib/gooddata/lcm/actions/print_types.rb +1 -4
  37. data/lib/gooddata/lcm/actions/provision_clients.rb +5 -5
  38. data/lib/gooddata/lcm/actions/purge_clients.rb +4 -10
  39. data/lib/gooddata/lcm/actions/segments_filter.rb +0 -6
  40. data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +8 -4
  41. data/lib/gooddata/lcm/actions/synchronize_cas.rb +61 -0
  42. data/lib/gooddata/lcm/actions/synchronize_clients.rb +9 -3
  43. data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +13 -5
  44. data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +71 -17
  45. data/lib/gooddata/lcm/actions/synchronize_label_types.rb +8 -5
  46. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +17 -8
  47. data/lib/gooddata/lcm/actions/synchronize_meta.rb +0 -3
  48. data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +9 -4
  49. data/lib/gooddata/lcm/actions/synchronize_processes.rb +9 -5
  50. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +15 -5
  51. data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +61 -0
  52. data/lib/gooddata/lcm/actions/update_release_table.rb +0 -3
  53. data/lib/gooddata/lcm/helpers/tags_helper.rb +35 -0
  54. data/lib/gooddata/lcm/lcm.rb +22 -4
  55. data/lib/gooddata/lcm/lcm2.rb +66 -13
  56. data/lib/gooddata/lcm/types/complex/update_preference.rb +1 -1
  57. data/lib/gooddata/mixins/md_finders.rb +4 -2
  58. data/lib/gooddata/mixins/md_object_indexer.rb +13 -3
  59. data/lib/gooddata/mixins/md_object_query.rb +8 -2
  60. data/lib/gooddata/models/blueprint/date_dimension.rb +6 -0
  61. data/lib/gooddata/models/blueprint/project_blueprint.rb +41 -11
  62. data/lib/gooddata/models/blueprint/project_builder.rb +20 -0
  63. data/lib/gooddata/models/blueprint/to_wire.rb +7 -0
  64. data/lib/gooddata/models/client.rb +6 -0
  65. data/lib/gooddata/models/domain.rb +6 -6
  66. data/lib/gooddata/models/from_wire.rb +5 -1
  67. data/lib/gooddata/models/metadata.rb +55 -9
  68. data/lib/gooddata/models/metadata/attribute.rb +19 -4
  69. data/lib/gooddata/models/metadata/dashboard.rb +15 -3
  70. data/lib/gooddata/models/metadata/dataset.rb +5 -2
  71. data/lib/gooddata/models/metadata/dimension.rb +4 -1
  72. data/lib/gooddata/models/metadata/fact.rb +9 -2
  73. data/lib/gooddata/models/metadata/folder.rb +4 -1
  74. data/lib/gooddata/models/metadata/metric.rb +11 -3
  75. data/lib/gooddata/models/metadata/report.rb +7 -2
  76. data/lib/gooddata/models/metadata/report_definition.rb +11 -4
  77. data/lib/gooddata/models/metadata/scheduled_mail.rb +4 -1
  78. data/lib/gooddata/models/metadata/variable.rb +7 -2
  79. data/lib/gooddata/models/model.rb +14 -3
  80. data/lib/gooddata/models/process.rb +10 -9
  81. data/lib/gooddata/models/project.rb +134 -36
  82. data/lib/gooddata/models/project_creator.rb +43 -20
  83. data/lib/gooddata/models/report_data_result.rb +6 -2
  84. data/lib/gooddata/models/schedule.rb +6 -3
  85. data/lib/gooddata/models/subscription.rb +8 -1
  86. data/lib/gooddata/models/user_filters/user_filter.rb +1 -0
  87. data/lib/gooddata/models/user_filters/user_filter_builder.rb +18 -4
  88. data/lib/gooddata/models/user_filters/variable_user_filter.rb +3 -1
  89. data/lib/gooddata/rest/client.rb +4 -6
  90. data/lib/gooddata/rest/connection.rb +10 -2
  91. data/lib/gooddata/version.rb +1 -1
  92. data/spec/data/blueprints/test_blueprint.json +1 -0
  93. data/spec/data/wire_models/test_blueprint.json +3 -0
  94. data/spec/data/workspace_table.csv +3 -0
  95. data/spec/environment/development.rb +4 -1
  96. data/spec/environment/environment.rb +1 -1
  97. data/spec/environment/staging.rb +5 -1
  98. data/spec/environment/testing.rb +5 -2
  99. data/spec/integration/blueprint_with_ca_spec.rb +56 -0
  100. data/spec/integration/clients_spec.rb +21 -0
  101. data/spec/integration/command_datawarehouse_spec.rb +7 -1
  102. data/spec/integration/create_from_template_spec.rb +9 -3
  103. data/spec/integration/project_spec.rb +7 -0
  104. data/spec/integration/segments_spec.rb +0 -53
  105. data/spec/integration/subscription_spec.rb +29 -4
  106. data/spec/integration/urn_date_dim_spec.rb +53 -0
  107. data/spec/integration/user_filters_spec.rb +6 -0
  108. data/spec/integration/variables_spec.rb +1 -2
  109. data/spec/spec_helper.rb +5 -30
  110. data/spec/unit/actions/collect_clients_spec.rb +38 -0
  111. data/spec/unit/actions/collect_meta_spec.rb +87 -0
  112. data/spec/unit/actions/collect_segment_clients_spec.rb +40 -0
  113. data/spec/unit/actions/collect_tagged_objects_spec.rb +110 -0
  114. data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +51 -0
  115. data/spec/unit/bricks/middleware/aws_middelware_spec.rb +55 -1
  116. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +15 -0
  117. data/spec/unit/helpers/data_helper_spec.rb +3 -5
  118. data/spec/unit/helpers/global_helpers_spec.rb +29 -0
  119. data/spec/unit/helpers_spec.rb +18 -1
  120. data/spec/unit/models/blueprint/project_blueprint_spec.rb +1 -23
  121. data/spec/unit/models/domain_spec.rb +19 -0
  122. data/spec/unit/models/metadata_spec.rb +34 -0
  123. data/spec/unit/models/schedule_spec.rb +31 -0
  124. data/spec/unit/models/to_manifest_spec.rb +10 -2
  125. data/spec/unit/models/unit_project_spec.rb +6 -1
  126. data/spec/unit/rest/polling_spec.rb +13 -1
  127. metadata +49 -31
@@ -180,7 +180,9 @@ module GoodData
180
180
 
181
181
  # Allows you to test if a report contains a row.
182
182
  #
183
- # @param [Array<String | Number>] row Row that you want to test. It is looking for the whole row. If the headers are getting in the way use #without_left_headers or #without_top_headers
183
+ # @param [Array<String | Number>] row Row that you want to test.
184
+ # It is looking for the whole row. If the headers are getting in the way
185
+ # use #without_left_headers or #without_top_headers
184
186
  # @return [Array] Returns true if data are inside a report
185
187
  def include_row?(row)
186
188
  @data.include?(row)
@@ -188,7 +190,9 @@ module GoodData
188
190
 
189
191
  # Allows you to test if a report contains a column.
190
192
  #
191
- # @param [Array<String | Number>] row Row that you want to test. It is looking for the whole row. If the headers are getting in the way use #without_left_headers or #without_top_headers
193
+ # @param [Array<String | Number>] row Row that you want to test.
194
+ # It is looking for the whole row. If the headers are getting in the way
195
+ # use #without_left_headers or #without_top_headers
192
196
  # @return [Array] Returns true if data are inside a report
193
197
  def include_column?(col)
194
198
  transpose.include_row?(col)
@@ -74,7 +74,6 @@ module GoodData
74
74
  dataload_datasets = '[]' unless dataload_datasets
75
75
 
76
76
  de_synchronize_all = options[:de_synchronize_all] || options['GDC_DE_SYNCHRONIZE_ALL']
77
- de_synchronize_all = 'true' unless de_synchronize_all
78
77
  else
79
78
  fail 'Executable has to be provided' if executable.blank?
80
79
  end
@@ -85,7 +84,7 @@ module GoodData
85
84
  params = { 'PROCESS_ID' => process_id }
86
85
  if is_dataload_process
87
86
  params['GDC_DATALOAD_DATASETS'] = dataload_datasets
88
- params['GDC_DE_SYNCHRONIZE_ALL'] = de_synchronize_all
87
+ params['GDC_DE_SYNCHRONIZE_ALL'] = de_synchronize_all if de_synchronize_all
89
88
  else
90
89
  params['EXECUTABLE'] = executable
91
90
  end
@@ -396,6 +395,10 @@ module GoodData
396
395
  self
397
396
  end
398
397
 
398
+ def rewrite_deprecated_params
399
+ params['EXECUTABLE'] = params.delete('GRAPH') if params['GRAPH']
400
+ end
401
+
399
402
  # Saves object if dirty
400
403
  #
401
404
  # @return [Boolean] True if saved
@@ -403,9 +406,9 @@ module GoodData
403
406
  fail 'trigger schedule has to be provided' if cron.blank? && trigger_id.blank?
404
407
  fail 'A timezone has to be provided' if timezone.blank?
405
408
  fail 'Schedule type has to be provided' if schedule_type.blank?
409
+ rewrite_deprecated_params
406
410
  if @dirty
407
411
  if saved?
408
- puts JSON.pretty_generate(to_update_payload)
409
412
  res = client.put(uri, to_update_payload)
410
413
  @json = Schedule.new(res).json
411
414
  else
@@ -175,7 +175,14 @@ module GoodData
175
175
 
176
176
  def ==(other)
177
177
  return false unless [:project, :title, :process, :channels, :message, :subject, :project_events, :timer_event].all? { |m| other.respond_to?(m) }
178
- @project == other.project && @title == other.title && @process == other.process && @channels == other.channels && @message == other.message && @subject == other.subject && @project_events == other.project_events && @timer_event == other.timer_event
178
+ @project == other.project &&
179
+ @title == other.title &&
180
+ @process == other.process &&
181
+ @channels == other.channels &&
182
+ @message == other.message &&
183
+ @subject == other.subject &&
184
+ @project_events == other.project_events &&
185
+ @timer_event == other.timer_event
179
186
  end
180
187
  end
181
188
  end
@@ -32,6 +32,7 @@ module GoodData
32
32
  # @return [GoodData::Project | GoodData::Profile] Related object
33
33
  def related
34
34
  uri = related_uri
35
+ return unless uri
35
36
  level == :project ? client.projects(uri) : client.create(GoodData::Profile, client.get(uri))
36
37
  end
37
38
 
@@ -130,7 +130,11 @@ module GoodData
130
130
  next true if domain_user
131
131
  false
132
132
  end
133
- fail "#{missing_users.count} users are not part of the project and variable cannot be resolved since :users_must_exist is set to true (#{missing_users.join(', ')})" unless missing_users.empty?
133
+ unless missing_users.empty?
134
+ fail "#{missing_users.count} users are not part of the project and " \
135
+ "variable cannot be resolved since :users_must_exist is set " \
136
+ "to true (#{missing_users.join(', ')})"
137
+ end
134
138
  end
135
139
  end
136
140
 
@@ -280,7 +284,7 @@ module GoodData
280
284
  fail 'Unsuported type in maqlify_filters.'
281
285
  end
282
286
 
283
- if profiles_uri && expression
287
+ if profiles_uri && expression && expression != 'TRUE'
284
288
  [create_user_filter(expression, profiles_uri)] + errors
285
289
  else
286
290
  [] + errors
@@ -376,7 +380,11 @@ module GoodData
376
380
  filters = user_filters.map { |data| client.create(MandatoryUserFilter, data, project: project) }
377
381
  to_create, to_delete = resolve_user_filters(filters, project.data_permissions)
378
382
 
379
- GoodData.logger.warn("Data permissions computed: #{to_create.count} to create and #{to_delete.count} to delete")
383
+ if options[:do_not_touch_filters_that_are_not_mentioned]
384
+ GoodData.logger.warn("Data permissions computed: #{to_create.count} to create")
385
+ else
386
+ GoodData.logger.warn("Data permissions computed: #{to_create.count} to create and #{to_delete.count} to delete")
387
+ end
380
388
  return { created: to_create, deleted: to_delete } if dry_run
381
389
 
382
390
  create_results = to_create.each_slice(100).flat_map do |batch|
@@ -396,7 +404,13 @@ module GoodData
396
404
  res = client.post("/gdc/md/#{project.pid}/userfilters", payload)
397
405
 
398
406
  # turn the errors from hashes into array of hashes
399
- res['userFiltersUpdateResult'].flat_map { |k, v| v.map { |r| { status: k.to_sym, user: r, type: :create } } }.map { |result| result[:status] == :failed ? result.merge(GoodData::Helpers.symbolize_keys(result[:user])) : result }
407
+ update_result = res['userFiltersUpdateResult'].flat_map do |k, v|
408
+ v.map { |r| { status: k.to_sym, user: r, type: :create } }
409
+ end
410
+
411
+ update_result.map do |result|
412
+ result[:status] == :failed ? result.merge(GoodData::Helpers.symbolize_keys(result[:user])) : result
413
+ end
400
414
  end
401
415
  end
402
416
 
@@ -17,7 +17,9 @@ module GoodData
17
17
  self
18
18
  end
19
19
 
20
- # Method used for replacing values in their state according to mapping. Can be used to replace any values but it is typically used to replace the URIs. Returns a new object of the same type.
20
+ # Method used for replacing values in their state according to mapping.
21
+ # Can be used to replace any values but it is typically used to replace
22
+ # the URIs. Returns a new object of the same type.
21
23
  #
22
24
  # @param [Array<Array>]Mapping specifying what should be exchanged for what. As mapping should be used output of GoodData::Helpers.prepare_mapping.
23
25
  # @return [GoodData::VariableUserFilter]
@@ -106,12 +106,6 @@ module GoodData
106
106
  client = Client.new(new_opts)
107
107
  GoodData.logger.info("Connected to server with webdav path #{client.user_webdav_path}")
108
108
 
109
- if client
110
- at_exit do
111
- puts client.connection.stats_table if client && client.connection && (GoodData.stats_on? || client.stats_on?)
112
- end
113
- end
114
-
115
109
  # HACK: This line assigns class instance # if not done yet
116
110
  @@instance = client # rubocop:disable ClassVars
117
111
  end
@@ -197,6 +191,10 @@ module GoodData
197
191
  end
198
192
 
199
193
  def disconnect
194
+ if stats_on?
195
+ puts "API call statistics to server #{@connection.server}"
196
+ puts @connection.stats_table
197
+ end
200
198
  @connection.disconnect
201
199
  end
202
200
 
@@ -19,7 +19,11 @@ module RestClient
19
19
  module AbstractResponse
20
20
  alias_method :old_follow_redirection, :follow_redirection
21
21
  def follow_redirection(request = nil, result = nil, &block)
22
- fail 'Using monkey patched version of RestClient::AbstractResponse#follow_redirection which is guaranteed to be compatible only with RestClient 1.8.0' if RestClient::VERSION != '1.8.0'
22
+ if RestClient::VERSION != '1.8.0'
23
+ fail 'Using monkey patched version of RestClient::AbstractResponse#' \
24
+ 'follow_redirection which is guaranteed to be compatible only ' \
25
+ 'with RestClient 1.8.0'
26
+ end
23
27
 
24
28
  new_args = @args.dup
25
29
 
@@ -508,6 +512,9 @@ module GoodData
508
512
  return e unless e.respond_to?(:response)
509
513
  error = MultiJson.load(e.response)
510
514
  message = GoodData::Helpers.interpolate_error_message(error)
515
+ if error && error['error'] && error['error']['errorClass'] == 'com.gooddata.security.authorization.AuthorizationFailedException'
516
+ message = "#{message}, accessing with #{user['accountSetting']['login']}"
517
+ end
511
518
  <<-ERR
512
519
 
513
520
  #{e}: #{message}
@@ -631,7 +638,8 @@ ERR
631
638
  ['/gdc/datawarehouse/instances/{id}', %r{/gdc/datawarehouse/instances/[\w]+}],
632
639
  ['/gdc/datawarehouse/executions/{id}', %r{/gdc/datawarehouse/executions/[\w]+}],
633
640
 
634
- ['/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}', %r{/gdc/domains/[\w]+/segments/[\w-]+/synchronizeClients/results/[\w]+/details/\?offset=[\d]+&limit=[\d]+}],
641
+ ['/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}',
642
+ %r{/gdc/domains/[\w]+/segments/[\w-]+/synchronizeClients/results/[\w]+/details/\?offset=[\d]+&limit=[\d]+}],
635
643
  ['/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}', %r{/gdc/domains/[\w]+/segments/[\w-]+/synchronizeClients/results/[\w]+}],
636
644
  ['/gdc/domains/{id}/segments/{segment}/', %r{/gdc/domains/[\w]+/segments/[\w-]+/}],
637
645
  ['/gdc/domains/{id}/segments/{segment}', %r{/gdc/domains/[\w]+/segments/[\w-]+}],
@@ -6,7 +6,7 @@
6
6
 
7
7
  # GoodData Module
8
8
  module GoodData
9
- VERSION = '0.6.51'
9
+ VERSION = '0.6.52'
10
10
 
11
11
  class << self
12
12
  # Version
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "title": "Devs module",
3
+ "include_ca": false,
3
4
  "datasets": [
4
5
  {
5
6
  "type": "dataset",
@@ -2,6 +2,9 @@
2
2
  "diffRequest": {
3
3
  "targetModel": {
4
4
  "projectModel": {
5
+ "modelMetadata": {
6
+ "containCA": false
7
+ },
5
8
  "datasets": [
6
9
  {
7
10
  "dataset": {
@@ -0,0 +1,3 @@
1
+ client_id,segment_id,project_title
2
+ client_foo,segment_foo,project_foo
3
+ client_bar,segment_bar,project_bar
@@ -7,7 +7,10 @@
7
7
  module GoodData
8
8
  module Environment
9
9
  module ConnectionHelper
10
- set_const :GD_PROJECT_TOKEN, GoodData::Helpers.decrypt("cfO9ifFYQVJw3q6Kf8/pVf/uLPLGnUJ/9nfvBxeGf/ILoj8N4ymWGgvryWEK\nHDMu\n", ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY'])
10
+ encrypted_token = "cfO9ifFYQVJw3q6Kf8/pVf/uLPLGnUJ/9nfvBxeGf/ILoj8N4ymWGgvryWEK\nHDMu\n"
11
+ key = ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY']
12
+ token = GoodData::Helpers.decrypt(encrypted_token, key)
13
+ set_const :GD_PROJECT_TOKEN, token
11
14
  set_const :DEFAULT_DOMAIN, 'staging3-lcm-prod'
12
15
  set_const :DEFAULT_SERVER, 'https://staging3-lcm-prod.intgdc.com'
13
16
  set_const :DEFAULT_USER_URL, '/gdc/account/profile/a4c644d7b42b65c34e5a0f46809f7164'
@@ -12,7 +12,7 @@ module GoodData
12
12
  hotfix: 'production'
13
13
  }
14
14
 
15
- def load(env = ENV['GD_ENV'] || 'development')
15
+ def load(env = ENV['GD_ENV'] || 'testing')
16
16
  require_relative 'default'
17
17
  env = branch_to_environment(env)
18
18
 
@@ -7,7 +7,11 @@
7
7
  module GoodData
8
8
  module Environment
9
9
  module ConnectionHelper
10
- set_const :GD_PROJECT_TOKEN, GoodData::Helpers.decrypt("YC+foKO2M8rIfB5gxF/sVvop5dRA7d/zLO/zzUlBr9ZimnoYeLFyAqU20U4k\ncRYb\n", ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY'])
10
+ encrypted_token = 'YC+foKO2M8rIfB5gxF/sVvop5dRA7d/zLO/zzUlBr9ZimnoYe' \
11
+ 'LFyAqU20U4k\ncRYb\n'
12
+ key = ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY']
13
+ token = GoodData::Helpers.decrypt(encrypted_token, key)
14
+ set_const :GD_PROJECT_TOKEN, token
11
15
  set_const :DEFAULT_DOMAIN, 'staging-lcm-prod'
12
16
  set_const :DEFAULT_SERVER, 'https://staging-lcm-prod.intgdc.com'
13
17
  set_const :DEFAULT_USER_URL, '/gdc/account/profile/e306b64fb4178785c9cf29c29b5e498a'
@@ -7,11 +7,14 @@
7
7
  module GoodData
8
8
  module Environment
9
9
  module ConnectionHelper
10
- set_const :GD_PROJECT_TOKEN, GoodData::Helpers.decrypt("DIRchLbHH1fovLSVEfo3f5aQwHHQ432+PxF3uR5IuNn+iYWz+HZrLtaZ3LVE\n0ZNc\n", ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY'])
10
+ set_const :GD_PROJECT_TOKEN, GoodData::Helpers.decrypt(
11
+ "DIRchLbHH1fovLSVEfo3f5aQwHHQ432+PxF3uR5IuNn+iYWz+HZrLtaZ3LVE\n0ZNc\n",
12
+ ENV['GD_SPEC_PASSWORD'] || ENV['BIA_ENCRYPTION_KEY']
13
+ )
11
14
  set_const :DEFAULT_DOMAIN, 'staging2-lcm-prod'
12
15
  set_const :DEFAULT_SERVER, 'https://staging2-lcm-prod.intgdc.com'
13
16
  set_const :DEFAULT_USER_URL, '/gdc/account/profile/5ad80b895edcc438e5a4418e222733fa'
14
- set_const :STAGING_URI, 'https://na1-staging2-di.intgdc.com/uploads/'
17
+ set_const :STAGING_URI, 'https://staging2-lcm-prod.intgdc.com/gdc/uploads/'
15
18
  end
16
19
 
17
20
  module ProcessHelper
@@ -0,0 +1,56 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ require 'gooddata'
8
+
9
+ describe 'Create project using GoodData client', :constraint => 'slow' do
10
+ before(:all) do
11
+ @client = ConnectionHelper.create_default_connection
12
+ @blueprint = GoodData::Model::ProjectBlueprint.build("My project from blueprint") do |project_builder|
13
+ project_builder.add_dataset('dataset.users', title: 'Users Dataset') do |schema_builder|
14
+ schema_builder.add_anchor('attr.users.id')
15
+ schema_builder.add_label('label.users.id_label', reference: 'attr.users.id')
16
+ schema_builder.add_attribute('attr.users.another_attr')
17
+ schema_builder.add_label('label.users.another_attr_label', reference: 'attr.users.another_attr')
18
+ schema_builder.add_fact('fact.users.some_number')
19
+ end
20
+ end
21
+ fail "blueprint is invalid" unless @blueprint.valid?
22
+
23
+ @project = @client.create_project_from_blueprint(@blueprint, auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
24
+ end
25
+
26
+ after(:all) do
27
+ @project && @project.delete
28
+ @client && @client.disconnect
29
+ end
30
+
31
+ it 'Should create computed attribute' do
32
+ metric = @project.facts('fact.users.some_number').create_metric(title: 'Test')
33
+ metric.save
34
+ attribute = @project.attributes('attr.users.another_attr')
35
+
36
+ update = GoodData::Model::ProjectBlueprint.build('update') do |project_builder|
37
+ project_builder.add_computed_attribute(
38
+ 'attr.comp.my_computed_attr',
39
+ title: 'My computed attribute',
40
+ metric: metric,
41
+ attribute: attribute,
42
+ buckets: [{ label: 'Small', highest_value: 1000 }, { label: 'Medium', highest_value: 2000 }, { label: 'High' }]
43
+ )
44
+ end
45
+
46
+ new_bp = @blueprint.merge(update)
47
+ fail "blueprint with computed attribute is invalid" unless new_bp.valid?
48
+
49
+ @project.update_from_blueprint(new_bp)
50
+ ca = @project.attributes.find { |a| a.title == 'My computed attribute' }
51
+
52
+ expect(ca).not_to be_nil
53
+ expect(ca.computed_attribute?).to be_truthy
54
+ expect(@project.computed_attributes.length).to eq 1
55
+ end
56
+ end
@@ -62,6 +62,27 @@ describe GoodData::Client do
62
62
  end
63
63
  end
64
64
 
65
+ describe '#dissociate' do
66
+ before(:all) do
67
+ client_id = SecureRandom.uuid
68
+ @client_project = @client.create_project(title: 'client_1 project', auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
69
+ @segment_client = @segment.create_client(id: "tenant_#{client_id}", project: @client_project)
70
+ end
71
+
72
+ after(:all) do
73
+ @client_project && @client_project.delete
74
+ end
75
+
76
+ it 'Dissociate particular client and their project is not cleaned up' do
77
+ expect(@segment.clients.count).to eq 1
78
+ s = @segment.clients(@segment_client)
79
+ s.dissociate
80
+ expect(@segment.clients.count).to eq 0
81
+ expect(@client_project.reload!.state).to eq :enabled
82
+ @segment_client = nil
83
+ end
84
+ end
85
+
65
86
  describe '#delete' do
66
87
  before(:all) do
67
88
  client_id = SecureRandom.uuid
@@ -26,7 +26,13 @@ describe GoodData::Command::DataWarehouse do
26
26
  dwh = nil
27
27
 
28
28
  begin
29
- dwh = GoodData::Command::DataWarehouse.create(title: title, summary: summary, token: ConnectionHelper::GD_PROJECT_TOKEN, environment: ProjectHelper::ENVIRONMENT, client: @client)
29
+ dwh = GoodData::Command::DataWarehouse.create(
30
+ title: title,
31
+ summary: summary,
32
+ token: ConnectionHelper::GD_PROJECT_TOKEN,
33
+ environment: ProjectHelper::ENVIRONMENT,
34
+ client: @client
35
+ )
30
36
 
31
37
  expect(dwh.title).to eq(title)
32
38
  expect(dwh.summary).to eq(summary)
@@ -6,7 +6,7 @@
6
6
 
7
7
  require 'gooddata'
8
8
 
9
- describe "Spin a project from template", :constraint => 'slow' do
9
+ describe 'Spin a project from template', :constraint => 'slow' do
10
10
  before(:all) do
11
11
  @client = ConnectionHelper.create_default_connection
12
12
  end
@@ -15,9 +15,15 @@ describe "Spin a project from template", :constraint => 'slow' do
15
15
  @client.disconnect
16
16
  end
17
17
 
18
- it "should spin a project from a template that does not exist. It should throw an error" do
18
+ it 'should spin a project from a template that does not exist. It should throw an error' do
19
19
  expect do
20
- GoodData::Project.create(:title => "Test project", :template => "/some/nonexisting/template/uri", :auth_token => ConnectionHelper::GD_PROJECT_TOKEN, environment: ProjectHelper::ENVIRONMENT, :client => @client)
20
+ GoodData::Project.create(
21
+ title: 'Test project',
22
+ template: '/some/nonexisting/template/uri',
23
+ auth_token: ConnectionHelper::GD_PROJECT_TOKEN,
24
+ environment: ProjectHelper::ENVIRONMENT,
25
+ client: @client
26
+ )
21
27
  end.to raise_error
22
28
  end
23
29
  end
@@ -155,6 +155,13 @@ describe GoodData::Project, :constraint => 'slow' do
155
155
  expect(@project.members?(users).all?).to be_truthy
156
156
  expect(@project.get_user(ConnectionHelper::DEFAULT_USERNAME).role.title).to eq 'Admin'
157
157
  end
158
+
159
+ it 'should downcase login' do
160
+ users = [ProjectHelper.create_random_user(@client, login: "#{rand(1e7)}+TMA-445+RubyDev+Admin@gooddata.com")]
161
+ @domain.create_users(users)
162
+ @project.import_users(users, domain: @domain, whitelists: ['rubydev+admin@gooddata.com'])
163
+ expect(@project.members?(users.map(&:to_hash).map { |u| u[:login].downcase! })).to be_truthy
164
+ end
158
165
  end
159
166
 
160
167
  describe '#set_user_roles' do
@@ -96,57 +96,4 @@ describe GoodData::Segment do
96
96
  end
97
97
  end
98
98
  end
99
-
100
- describe '#provision_client_projects' do
101
- it 'can create a new client in a segment without project and then provision' do
102
- begin
103
- segment_client = @segment.create_client(id: 'tenant_1')
104
- expect(segment_client).to be_an_instance_of(GoodData::Client)
105
- expect(@segment.clients.count).to eq 1
106
- @domain.synchronize_clients
107
- @domain.provision_client_projects
108
- expect(@domain.segments.flat_map { |s| s.clients.to_a }.all?(&:project?)).to be_truthy
109
- ensure
110
- segment_client && segment_client.delete
111
- end
112
- end
113
- end
114
-
115
- describe '#update_clients' do
116
- it 'can create a new client in a segment without project and then provision' do
117
- begin
118
- uuid_2 = SecureRandom.uuid
119
- master_project_2 = @client.create_project(title: "Test MASTER project for #{uuid_2}", auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
120
- segment_name_2 = "segment-#{uuid_2}"
121
- segment_2 = @domain.create_segment(segment_id: segment_name_2, master_project: master_project_2)
122
-
123
- client_1 = "client-#{SecureRandom.uuid}"
124
- client_2 = "client-#{SecureRandom.uuid}"
125
- data = [{ id: client_1, segment: segment_name_2 },
126
- { id: client_2, segment: @segment_name }]
127
- @domain.update_clients(data)
128
- expect(@domain.segments.map(&:id)).to include(@segment.id, segment_2.id)
129
- expect(@domain.segments.pmapcat { |s| s.clients.to_a }.map(&:id)).to include(client_1, client_2)
130
-
131
- client_3 = "client-#{SecureRandom.uuid}"
132
- client_4 = "client-#{SecureRandom.uuid}"
133
- data = [{ id: client_3, segment: segment_name_2 },
134
- { id: client_4, segment: @segment_name }]
135
- @domain.update_clients(data)
136
- expect(@domain.segments.pmapcat { |s| s.clients.to_a }.map(&:id)).to include(client_1, client_2, client_3, client_4)
137
-
138
- # bring the projects
139
- @domain.synchronize_clients
140
- @domain.provision_client_projects
141
- projects_to_delete = @domain.segments.pmapcat { |s| s.clients.to_a }.select { |c| [client_1, client_2].include?(c.id) }.map(&:project)
142
- @domain.update_clients(data, delete_extra: true)
143
- expect(@domain.segments.pmapcat { |s| s.clients.to_a }.map(&:id)).to include(client_3, client_4)
144
- expect(@domain.segments.pmapcat { |s| s.clients.to_a }.map(&:id)).not_to include(client_1, client_2)
145
- expect(projects_to_delete.pmap(&:reload!).map(&:state)).to eq [:deleted, :deleted]
146
- ensure
147
- master_project_2.delete if master_project_2
148
- segment_2.delete(force: true) if segment_2
149
- end
150
- end
151
- end
152
99
  end