gooddata 0.6.50 → 0.6.51
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.
- checksums.yaml +4 -4
- data/.editorconfig +12 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +3 -0
- data/gooddata.gemspec +2 -1
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +4 -0
- data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +1 -1
- data/lib/gooddata/bricks/middleware/dwh_middleware.rb +1 -0
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +1 -0
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +2 -1
- data/lib/gooddata/core/nil_logger.rb +9 -0
- data/lib/gooddata/goodzilla/goodzilla.rb +1 -1
- data/lib/gooddata/helpers/data_helper.rb +1 -0
- data/lib/gooddata/helpers/global_helpers_params.rb +54 -27
- data/lib/gooddata/lcm/actions/apply_custom_maql.rb +70 -0
- data/lib/gooddata/lcm/actions/associate_clients.rb +17 -4
- data/lib/gooddata/lcm/actions/collect_clients.rb +4 -1
- data/lib/gooddata/lcm/actions/collect_segment_clients.rb +1 -0
- data/lib/gooddata/lcm/actions/collect_segments.rb +15 -2
- data/lib/gooddata/lcm/actions/create_segment_masters.rb +2 -2
- data/lib/gooddata/lcm/actions/provision_clients.rb +2 -4
- data/lib/gooddata/lcm/actions/purge_clients.rb +2 -2
- data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +81 -0
- data/lib/gooddata/lcm/actions/synchronize_label_types.rb +2 -2
- data/lib/gooddata/lcm/actions/synchronize_processes.rb +3 -1
- data/lib/gooddata/lcm/data/create_lcm_release.sql.erb +2 -1
- data/lib/gooddata/lcm/helpers/check_helper.rb +1 -1
- data/lib/gooddata/lcm/lcm.rb +29 -11
- data/lib/gooddata/lcm/lcm2.rb +82 -20
- data/lib/gooddata/models/domain.rb +22 -1
- data/lib/gooddata/models/metadata.rb +13 -8
- data/lib/gooddata/models/metadata/attribute.rb +1 -1
- data/lib/gooddata/models/metadata/report_definition.rb +1 -0
- data/lib/gooddata/models/profile.rb +1 -1
- data/lib/gooddata/models/project.rb +162 -38
- data/lib/gooddata/models/project_creator.rb +26 -6
- data/lib/gooddata/models/project_log_formatter.rb +204 -0
- data/lib/gooddata/models/schedule.rb +2 -21
- data/lib/gooddata/models/segment.rb +26 -0
- data/lib/gooddata/models/style_setting.rb +5 -1
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +9 -0
- data/lib/gooddata/rest/connection.rb +4 -1
- data/lib/gooddata/version.rb +1 -1
- data/spec/environment/development.rb +29 -0
- data/spec/environment/environment.rb +14 -2
- data/spec/environment/{hotfix.rb → testing.rb} +0 -0
- data/spec/integration/date_dim_switch_spec.rb +3 -5
- data/spec/integration/lcm_spec.rb +24 -21
- data/spec/integration/project_spec.rb +16 -0
- data/spec/integration/segments_spec.rb +1 -1
- data/spec/unit/helpers/global_helpers_spec.rb +26 -2
- data/spec/unit/helpers_spec.rb +20 -0
- data/spec/unit/models/project_creator_spec.rb +3 -2
- metadata +29 -12
- data/lib/gooddata/lcm/actions/ensure_titles.rb +0 -54
- data/spec/environment/develop.rb +0 -46
|
@@ -55,10 +55,10 @@ module GoodData
|
|
|
55
55
|
project = segment_client.project
|
|
56
56
|
res = {
|
|
57
57
|
client_id: segment_client.client_id,
|
|
58
|
-
project: project.pid
|
|
58
|
+
project: project && project.pid
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
if project.deleted?
|
|
61
|
+
if project.nil? || project.deleted?
|
|
62
62
|
segment_client.delete
|
|
63
63
|
res[:status] = 'purged'
|
|
64
64
|
else
|
|
@@ -0,0 +1,81 @@
|
|
|
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_relative 'base_action'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
module LCM2
|
|
11
|
+
class SynchronizeETLsInSegment < BaseAction
|
|
12
|
+
DESCRIPTION = 'Synchronize ETLs (CC/Ruby) In Segment'
|
|
13
|
+
|
|
14
|
+
PARAMS = define_params(self) do
|
|
15
|
+
description 'Client Used for Connecting to GD'
|
|
16
|
+
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# will be updated later based on the way etl synchronization
|
|
20
|
+
RESULT_HEADER = [
|
|
21
|
+
:segment,
|
|
22
|
+
:master_project,
|
|
23
|
+
:client_id,
|
|
24
|
+
:client_project,
|
|
25
|
+
:status
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
def call(params)
|
|
30
|
+
# Check if all required parameters were passed
|
|
31
|
+
BaseAction.check_params(PARAMS, params)
|
|
32
|
+
|
|
33
|
+
client = params.gdc_gd_client
|
|
34
|
+
domain_name = params.organization || params.domain
|
|
35
|
+
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
36
|
+
synchronize_segments = params.synchronize.group_by do |info|
|
|
37
|
+
info[:segment_id]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
results = synchronize_segments.flat_map do |segment_id, synchronize|
|
|
41
|
+
segment = domain.segments(segment_id)
|
|
42
|
+
res = segment.synchronize_processes(
|
|
43
|
+
synchronize.flat_map do |info|
|
|
44
|
+
info[:to].flat_map do |to|
|
|
45
|
+
to[:pid]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
res = GoodData::Helpers.symbolize_keys(res)
|
|
51
|
+
res[:syncedResult][:clients].flat_map do |item|
|
|
52
|
+
item = item[:client]
|
|
53
|
+
{
|
|
54
|
+
segment: segment_id,
|
|
55
|
+
master_project: segment.master_project_id,
|
|
56
|
+
client_id: item[:id],
|
|
57
|
+
client_project: item[:project].split('/').last,
|
|
58
|
+
status: 'ok'
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
params.synchronize.each do |info|
|
|
64
|
+
to_projects = info.to
|
|
65
|
+
to_projects.each do |entry|
|
|
66
|
+
pid = entry[:pid]
|
|
67
|
+
to_project = client.projects(pid) || fail("Invalid 'to' project specified - '#{pid}'")
|
|
68
|
+
to_project.schedules.each do |schedule|
|
|
69
|
+
schedule.update_params(params.additional_params || {})
|
|
70
|
+
schedule.update_hidden_params(params.additional_hidden_params || {})
|
|
71
|
+
schedule.save
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
results
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -37,8 +37,8 @@ module GoodData
|
|
|
37
37
|
to = info.to
|
|
38
38
|
|
|
39
39
|
from_project = development_client.projects(from) || fail("Invalid 'from' project specified - '#{from}'")
|
|
40
|
-
to_projects = to.map do |
|
|
41
|
-
client.projects(pid)
|
|
40
|
+
to_projects = to.map do |project|
|
|
41
|
+
client.projects(project.pid)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
GoodData::LCM.transfer_label_types(from_project, to_projects)
|
|
@@ -14,6 +14,8 @@ module GoodData
|
|
|
14
14
|
PARAMS = define_params(self) do
|
|
15
15
|
description 'Client Used for Connecting to GD'
|
|
16
16
|
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
|
+
description 'Uri of the source output stage. It must be in the same domain as the target project.'
|
|
18
|
+
param :ads_output_stage_uri, instance_of(Type::StringType), required: false
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
RESULT_HEADER = [
|
|
@@ -45,7 +47,7 @@ module GoodData
|
|
|
45
47
|
to_project = client.projects(pid) || fail("Invalid 'to' project specified - '#{pid}'")
|
|
46
48
|
|
|
47
49
|
params.gdc_logger.info "Transferring processes, from project: '#{from.title}', PID: '#{from.pid}', to project: '#{to_project.title}', PID: '#{to_project.pid}'"
|
|
48
|
-
GoodData::Project.transfer_processes(from, to_project)
|
|
50
|
+
GoodData::Project.transfer_processes(from, to_project, ads_output_stage_uri: params.ads_output_stage_uri)
|
|
49
51
|
|
|
50
52
|
to_project.add.output_stage.client_id = client_id if client_id && to_project.add.output_stage
|
|
51
53
|
|
data/lib/gooddata/lcm/lcm.rb
CHANGED
|
@@ -146,6 +146,15 @@ module GoodData
|
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
|
+
|
|
150
|
+
# User groups must be migrated after dashboards
|
|
151
|
+
puts 'Migrating User Groups'
|
|
152
|
+
domain.clients.peach do |c|
|
|
153
|
+
segment = c.segment
|
|
154
|
+
segment_master = segment.master_project
|
|
155
|
+
project = c.project
|
|
156
|
+
GoodData::Project.transfer_user_groups(segment_master, project)
|
|
157
|
+
end
|
|
149
158
|
end
|
|
150
159
|
|
|
151
160
|
def transfer_label_types(source_project, targets)
|
|
@@ -251,30 +260,39 @@ module GoodData
|
|
|
251
260
|
|
|
252
261
|
# Generate transfer table
|
|
253
262
|
drill_paths = attributes.map do |attribute|
|
|
254
|
-
|
|
263
|
+
drill_label_uri = attribute.content['drillDownStepAttributeDF']
|
|
264
|
+
if drill_label_uri
|
|
265
|
+
drill_label = source_project.labels(drill_label_uri)
|
|
266
|
+
[attribute.meta['identifier'], drill_label.identifier]
|
|
267
|
+
else
|
|
268
|
+
[]
|
|
269
|
+
end
|
|
255
270
|
end
|
|
256
271
|
transfer = Hash[*drill_paths.flatten].compact
|
|
257
272
|
|
|
258
273
|
# Transfer to target projects
|
|
259
274
|
targets.peach do |target|
|
|
260
|
-
transfer.peach do |
|
|
261
|
-
|
|
262
|
-
next unless
|
|
275
|
+
transfer.peach do |attr_identifier, drill_path_identifier|
|
|
276
|
+
attr_uri = GoodData::MdObject.identifier_to_uri({ project: target, client: target.client }, attr_identifier)
|
|
277
|
+
next unless attr_uri
|
|
263
278
|
|
|
264
|
-
|
|
279
|
+
attribute = GoodData::MdObject[attr_uri, project: target, client: target.client]
|
|
265
280
|
|
|
266
|
-
if
|
|
267
|
-
|
|
281
|
+
if attribute
|
|
282
|
+
drill_path = GoodData::MdObject.identifier_to_uri({ project: target, client: target.client }, drill_path_identifier)
|
|
283
|
+
next unless drill_path
|
|
284
|
+
|
|
285
|
+
if !attribute.content['drillDownStepAttributeDF'] || attribute.content['drillDownStepAttributeDF'] != drill_path
|
|
268
286
|
semaphore.synchronize do
|
|
269
|
-
GoodData.logger.info "Updating drill path of #{
|
|
287
|
+
GoodData.logger.info "Updating drill path of #{attr_identifier} -> #{drill_path} in '#{target.title}'"
|
|
270
288
|
end
|
|
271
289
|
|
|
272
|
-
|
|
273
|
-
|
|
290
|
+
attribute.content['drillDownStepAttributeDF'] = drill_path
|
|
291
|
+
attribute.save
|
|
274
292
|
end
|
|
275
293
|
else
|
|
276
294
|
semaphore.synchronize do
|
|
277
|
-
GoodData.logger.warn "Unable to find #{
|
|
295
|
+
GoodData.logger.warn "Unable to find #{attr_identifier} in '#{target.title}'"
|
|
278
296
|
end
|
|
279
297
|
end
|
|
280
298
|
|
data/lib/gooddata/lcm/lcm2.rb
CHANGED
|
@@ -16,8 +16,16 @@ module GoodData
|
|
|
16
16
|
def method_missing(name, *_args)
|
|
17
17
|
key = name.to_s.downcase.to_sym
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
value = nil
|
|
20
|
+
keys.each do |k|
|
|
21
|
+
if k.to_s.downcase.to_sym == key
|
|
22
|
+
value = self[k]
|
|
23
|
+
break
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if value
|
|
28
|
+
value
|
|
21
29
|
else
|
|
22
30
|
begin
|
|
23
31
|
super
|
|
@@ -27,6 +35,16 @@ module GoodData
|
|
|
27
35
|
end
|
|
28
36
|
end
|
|
29
37
|
|
|
38
|
+
def key?(key)
|
|
39
|
+
return true if super
|
|
40
|
+
|
|
41
|
+
keys.each do |k|
|
|
42
|
+
return true if k.to_s.downcase.to_sym == key.to_s.downcase.to_sym
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
false
|
|
46
|
+
end
|
|
47
|
+
|
|
30
48
|
def respond_to_missing?(name, *_args)
|
|
31
49
|
key = name.to_s.downcase.to_sym
|
|
32
50
|
key?(key)
|
|
@@ -68,6 +86,7 @@ module GoodData
|
|
|
68
86
|
EnsureTechnicalUsersProject,
|
|
69
87
|
SynchronizeLdm,
|
|
70
88
|
SynchronizeMeta,
|
|
89
|
+
SynchronizeLabelTypes,
|
|
71
90
|
SynchronizeAttributeDrillpath,
|
|
72
91
|
SynchronizeProcesses,
|
|
73
92
|
SynchronizeSchedules,
|
|
@@ -86,10 +105,9 @@ module GoodData
|
|
|
86
105
|
ProvisionClients,
|
|
87
106
|
EnsureTechnicalUsersDomain,
|
|
88
107
|
EnsureTechnicalUsersProject,
|
|
89
|
-
EnsureTitles,
|
|
90
108
|
SynchronizeAttributeDrillpath,
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
SynchronizeETLsInSegment,
|
|
110
|
+
SynchronizeColorPalette
|
|
93
111
|
],
|
|
94
112
|
|
|
95
113
|
rollout: [
|
|
@@ -102,9 +120,10 @@ module GoodData
|
|
|
102
120
|
SynchronizeLdm,
|
|
103
121
|
# SynchronizeLabelTypes,
|
|
104
122
|
SynchronizeAttributeDrillpath,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
SynchronizeClients
|
|
123
|
+
ApplyCustomMaql,
|
|
124
|
+
SynchronizeColorPalette,
|
|
125
|
+
SynchronizeClients,
|
|
126
|
+
SynchronizeETLsInSegment
|
|
108
127
|
]
|
|
109
128
|
}
|
|
110
129
|
|
|
@@ -122,9 +141,9 @@ module GoodData
|
|
|
122
141
|
res = SmartHash.new
|
|
123
142
|
params.each_pair do |k, v|
|
|
124
143
|
if v.is_a?(Hash) || v.is_a?(Array)
|
|
125
|
-
res[k
|
|
144
|
+
res[k] = convert_to_smart_hash(v)
|
|
126
145
|
else
|
|
127
|
-
res[k
|
|
146
|
+
res[k] = v
|
|
128
147
|
end
|
|
129
148
|
end
|
|
130
149
|
res
|
|
@@ -138,7 +157,13 @@ module GoodData
|
|
|
138
157
|
end
|
|
139
158
|
|
|
140
159
|
def get_mode_actions(mode)
|
|
141
|
-
|
|
160
|
+
mode = mode.to_sym
|
|
161
|
+
actions = MODES[mode]
|
|
162
|
+
if mode == :generic_lifecycle
|
|
163
|
+
[]
|
|
164
|
+
else
|
|
165
|
+
actions || fail("Invalid mode specified '#{mode}', supported modes are: '#{MODE_NAMES.join(', ')}'")
|
|
166
|
+
end
|
|
142
167
|
end
|
|
143
168
|
|
|
144
169
|
def print_action_names(mode, actions)
|
|
@@ -166,12 +191,13 @@ module GoodData
|
|
|
166
191
|
keys = if action.const_defined?('RESULT_HEADER')
|
|
167
192
|
action.const_get('RESULT_HEADER')
|
|
168
193
|
else
|
|
194
|
+
GoodData.logger.warn("Action #{action.name} does not have RESULT_HEADERS, inferring headers from results.")
|
|
169
195
|
(messages.first && messages.first.keys) || []
|
|
170
196
|
end
|
|
171
197
|
|
|
172
198
|
headings = keys.map(&:upcase)
|
|
173
199
|
|
|
174
|
-
rows = messages.map do |message|
|
|
200
|
+
rows = messages && messages.map do |message|
|
|
175
201
|
row = []
|
|
176
202
|
keys.each do |heading|
|
|
177
203
|
row << message[heading]
|
|
@@ -179,6 +205,8 @@ module GoodData
|
|
|
179
205
|
row
|
|
180
206
|
end
|
|
181
207
|
|
|
208
|
+
rows ||= []
|
|
209
|
+
|
|
182
210
|
table = Terminal::Table.new :title => title, :headings => headings do |t|
|
|
183
211
|
rows.each_with_index do |row, index|
|
|
184
212
|
t << row
|
|
@@ -202,6 +230,17 @@ module GoodData
|
|
|
202
230
|
|
|
203
231
|
# Get actions for mode specified
|
|
204
232
|
actions = get_mode_actions(mode)
|
|
233
|
+
if params.actions
|
|
234
|
+
actions = params.actions.map do |action|
|
|
235
|
+
"GoodData::LCM2::#{action}".split('::').inject(Object) do |o, c|
|
|
236
|
+
begin
|
|
237
|
+
o.const_get(c)
|
|
238
|
+
rescue NameError
|
|
239
|
+
fail NameError, "Cannot find action 'GoodData::LCM2::#{action}'"
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
205
244
|
|
|
206
245
|
# Print name of actions to be performed for debug purposes
|
|
207
246
|
print_action_names(mode, actions)
|
|
@@ -210,12 +249,34 @@ module GoodData
|
|
|
210
249
|
|
|
211
250
|
new_params = params
|
|
212
251
|
|
|
252
|
+
fail_early = if params.key?(:fail_early)
|
|
253
|
+
params.fail_early.to_b
|
|
254
|
+
else
|
|
255
|
+
true
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
strict_mode = if params.key?(:strict)
|
|
259
|
+
params.strict.to_b
|
|
260
|
+
else
|
|
261
|
+
true
|
|
262
|
+
end
|
|
263
|
+
|
|
213
264
|
# Run actions
|
|
214
|
-
|
|
265
|
+
errors = []
|
|
266
|
+
results = []
|
|
267
|
+
actions.each do |action|
|
|
215
268
|
puts
|
|
216
269
|
|
|
217
270
|
# Invoke action
|
|
218
|
-
|
|
271
|
+
begin
|
|
272
|
+
out = action.send(:call, params)
|
|
273
|
+
rescue => e
|
|
274
|
+
errors << {
|
|
275
|
+
action: action,
|
|
276
|
+
err: e
|
|
277
|
+
}
|
|
278
|
+
break if fail_early
|
|
279
|
+
end
|
|
219
280
|
|
|
220
281
|
# Handle output results and params
|
|
221
282
|
res = out.is_a?(Array) ? out : out[:results]
|
|
@@ -229,10 +290,13 @@ module GoodData
|
|
|
229
290
|
puts
|
|
230
291
|
print_action_result(action, res)
|
|
231
292
|
|
|
232
|
-
#
|
|
233
|
-
res
|
|
293
|
+
# Store result for final summary
|
|
294
|
+
results << res
|
|
234
295
|
end
|
|
235
296
|
|
|
297
|
+
# Fail whole execution if there is any failed action
|
|
298
|
+
fail(JSON.pretty_generate(errors)) if strict_mode && errors.any?
|
|
299
|
+
|
|
236
300
|
if actions.length > 1
|
|
237
301
|
puts
|
|
238
302
|
puts 'SUMMARY'
|
|
@@ -244,13 +308,11 @@ module GoodData
|
|
|
244
308
|
|
|
245
309
|
brick_results = {}
|
|
246
310
|
actions.each_with_index do |action, index|
|
|
247
|
-
brick_results[action.
|
|
311
|
+
brick_results[action.short_name] = results[index]
|
|
248
312
|
end
|
|
249
313
|
|
|
250
314
|
{
|
|
251
|
-
actions: actions.map
|
|
252
|
-
action.class.short_name
|
|
253
|
-
end,
|
|
315
|
+
actions: actions.map(&:short_name),
|
|
254
316
|
results: brick_results,
|
|
255
317
|
params: params
|
|
256
318
|
}
|
|
@@ -241,19 +241,30 @@ module GoodData
|
|
|
241
241
|
|
|
242
242
|
list.pmapcat do |user|
|
|
243
243
|
begin
|
|
244
|
-
user_data = user.to_hash.tap { |uh| uh[:login].downcase }
|
|
244
|
+
user_data = user.to_hash.tap { |uh| uh[:login].downcase! }
|
|
245
245
|
domain_user = domain_users_cache[user_data[:login]]
|
|
246
|
+
user_login = user_data[:login]
|
|
246
247
|
if !domain_user
|
|
247
248
|
added_user = domain.add_user(user_data, opts)
|
|
249
|
+
GoodData.logger.info("Added new user=#{user_login} to domain=#{default_domain_name}.")
|
|
248
250
|
[{ type: :successful, :action => :user_added_to_domain, user: added_user }]
|
|
249
251
|
else
|
|
252
|
+
domain_user_data = domain_user.to_hash
|
|
250
253
|
fields_to_check = opts[:fields_to_check] || user_data.keys
|
|
251
254
|
diff = GoodData::Helpers.diff([domain_user.to_hash], [user_data], key: :login, fields: fields_to_check)
|
|
252
255
|
next [] if diff[:changed].empty?
|
|
253
256
|
updated_user = domain.update_user(domain_user.to_hash.merge(user_data.compact), opts)
|
|
257
|
+
GoodData.logger.debug "Updated user=#{user_login} from old properties \
|
|
258
|
+
(email=#{domain_user_data[:email]}, sso_provider=#{domain_user_data[:sso_provider]}) \
|
|
259
|
+
to new properties (email=#{user_data[:email]}, sso_provider=#{user_data[:sso_provider]}) in domain=#{default_domain_name}."
|
|
254
260
|
[{ type: :successful, :action => :user_changed_in_domain, user: updated_user }]
|
|
255
261
|
end
|
|
256
262
|
rescue RuntimeError => e
|
|
263
|
+
if !domain_user
|
|
264
|
+
GoodData.logger.error("Failed to add user=#{user_login} to domain=#{default_domain_name}. Error: #{e.message}")
|
|
265
|
+
else
|
|
266
|
+
GoodData.logger.error("Failed to update user=#{user_login} in domain=#{default_domain_name}. Error: #{e.message}")
|
|
267
|
+
end
|
|
257
268
|
[{ type: :failed, :user => user, message: e }]
|
|
258
269
|
end
|
|
259
270
|
end
|
|
@@ -431,6 +442,10 @@ module GoodData
|
|
|
431
442
|
alias_method :add_clients_settings, :update_clients_settings
|
|
432
443
|
|
|
433
444
|
def update_clients(data, options = {})
|
|
445
|
+
if options[:delete_extra] && options[:delete_extra_in_segments]
|
|
446
|
+
fail 'Options delete_extra and delete_extra_in_segments are mutually exclusive.'
|
|
447
|
+
end
|
|
448
|
+
|
|
434
449
|
delete_projects = options[:delete_projects] == false ? false : true
|
|
435
450
|
payload = data.map do |datum|
|
|
436
451
|
{
|
|
@@ -444,6 +459,12 @@ module GoodData
|
|
|
444
459
|
end
|
|
445
460
|
if options[:delete_extra] == true
|
|
446
461
|
res = client.post(segments_uri + '/updateClients?deleteExtra=true', updateClients: { items: payload })
|
|
462
|
+
elsif options[:delete_extra_in_segments]
|
|
463
|
+
segments_to_delete_in = options[:delete_extra_in_segments]
|
|
464
|
+
.map { |segment| CGI.escape(segment) }
|
|
465
|
+
.join(',')
|
|
466
|
+
uri = segments_uri + "/updateClients?deleteExtraInSegments=#{segments_to_delete_in}"
|
|
467
|
+
res = client.post(uri, updateClients: { items: payload })
|
|
447
468
|
else
|
|
448
469
|
res = client.post(segments_uri + '/updateClients', updateClients: { items: payload })
|
|
449
470
|
end
|