gooddata 0.6.51 → 0.6.52
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +13 -1
- data/CONTRIBUTING.md +25 -0
- data/PULL_REQUEST_TEMPLATE.md +5 -0
- data/README.md +7 -4
- data/gooddata.gemspec +2 -3
- data/lib/gooddata.rb +1 -0
- data/lib/gooddata/bricks/base_downloader.rb +6 -6
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +15 -5
- data/lib/gooddata/bricks/middleware/dwh_middleware.rb +15 -3
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +13 -4
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +3 -0
- data/lib/gooddata/exceptions/no_project_error.rb +5 -1
- data/lib/gooddata/goodzilla/goodzilla.rb +7 -6
- data/lib/gooddata/helpers/data_helper.rb +4 -4
- data/lib/gooddata/helpers/global_helpers_params.rb +61 -39
- data/lib/gooddata/lcm/actions/apply_custom_maql.rb +9 -0
- data/lib/gooddata/lcm/actions/associate_clients.rb +23 -4
- data/lib/gooddata/lcm/actions/collect_attrs.rb +56 -0
- data/lib/gooddata/lcm/actions/collect_ca_metrics.rb +53 -0
- data/lib/gooddata/lcm/actions/collect_clients.rb +25 -3
- data/lib/gooddata/lcm/actions/collect_meta.rb +83 -0
- data/lib/gooddata/lcm/actions/collect_segment_clients.rb +12 -4
- data/lib/gooddata/lcm/actions/collect_segments.rb +4 -4
- data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +74 -0
- data/lib/gooddata/lcm/actions/create_segment_masters.rb +16 -30
- data/lib/gooddata/lcm/actions/ensure_release_table.rb +0 -3
- data/lib/gooddata/lcm/actions/ensure_segments.rb +1 -4
- data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +5 -5
- data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +8 -5
- data/lib/gooddata/lcm/actions/hello_world.rb +0 -3
- data/lib/gooddata/lcm/actions/import_object_collections.rb +60 -0
- data/lib/gooddata/lcm/actions/print_actions.rb +0 -3
- data/lib/gooddata/lcm/actions/print_modes.rb +0 -3
- data/lib/gooddata/lcm/actions/print_types.rb +1 -4
- data/lib/gooddata/lcm/actions/provision_clients.rb +5 -5
- data/lib/gooddata/lcm/actions/purge_clients.rb +4 -10
- data/lib/gooddata/lcm/actions/segments_filter.rb +0 -6
- data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +8 -4
- data/lib/gooddata/lcm/actions/synchronize_cas.rb +61 -0
- data/lib/gooddata/lcm/actions/synchronize_clients.rb +9 -3
- data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +13 -5
- data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +71 -17
- data/lib/gooddata/lcm/actions/synchronize_label_types.rb +8 -5
- data/lib/gooddata/lcm/actions/synchronize_ldm.rb +17 -8
- data/lib/gooddata/lcm/actions/synchronize_meta.rb +0 -3
- data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +9 -4
- data/lib/gooddata/lcm/actions/synchronize_processes.rb +9 -5
- data/lib/gooddata/lcm/actions/synchronize_schedules.rb +15 -5
- data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +61 -0
- data/lib/gooddata/lcm/actions/update_release_table.rb +0 -3
- data/lib/gooddata/lcm/helpers/tags_helper.rb +35 -0
- data/lib/gooddata/lcm/lcm.rb +22 -4
- data/lib/gooddata/lcm/lcm2.rb +66 -13
- data/lib/gooddata/lcm/types/complex/update_preference.rb +1 -1
- data/lib/gooddata/mixins/md_finders.rb +4 -2
- data/lib/gooddata/mixins/md_object_indexer.rb +13 -3
- data/lib/gooddata/mixins/md_object_query.rb +8 -2
- data/lib/gooddata/models/blueprint/date_dimension.rb +6 -0
- data/lib/gooddata/models/blueprint/project_blueprint.rb +41 -11
- data/lib/gooddata/models/blueprint/project_builder.rb +20 -0
- data/lib/gooddata/models/blueprint/to_wire.rb +7 -0
- data/lib/gooddata/models/client.rb +6 -0
- data/lib/gooddata/models/domain.rb +6 -6
- data/lib/gooddata/models/from_wire.rb +5 -1
- data/lib/gooddata/models/metadata.rb +55 -9
- data/lib/gooddata/models/metadata/attribute.rb +19 -4
- data/lib/gooddata/models/metadata/dashboard.rb +15 -3
- data/lib/gooddata/models/metadata/dataset.rb +5 -2
- data/lib/gooddata/models/metadata/dimension.rb +4 -1
- data/lib/gooddata/models/metadata/fact.rb +9 -2
- data/lib/gooddata/models/metadata/folder.rb +4 -1
- data/lib/gooddata/models/metadata/metric.rb +11 -3
- data/lib/gooddata/models/metadata/report.rb +7 -2
- data/lib/gooddata/models/metadata/report_definition.rb +11 -4
- data/lib/gooddata/models/metadata/scheduled_mail.rb +4 -1
- data/lib/gooddata/models/metadata/variable.rb +7 -2
- data/lib/gooddata/models/model.rb +14 -3
- data/lib/gooddata/models/process.rb +10 -9
- data/lib/gooddata/models/project.rb +134 -36
- data/lib/gooddata/models/project_creator.rb +43 -20
- data/lib/gooddata/models/report_data_result.rb +6 -2
- data/lib/gooddata/models/schedule.rb +6 -3
- data/lib/gooddata/models/subscription.rb +8 -1
- data/lib/gooddata/models/user_filters/user_filter.rb +1 -0
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +18 -4
- data/lib/gooddata/models/user_filters/variable_user_filter.rb +3 -1
- data/lib/gooddata/rest/client.rb +4 -6
- data/lib/gooddata/rest/connection.rb +10 -2
- data/lib/gooddata/version.rb +1 -1
- data/spec/data/blueprints/test_blueprint.json +1 -0
- data/spec/data/wire_models/test_blueprint.json +3 -0
- data/spec/data/workspace_table.csv +3 -0
- data/spec/environment/development.rb +4 -1
- data/spec/environment/environment.rb +1 -1
- data/spec/environment/staging.rb +5 -1
- data/spec/environment/testing.rb +5 -2
- data/spec/integration/blueprint_with_ca_spec.rb +56 -0
- data/spec/integration/clients_spec.rb +21 -0
- data/spec/integration/command_datawarehouse_spec.rb +7 -1
- data/spec/integration/create_from_template_spec.rb +9 -3
- data/spec/integration/project_spec.rb +7 -0
- data/spec/integration/segments_spec.rb +0 -53
- data/spec/integration/subscription_spec.rb +29 -4
- data/spec/integration/urn_date_dim_spec.rb +53 -0
- data/spec/integration/user_filters_spec.rb +6 -0
- data/spec/integration/variables_spec.rb +1 -2
- data/spec/spec_helper.rb +5 -30
- data/spec/unit/actions/collect_clients_spec.rb +38 -0
- data/spec/unit/actions/collect_meta_spec.rb +87 -0
- data/spec/unit/actions/collect_segment_clients_spec.rb +40 -0
- data/spec/unit/actions/collect_tagged_objects_spec.rb +110 -0
- data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +51 -0
- data/spec/unit/bricks/middleware/aws_middelware_spec.rb +55 -1
- data/spec/unit/bricks/middleware/logger_middleware_spec.rb +15 -0
- data/spec/unit/helpers/data_helper_spec.rb +3 -5
- data/spec/unit/helpers/global_helpers_spec.rb +29 -0
- data/spec/unit/helpers_spec.rb +18 -1
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +1 -23
- data/spec/unit/models/domain_spec.rb +19 -0
- data/spec/unit/models/metadata_spec.rb +34 -0
- data/spec/unit/models/schedule_spec.rb +31 -0
- data/spec/unit/models/to_manifest_spec.rb +10 -2
- data/spec/unit/models/unit_project_spec.rb +6 -1
- data/spec/unit/rest/polling_spec.rb +13 -1
- 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.
|
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.
|
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 &&
|
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
|
@@ -130,7 +130,11 @@ module GoodData
|
|
130
130
|
next true if domain_user
|
131
131
|
false
|
132
132
|
end
|
133
|
-
|
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
|
-
|
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
|
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.
|
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]
|
data/lib/gooddata/rest/client.rb
CHANGED
@@ -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
|
-
|
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}',
|
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-]+}],
|
data/lib/gooddata/version.rb
CHANGED
@@ -7,7 +7,10 @@
|
|
7
7
|
module GoodData
|
8
8
|
module Environment
|
9
9
|
module ConnectionHelper
|
10
|
-
|
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'
|
data/spec/environment/staging.rb
CHANGED
@@ -7,7 +7,11 @@
|
|
7
7
|
module GoodData
|
8
8
|
module Environment
|
9
9
|
module ConnectionHelper
|
10
|
-
|
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'
|
data/spec/environment/testing.rb
CHANGED
@@ -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(
|
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://
|
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(
|
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
|
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
|
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(
|
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
|