gooddata 2.1.12 → 2.1.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gdc-ii-config.yaml +1 -1
  3. data/.sonar.settings +4 -0
  4. data/.travis.yml +78 -12
  5. data/CHANGELOG.md +37 -0
  6. data/Dockerfile +9 -3
  7. data/Dockerfile.jruby +11 -1
  8. data/LICENSE +30 -22
  9. data/LICENSE.rb +1 -1
  10. data/README.md +19 -1
  11. data/Rakefile +8 -1
  12. data/SDK_VERSION +1 -1
  13. data/VERSION +1 -1
  14. data/bin/test_projects_cleanup.rb +45 -3
  15. data/ci/postgresql/pom.xml +57 -0
  16. data/dev-gooddata-sso.pub.encrypted +40 -40
  17. data/docker-compose.lcm.yml +3 -0
  18. data/gdc_fossa_ruby_sdk.yaml +1 -0
  19. data/gooddata.gemspec +8 -5
  20. data/k8s/charts/lcm-bricks/Chart.yaml +1 -1
  21. data/k8s/charts/lcm-bricks/templates/prometheus/alertingRules.yaml +11 -1
  22. data/lcm.rake +10 -4
  23. data/lib/gooddata.rb +2 -0
  24. data/lib/gooddata/cloud_resources/{cloud_resouce_factory.rb → cloud_resource_factory.rb} +8 -0
  25. data/lib/gooddata/cloud_resources/cloud_resources.rb +1 -1
  26. data/lib/gooddata/cloud_resources/postgresql/drivers/.gitkeepme +0 -0
  27. data/lib/gooddata/cloud_resources/postgresql/postgresql_client.rb +107 -0
  28. data/lib/gooddata/commands/scaffold.rb +9 -10
  29. data/lib/gooddata/core/nil_logger.rb +3 -1
  30. data/lib/gooddata/helpers/data_helper.rb +1 -2
  31. data/lib/gooddata/helpers/global_helpers.rb +6 -5
  32. data/lib/gooddata/helpers/global_helpers_params.rb +2 -2
  33. data/lib/gooddata/lcm/actions/associate_clients.rb +8 -2
  34. data/lib/gooddata/lcm/actions/base_action.rb +0 -2
  35. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +2 -1
  36. data/lib/gooddata/lcm/actions/migrate_gdc_date_dimension.rb +116 -0
  37. data/lib/gooddata/lcm/actions/provision_clients.rb +31 -10
  38. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +3 -1
  39. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +4 -0
  40. data/lib/gooddata/lcm/actions/synchronize_users.rb +7 -6
  41. data/lib/gooddata/lcm/lcm2.rb +1 -2
  42. data/lib/gooddata/lcm/types/base_type.rb +0 -2
  43. data/lib/gooddata/mixins/md_object_query.rb +8 -6
  44. data/lib/gooddata/models/blueprint/project_blueprint.rb +0 -2
  45. data/lib/gooddata/models/client.rb +14 -12
  46. data/lib/gooddata/models/data_source.rb +664 -0
  47. data/lib/gooddata/models/domain.rb +3 -2
  48. data/lib/gooddata/models/from_wire.rb +1 -0
  49. data/lib/gooddata/models/metadata/analytical_dashboard.rb +49 -0
  50. data/lib/gooddata/models/metadata/analytical_visualization_object.rb +30 -0
  51. data/lib/gooddata/models/metadata/scheduled_mail.rb +1 -1
  52. data/lib/gooddata/models/metadata/visualization_object.rb +50 -0
  53. data/lib/gooddata/models/process.rb +11 -3
  54. data/lib/gooddata/models/project.rb +104 -13
  55. data/lib/gooddata/models/user_filters/user_filter_builder.rb +0 -1
  56. data/lib/gooddata/models/user_group.rb +0 -1
  57. data/lib/gooddata/rest/connection.rb +6 -4
  58. data/lib/gooddata/rest/phmap.rb +1 -1
  59. data/rubydev_public.gpg.encrypted +51 -51
  60. data/rubydev_secret_keys.gpg.encrypted +109 -109
  61. metadata +21 -22
  62. data/DEPENDENCIES.md +0 -880
@@ -5,7 +5,6 @@
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
7
  require 'cgi'
8
- require 'active_support/core_ext/hash/compact'
9
8
 
10
9
  require_relative 'profile'
11
10
  require_relative '../extensions/enumerable'
@@ -457,10 +456,12 @@ Available values for setting language are: #{available_languages}."
457
456
  alias_method :add_clients_settings, :update_clients_settings
458
457
 
459
458
  def update_clients(data, options = {})
459
+ results = []
460
460
  data.group_by(&:data_product_id).each do |data_product_id, client_update_data|
461
461
  data_product = data_products(data_product_id)
462
- data_product.update_clients(client_update_data, options)
462
+ results.concat data_product.update_clients(client_update_data, options)
463
463
  end
464
+ results
464
465
  end
465
466
 
466
467
  # Update user in domain
@@ -105,6 +105,7 @@ module GoodData
105
105
  d[:title] = date_dim['dateDimension']['title']
106
106
  d[:urn] = date_dim['dateDimension']['urn']
107
107
  d[:identifier_prefix] = date_dim['dateDimension']['identifierPrefix']
108
+ d[:identifier] = date_dim['dateDimension']['identifier'] if date_dim['dateDimension']['identifier']
108
109
  d[:columns] = parse_bridges(date_dim)
109
110
  end
110
111
  end
@@ -0,0 +1,49 @@
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
+ require_relative 'analytical_visualization_object'
9
+
10
+ module GoodData
11
+ class AnalyticalDashboard < GoodData::AnalyticalVisualizationObject
12
+ EMPTY_OBJECT = {
13
+ 'analyticalDashboard' => {
14
+ 'content' => {
15
+ 'filterContext' => '',
16
+ 'layout' => {},
17
+ 'widgets' => []
18
+ },
19
+ 'meta' => {
20
+ 'deprecated' => '0',
21
+ 'summary' => '',
22
+ 'title' => ''
23
+ }
24
+ }
25
+ }
26
+
27
+ ASSIGNABLE_MEMBERS = %i[filterContext layout widgets deprecated summary title]
28
+
29
+ class << self
30
+ # Method intended to get all AnalyticalDashboard objects in a specified project
31
+ #
32
+ # @param options [Hash] the options hash
33
+ # @option options [Boolean] :full with true value will pull in full objects. Default is false value
34
+ # @return [Array<GoodData::AnalyticalDashboard>] Return AnalyticalDashboard list
35
+ def all(options = { :client => GoodData.connection, :project => GoodData.project })
36
+ query('analyticalDashboard', AnalyticalDashboard, options)
37
+ end
38
+
39
+ # Create Analytical Dashboard in the specify project
40
+ #
41
+ # @param analytical_dashboard [Hash] the data of object will be created
42
+ # @param options [Hash] The project that the object will be created in
43
+ # @return GoodData::AnalyticalDashboard object
44
+ def create(analytical_dashboard = {}, options = { :client => GoodData.client, :project => GoodData.project })
45
+ GoodData::AnalyticalVisualizationObject.create(analytical_dashboard, AnalyticalDashboard, EMPTY_OBJECT, ASSIGNABLE_MEMBERS, options)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,30 @@
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 AnalyticalVisualizationObject < GoodData::MdObject
10
+ class << self
11
+ # Create a specify object in the specify project
12
+ #
13
+ # @param object_data [Hash] the data of object will be created
14
+ # @param klass [Class] A class used for instantiating the returned data
15
+ # @param empty_data_object [Hash] the empty data of object will be created
16
+ # @param assignable_properties [Hash] the properties allow updating
17
+ # @param options [Hash] The project that the object will be created in
18
+ # @return klass object
19
+ def create(object_data, klass, empty_data_object = {}, assignable_properties = [], options = { :client => GoodData.client, :project => GoodData.project })
20
+ client, project = GoodData.get_client_and_project(GoodData::Helpers.symbolize_keys(options))
21
+
22
+ res = client.create(klass, GoodData::Helpers.deep_dup(GoodData::Helpers.stringify_keys(empty_data_object)), :project => project)
23
+ object_data.each do |k, v|
24
+ res.send("#{k}=", v) if assignable_properties.include? k
25
+ end
26
+ res
27
+ end
28
+ end
29
+ end
30
+ end
@@ -30,7 +30,7 @@ module GoodData
30
30
  :deprecated => 0,
31
31
 
32
32
  # Content When options
33
- :recurrency => '0:0:0:12:0:0',
33
+ :recurrency => '0:0:0:1*12:0:0',
34
34
  :startDate => '2012-06-05',
35
35
  :timeZone => 'America/Los_Angeles',
36
36
 
@@ -0,0 +1,50 @@
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
+ require_relative 'analytical_visualization_object'
9
+
10
+ module GoodData
11
+ class VisualizationObject < GoodData::AnalyticalVisualizationObject
12
+ EMPTY_OBJECT = {
13
+ 'visualizationObject' => {
14
+ 'content' => {
15
+ 'buckets' => [],
16
+ 'properties' => '',
17
+ 'visualizationClass' => {}
18
+ },
19
+ 'links' => {},
20
+ 'meta' => {
21
+ 'deprecated' => '0',
22
+ 'summary' => '',
23
+ 'title' => ''
24
+ }
25
+ }
26
+ }
27
+
28
+ ASSIGNABLE_MEMBERS = %i[buckets properties visualizationClass deprecated summary title]
29
+
30
+ class << self
31
+ # Method intended to get all VisualizationObject objects in a specified project
32
+ #
33
+ # @param options [Hash] the options hash
34
+ # @option options [Boolean] :full with true value to pull full objects
35
+ # @return [Array<GoodData::VisualizationObject>] Return VisualizationObject list
36
+ def all(options = { :client => GoodData.connection, :project => GoodData.project })
37
+ query('visualizationObject', VisualizationObject, options)
38
+ end
39
+
40
+ # Create Visualization Object in the specify project
41
+ #
42
+ # @param visualization_object [Hash] the data of object will be created
43
+ # @param options [Hash] The project that the object will be created in
44
+ # @return GoodData::VisualizationObject object
45
+ def create(visualization_object = {}, options = { :client => GoodData.client, :project => GoodData.project })
46
+ GoodData::AnalyticalVisualizationObject.create(visualization_object, VisualizationObject, EMPTY_OBJECT, ASSIGNABLE_MEMBERS, options)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -118,11 +118,13 @@ module GoodData
118
118
  GoodData.logger.info("Deploying #{path}") if verbose
119
119
 
120
120
  deployed_path = Process.upload_package(path, files_to_exclude, client: client, project: project)
121
+ data_sources = options[:data_sources] || []
121
122
  data = {
122
123
  :process => {
123
124
  :name => deploy_name,
124
125
  :path => "/uploads/#{File.basename(deployed_path)}",
125
- :type => type
126
+ :type => type,
127
+ :dataSources => data_sources
126
128
  }
127
129
  }
128
130
 
@@ -171,10 +173,12 @@ module GoodData
171
173
  verbose = options[:verbose] || false
172
174
  GoodData.logger.info("Deploying #{path}") if verbose
173
175
 
176
+ data_sources = options[:data_sources] || []
174
177
  data = {
175
178
  process: {
176
179
  name: deploy_name,
177
180
  path: path,
181
+ dataSources: data_sources,
178
182
  type: 'RUBY'
179
183
  }
180
184
  }
@@ -185,7 +189,7 @@ module GoodData
185
189
  def deploy_component(data, options = { client: GoodData.client, project: GoodData.project })
186
190
  client, project = GoodData.get_client_and_project(options)
187
191
  data = { process: data } unless data[:process]
188
- data[:process] = GoodData::Helpers.symbolize_keys(data[:process]).select { |k| %i[type name component].include? k }
192
+ data[:process] = GoodData::Helpers.symbolize_keys(data[:process]).select { |k| %i[type name component dataSources].include? k }
189
193
  data[:process][:component] = GoodData::Helpers.symbolize_keys(data[:process][:component]).select { |k| %i[name version configLocation config].include? k }
190
194
 
191
195
  save(data, options)
@@ -266,7 +270,7 @@ module GoodData
266
270
  # @option options [String] :name Readable name of the process
267
271
  # @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging
268
272
  def deploy(path, options = {})
269
- Process.deploy(path, { client: client, process_id: process_id, :project => project, :name => name, :type => type }.merge(options))
273
+ Process.deploy(path, { client: client, process_id: process_id, :project => project, :name => name, :type => type, :data_sources => data_sources }.merge(options))
270
274
  end
271
275
 
272
276
  # Downloads the process from S3 in a zipped form.
@@ -326,6 +330,10 @@ module GoodData
326
330
  process['component']
327
331
  end
328
332
 
333
+ def data_sources
334
+ process['dataSources']
335
+ end
336
+
329
337
  # Determines whether the process is an ADDv2 component.
330
338
  # @return [Bool] True if the process is an ADDv2 component.
331
339
  def add_v2_component?
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2021 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -13,7 +13,6 @@ require 'zip'
13
13
  require 'net/smtp'
14
14
 
15
15
  require 'active_support/core_ext/hash/except'
16
- require 'active_support/core_ext/hash/compact'
17
16
  require 'active_support/core_ext/hash/slice'
18
17
 
19
18
  require_relative '../exceptions/no_project_error'
@@ -38,7 +37,8 @@ require_relative 'metadata/scheduled_mail/report_attachment'
38
37
 
39
38
  module GoodData
40
39
  class Project < Rest::Resource
41
- USERSPROJECTS_PATH = '/gdc/account/profile/%s/projects'
40
+ USER_ACCOUNT_PATH = '/gdc/account/profile/'
41
+ USERSPROJECTS_PATH = USER_ACCOUNT_PATH + '%s/projects'
42
42
  PROJECTS_PATH = '/gdc/projects'
43
43
  PROJECT_PATH = '/gdc/projects/%s'
44
44
  SLIS_PATH = '/ldm/singleloadinterface'
@@ -261,21 +261,26 @@ module GoodData
261
261
  # @option ads_output_stage_uri Uri of the source output stage. It must be in the same domain as the target project.
262
262
  def transfer_processes(from_project, to_project, options = {})
263
263
  options = GoodData::Helpers.symbolize_keys(options)
264
+ aliases = {}
264
265
  to_project_processes = to_project.processes
265
266
  additional_hidden_params = options[:additional_hidden_params] || {}
266
267
  result = from_project.processes.uniq(&:name).map do |process|
267
- fail "The process name #{process.name} must be unique in transfered project #{to_project}" if to_project_processes.count { |p| p.name == process.name } > 1
268
+ fail "The process name #{process.name} must be unique in transferred project #{to_project}" if to_project_processes.count { |p| p.name == process.name } > 1
268
269
  next if process.type == :dataload || process.add_v2_component?
270
+ collect_process_aliases(process.data, from_project.client, aliases)
269
271
 
270
272
  to_process = to_project_processes.find { |p| p.name == process.name }
271
273
 
274
+ data_sources = GoodData::Helpers.symbolize_keys_recursively!(process.data_sources)
275
+ data_sources = replace_data_source_ids(data_sources, to_project.client, aliases)
272
276
  to_process = if process.path
273
277
  to_process.delete if to_process
274
- GoodData::Process.deploy_from_appstore(process.path, name: process.name, client: to_project.client, project: to_project)
278
+ Process.deploy_from_appstore(process.path, name: process.name, client: to_project.client, project: to_project, data_sources: data_sources)
275
279
  elsif process.component
276
280
  to_process.delete if to_process
277
281
  process_hash = GoodData::Helpers::DeepMergeableHash[GoodData::Helpers.symbolize_keys(process.to_hash)].deep_merge(additional_hidden_params)
278
- GoodData::Process.deploy_component(process_hash, project: to_project, client: to_project.client)
282
+ process_hash = replace_process_data_source_ids(process_hash, to_project.client, aliases)
283
+ Process.deploy_component(process_hash, project: to_project, client: to_project.client)
279
284
  else
280
285
  Dir.mktmpdir('etl_transfer') do |dir|
281
286
  dir = Pathname(dir)
@@ -283,11 +288,10 @@ module GoodData
283
288
  File.open(filename, 'w') do |f|
284
289
  f << process.download
285
290
  end
286
-
287
291
  if to_process
288
- to_process.deploy(filename, type: process.type, name: process.name)
292
+ to_process.deploy(filename, type: process.type, name: process.name, data_sources: data_sources)
289
293
  else
290
- to_project.deploy_process(filename, type: process.type, name: process.name)
294
+ to_project.deploy_process(filename, type: process.type, name: process.name, data_sources: data_sources)
291
295
  end
292
296
  end
293
297
  end
@@ -318,6 +322,78 @@ module GoodData
318
322
  result.compact
319
323
  end
320
324
 
325
+ def collect_process_aliases(process_data, client, aliases)
326
+ data_sources = process_data.dig('process', 'dataSources')
327
+ unless data_sources.blank?
328
+ data_sources.map do |data_source|
329
+ get_data_source_alias(data_source['id'], client, aliases)
330
+ end
331
+ end
332
+ component = process_data.dig('process', 'component')
333
+ get_data_source_alias(component['configLocation']['dataSourceConfig']['id'], client, aliases) if component&.dig('configLocation', 'dataSourceConfig')
334
+ aliases
335
+ end
336
+
337
+ def get_data_source_alias(data_source_id, client, aliases)
338
+ unless aliases[data_source_id]
339
+ data_source = GoodData::DataSource.from_id(data_source_id, client: client)
340
+ if data_source&.dig('dataSource', 'alias')
341
+ aliases[data_source_id] = {
342
+ :type => get_data_source_type(data_source),
343
+ :alias => data_source['dataSource']['alias']
344
+ }
345
+ end
346
+ end
347
+ aliases[data_source_id]
348
+ end
349
+
350
+ def get_data_source_type(data_source_data)
351
+ data_source_data&.dig('dataSource', 'connectionInfo') ? data_source_data['dataSource']['connectionInfo'].first[0].upcase : ""
352
+ end
353
+
354
+ def replace_process_data_source_ids(process_data, client, aliases)
355
+ component = process_data.dig(:process, :component)
356
+ if component&.dig(:configLocation, :dataSourceConfig)
357
+ the_alias = aliases[component[:configLocation][:dataSourceConfig][:id]]
358
+ process_data[:process][:component][:configLocation][:dataSourceConfig][:id] = verify_data_source_alias(the_alias, client)
359
+ end
360
+ process_data[:process][:dataSources] = replace_data_source_ids(process_data[:process][:dataSources], client, aliases)
361
+ process_data
362
+ end
363
+
364
+ def replace_data_source_ids(data_sources, client, aliases)
365
+ array_data_sources = []
366
+ if data_sources && !data_sources.empty?
367
+ data_sources.map do |data_source|
368
+ new_id = verify_data_source_alias(aliases[data_source[:id]], client)
369
+ array_data_sources.push(:id => new_id)
370
+ end
371
+ end
372
+ array_data_sources
373
+ end
374
+
375
+ # Verify whether the data source exists in the domain using its alias
376
+ #
377
+ # @param [String] ds_alias The data source's alias
378
+ # @param [Object] client The Rest Client object
379
+ # @return [String] Id of the data source or failed with the reason
380
+ def verify_data_source_alias(ds_alias, client)
381
+ domain = client.connection.server.url
382
+ fail "The data source alias is empty, check your data source configuration." unless ds_alias
383
+
384
+ uri = "/gdc/dataload/dataSources/internal/availableAlias?alias=#{ds_alias[:alias]}"
385
+ res = client.get(uri)
386
+ fail "Unable to get information about the Data Source '#{ds_alias[:alias]}' in the domain '#{domain}'" unless res
387
+ fail "Unable to find the #{ds_alias[:type]} Data Source '#{ds_alias[:alias]}' in the domain '#{domain}'" if res['availableAlias']['available']
388
+
389
+ ds_type = res['availableAlias']['existingDataSource']['type']
390
+ if ds_type && ds_type != ds_alias[:type]
391
+ fail "Wrong Data Source type - the '#{ds_type}' type is expected but the Data Source '#{ds_alias[:alias]}' in the domain '#{domain}' has the '#{ds_alias[:type]}' type"
392
+ else
393
+ res['availableAlias']['existingDataSource']['id']
394
+ end
395
+ end
396
+
321
397
  def transfer_user_groups(from_project, to_project)
322
398
  from_project.user_groups.map do |ug|
323
399
  # migrate groups
@@ -625,6 +701,7 @@ module GoodData
625
701
  def blueprint(options = {})
626
702
  options = { include_ca: true }.merge(options)
627
703
  result = client.get("/gdc/projects/#{pid}/model/view", params: { includeDeprecated: true, includeGrain: true, includeCA: options[:include_ca] })
704
+
628
705
  polling_url = result['asyncTask']['link']['poll']
629
706
  model = client.poll_on_code(polling_url, options)
630
707
  bp = GoodData::Model::FromWire.from_wire(model, options)
@@ -1661,7 +1738,7 @@ module GoodData
1661
1738
  end
1662
1739
  end
1663
1740
  diff_results = diff_results.map do |u|
1664
- u[:login_uri] = "/gdc/account/profile/" + u[:login]
1741
+ u[:login_uri] = USER_ACCOUNT_PATH + u[:login]
1665
1742
  u
1666
1743
  end
1667
1744
  return diff_results if options[:dry_run]
@@ -1897,17 +1974,17 @@ module GoodData
1897
1974
 
1898
1975
  def resolve_roles(login, desired_roles, options = {})
1899
1976
  user = if login.is_a?(String) && login.include?('@')
1900
- '/gdc/account/profile/' + login
1977
+ USER_ACCOUNT_PATH + login
1901
1978
  elsif login.is_a?(String)
1902
1979
  login
1903
1980
  elsif login.is_a?(Hash) && login[:login]
1904
- '/gdc/account/profile/' + login[:login]
1981
+ USER_ACCOUNT_PATH + login[:login]
1905
1982
  elsif login.is_a?(Hash) && login[:uri]
1906
1983
  login[:uri]
1907
1984
  elsif login.respond_to?(:uri) && login.uri
1908
1985
  login.uri
1909
1986
  elsif login.respond_to?(:login) && login.login
1910
- '/gdc/account/profile/' + login.login
1987
+ USER_ACCOUNT_PATH + login.login
1911
1988
  else
1912
1989
  fail "Unsupported user specification #{login}"
1913
1990
  end
@@ -1922,6 +1999,20 @@ module GoodData
1922
1999
  [user, roles]
1923
2000
  end
1924
2001
 
2002
+ def upgrade_custom_v2(message, options = {})
2003
+ uri = "/gdc/md/#{pid}/datedimension/upgrade"
2004
+ poll_result = client&.post(uri, message)
2005
+
2006
+ return poll_result['wTaskStatus']['status'] if poll_result['wTaskStatus'] && poll_result['wTaskStatus']['status']
2007
+
2008
+ polling_uri = poll_result['asyncTask']['link']['poll']
2009
+ result = client&.poll_on_response(polling_uri, options) do |body|
2010
+ body && body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING'
2011
+ end
2012
+
2013
+ result['wTaskStatus']['status'] == 'OK' ? 'OK' : 'FAIL'
2014
+ end
2015
+
1925
2016
  def add
1926
2017
  @add ||= GoodData::AutomatedDataDistribution.new(self)
1927
2018
  @add
@@ -7,7 +7,6 @@
7
7
  require_relative '../project_log_formatter'
8
8
 
9
9
  require 'active_support/core_ext/hash/indifferent_access'
10
- require 'active_support/core_ext/hash/compact'
11
10
 
12
11
  require 'gooddata/extensions/true'
13
12
  require 'gooddata/extensions/false'
@@ -13,7 +13,6 @@ require_relative '../mixins/rest_resource'
13
13
  require_relative '../mixins/uri_getter'
14
14
 
15
15
  require 'active_support/core_ext/hash/except'
16
- require 'active_support/core_ext/hash/compact'
17
16
 
18
17
  module GoodData
19
18
  # Representation of User Group