gooddata 0.6.10 → 0.6.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/README.md +1 -0
- data/gooddata.gemspec +38 -40
- data/lib/gooddata/bricks/base_downloader.rb +1 -1
- data/lib/gooddata/bricks/middleware/base_middleware.rb +36 -0
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +8 -38
- data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +14 -0
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +7 -6
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +7 -5
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +1 -1
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +20 -14
- data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +33 -0
- data/lib/gooddata/cli/commands/api_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/console_cmd.rb +2 -2
- data/lib/gooddata/cli/commands/process_cmd.rb +54 -7
- data/lib/gooddata/cli/commands/project_cmd.rb +9 -9
- data/lib/gooddata/cli/commands/projects_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +24 -7
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +2 -2
- data/lib/gooddata/cli/commands/user_cmd.rb +1 -1
- data/lib/gooddata/cli/hooks.rb +3 -3
- data/lib/gooddata/commands/datasets.rb +1 -1
- data/lib/gooddata/commands/project.rb +2 -2
- data/lib/gooddata/commands/role.rb +1 -1
- data/lib/gooddata/commands/runners.rb +2 -2
- data/lib/gooddata/connection.rb +2 -2
- data/lib/gooddata/core/nil_logger.rb +1 -1
- data/lib/gooddata/core/rest.rb +12 -8
- data/lib/gooddata/data/guesser.rb +1 -1
- data/lib/gooddata/exceptions/attr_element_not_found.rb +1 -1
- data/lib/gooddata/extensions/enumerable.rb +1 -1
- data/lib/gooddata/extensions/hash.rb +20 -0
- data/lib/gooddata/helpers/csv_helper.rb +1 -1
- data/lib/gooddata/helpers/global_helpers.rb +59 -1
- data/lib/gooddata/mixins/md_lock.rb +83 -0
- data/lib/gooddata/mixins/md_object_indexer.rb +1 -1
- data/lib/gooddata/mixins/md_object_query.rb +1 -1
- data/lib/gooddata/mixins/md_relations.rb +0 -9
- data/lib/gooddata/models/dashboard_builder.rb +1 -1
- data/lib/gooddata/models/domain.rb +2 -2
- data/lib/gooddata/models/empty_result.rb +5 -5
- data/lib/gooddata/models/execution.rb +74 -0
- data/lib/gooddata/models/execution_detail.rb +74 -0
- data/lib/gooddata/models/membership.rb +1 -1
- data/lib/gooddata/models/metadata/attribute.rb +4 -6
- data/lib/gooddata/models/metadata/dashboard.rb +2 -0
- data/lib/gooddata/models/metadata/fact.rb +2 -2
- data/lib/gooddata/models/metadata/metric.rb +4 -1
- data/lib/gooddata/models/metadata/report.rb +84 -34
- data/lib/gooddata/models/metadata/report_definition.rb +28 -17
- data/lib/gooddata/models/metadata.rb +1 -1
- data/lib/gooddata/models/model.rb +1 -1
- data/lib/gooddata/models/process.rb +70 -54
- data/lib/gooddata/models/profile.rb +47 -10
- data/lib/gooddata/models/project.rb +74 -30
- data/lib/gooddata/models/project_blueprint.rb +9 -10
- data/lib/gooddata/models/project_builder.rb +2 -2
- data/lib/gooddata/models/project_creator.rb +4 -4
- data/lib/gooddata/models/report_data_result.rb +1 -1
- data/lib/gooddata/models/schedule.rb +39 -32
- data/lib/gooddata/models/to_manifest.rb +5 -5
- data/lib/gooddata/models/to_wire.rb +3 -3
- data/lib/gooddata/rest/client.rb +64 -31
- data/lib/gooddata/rest/connection.rb +7 -7
- data/lib/gooddata/rest/connections/dummy_connection.rb +5 -5
- data/lib/gooddata/rest/connections/rest_client_connection.rb +106 -44
- data/lib/gooddata/rest/object.rb +1 -1
- data/lib/gooddata/version.rb +1 -1
- data/spec/bricks/bricks_spec.rb +67 -0
- data/spec/bricks/default-config.json +8 -0
- data/spec/data/gooddata_version_process/gooddata_version.rb +3 -0
- data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
- data/spec/data/ruby_params_process/ruby_params.rb +3 -0
- data/spec/helpers/process_helper.rb +12 -0
- data/spec/helpers/schedule_helper.rb +21 -0
- data/spec/integration/create_project_spec.rb +19 -0
- data/spec/integration/full_process_schedule_spec.rb +129 -8
- data/spec/integration/full_project_spec.rb +52 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/core/rest_spec.rb +76 -3
- data/spec/unit/helpers_spec.rb +43 -0
- data/spec/unit/models/metric_spec.rb +33 -0
- data/spec/unit/models/params_spec.rb +96 -0
- data/spec/unit/models/profile_spec.rb +16 -0
- data/spec/unit/models/schedule_spec.rb +12 -3
- metadata +350 -187
- data/lib/gooddata/helper/class_helper.rb +0 -1
- data/lib/gooddata/helper/helpers.rb +0 -8
@@ -1,9 +1,14 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
require 'pry'
|
4
|
+
require 'zip'
|
4
5
|
|
6
|
+
require_relative '../helpers/global_helpers'
|
5
7
|
require_relative '../rest/resource'
|
6
8
|
|
9
|
+
require_relative 'execution_detail'
|
10
|
+
require_relative 'schedule'
|
11
|
+
|
7
12
|
module GoodData
|
8
13
|
class Process < GoodData::Rest::Object
|
9
14
|
attr_reader :data
|
@@ -82,48 +87,7 @@ module GoodData
|
|
82
87
|
project = GoodData::Project[p, opts]
|
83
88
|
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
84
89
|
|
85
|
-
|
86
|
-
puts 'Creating package for upload'
|
87
|
-
Tempfile.open('deploy-graph-archive') do |temp|
|
88
|
-
Zip::OutputStream.open(temp.path) do |zio|
|
89
|
-
FileUtils.cd(path.parent) do
|
90
|
-
files_to_pack = [path.basename]
|
91
|
-
files_to_pack.each do |item|
|
92
|
-
puts "including #{item}"
|
93
|
-
unless File.directory?(item)
|
94
|
-
zio.put_next_entry(item)
|
95
|
-
zio.print IO.read(item)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
client.upload_to_user_webdav(temp.path, opts)
|
102
|
-
temp.path
|
103
|
-
end
|
104
|
-
elsif !path.directory?
|
105
|
-
client.upload_to_user_webdav(path, opts)
|
106
|
-
path
|
107
|
-
else
|
108
|
-
Tempfile.open('deploy-graph-archive') do |temp|
|
109
|
-
Zip::OutputStream.open(temp.path) do |zio|
|
110
|
-
FileUtils.cd(path) do
|
111
|
-
|
112
|
-
files_to_pack = Dir.glob('./**/*').reject { |f| files_to_exclude.include?(Pathname(path) + f) }
|
113
|
-
files_to_pack.each do |item|
|
114
|
-
puts "including #{item}"
|
115
|
-
unless File.directory?(item)
|
116
|
-
zio.put_next_entry(item)
|
117
|
-
zio.print IO.read(item)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
client.upload_to_user_webdav(temp.path, opts)
|
124
|
-
temp.path
|
125
|
-
end
|
126
|
-
end
|
90
|
+
zip_and_upload path, files_to_exclude, opts
|
127
91
|
end
|
128
92
|
|
129
93
|
# Deploy a new process or redeploy existing one.
|
@@ -134,7 +98,7 @@ module GoodData
|
|
134
98
|
# @option options [String] :name Readable name of the process
|
135
99
|
# @option options [String] :process_id ID of a process to be redeployed (do not set if you want to create a new process)
|
136
100
|
# @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging
|
137
|
-
def deploy(path, options = {})
|
101
|
+
def deploy(path, options = { :client => GoodData.client, :project => GoodData.project })
|
138
102
|
client = options[:client]
|
139
103
|
fail ArgumentError, 'No :client specified' if client.nil?
|
140
104
|
|
@@ -174,6 +138,46 @@ module GoodData
|
|
174
138
|
puts HighLine.color("Deploy DONE #{path}", HighLine::GREEN) if verbose
|
175
139
|
process
|
176
140
|
end
|
141
|
+
|
142
|
+
# ----------------------------- Private Stuff
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def zip_and_upload(path, files_to_exclude, opts = {})
|
147
|
+
def with_zip(opts = {})
|
148
|
+
Tempfile.open('deploy-graph-archive') do |temp|
|
149
|
+
zip_filename = temp.path
|
150
|
+
File.open(zip_filename, 'w') do |zip|
|
151
|
+
Zip::File.open(zip.path, Zip::File::CREATE) do |zipfile|
|
152
|
+
yield zipfile
|
153
|
+
end
|
154
|
+
end
|
155
|
+
client.upload_to_user_webdav(temp.path, opts)
|
156
|
+
temp.path
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
puts 'Creating package for upload'
|
161
|
+
if !path.directory? && (path.extname == '.grf' || path.extname == '.rb')
|
162
|
+
with_zip(opts) do |zipfile|
|
163
|
+
zipfile.add(File.basename(path), path)
|
164
|
+
end
|
165
|
+
|
166
|
+
elsif !path.directory?
|
167
|
+
client.upload_to_user_webdav(path, opts)
|
168
|
+
path
|
169
|
+
else
|
170
|
+
with_zip(opts) do |zipfile|
|
171
|
+
Dir[File.join(path, '**', '**')].reject { |f| files_to_exclude.include?(Pathname(path) + f) }.each do |file|
|
172
|
+
file_pathname = Pathname.new(file)
|
173
|
+
puts "Including item #{file_pathname}"
|
174
|
+
file_relative_pathname = file_pathname.relative_path_from(Pathname.new(path))
|
175
|
+
zipfile.add(file_relative_pathname, file)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
# -----------------------------
|
177
181
|
end
|
178
182
|
|
179
183
|
def initialize(data)
|
@@ -193,7 +197,15 @@ module GoodData
|
|
193
197
|
# @option options [String] :name Readable name of the process
|
194
198
|
# @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging
|
195
199
|
def deploy(path, options = {})
|
196
|
-
Process.deploy(path, options.merge(:process_id => process_id))
|
200
|
+
Process.deploy(path, options.merge(:process_id => process_id, :client => client, :project => project))
|
201
|
+
end
|
202
|
+
|
203
|
+
# Downloads the process from S3 in a zipped form.
|
204
|
+
#
|
205
|
+
# @return [IO] The stream of data that represents a zipped deployed process.
|
206
|
+
def download
|
207
|
+
link = links['source']
|
208
|
+
client.get(link, process: false) { |_, _, result| RestClient.get(result.to_hash['location'].first) }
|
197
209
|
end
|
198
210
|
|
199
211
|
def process
|
@@ -245,14 +257,7 @@ module GoodData
|
|
245
257
|
end
|
246
258
|
|
247
259
|
def execute(executable, options = {})
|
248
|
-
|
249
|
-
hidden_params = options[:hidden_params] || {}
|
250
|
-
result = client.post(executions_link,
|
251
|
-
:execution => {
|
252
|
-
:graph => executable.to_s,
|
253
|
-
:params => params,
|
254
|
-
:hiddenParams => hidden_params
|
255
|
-
})
|
260
|
+
result = start_execution(executable, options)
|
256
261
|
begin
|
257
262
|
client.poll_on_code(result['executionTask']['links']['poll'])
|
258
263
|
rescue RestClient::RequestFailed => e
|
@@ -260,10 +265,21 @@ module GoodData
|
|
260
265
|
ensure
|
261
266
|
result = client.get(result['executionTask']['links']['detail'])
|
262
267
|
if result['executionDetail']['status'] == 'ERROR'
|
263
|
-
fail "Runing process failed. You can look at a log here #{result[
|
268
|
+
fail "Runing process failed. You can look at a log here #{result['executionDetail']['logFileName']}"
|
264
269
|
end
|
265
270
|
end
|
266
|
-
result
|
271
|
+
client.create(GoodData::ExecutionDetail, result, client: client, project: project)
|
272
|
+
end
|
273
|
+
|
274
|
+
def start_execution(executable, options = {})
|
275
|
+
params = options[:params] || {}
|
276
|
+
hidden_params = options[:hidden_params] || {}
|
277
|
+
client.post(executions_link,
|
278
|
+
:execution => {
|
279
|
+
:graph => executable.to_s,
|
280
|
+
:params => GoodData::Helpers.encode_params(params, false),
|
281
|
+
:hiddenParams => GoodData::Helpers.encode_params(hidden_params, true)
|
282
|
+
})
|
267
283
|
end
|
268
284
|
end
|
269
285
|
end
|
@@ -43,7 +43,31 @@ module GoodData
|
|
43
43
|
:timezone
|
44
44
|
]
|
45
45
|
|
46
|
+
PROFILE_PATH = '/gdc/account/profile/%s'
|
47
|
+
|
46
48
|
class << self
|
49
|
+
# Get profile by ID or URI
|
50
|
+
#
|
51
|
+
# @param id ID or URI of user to be found
|
52
|
+
# @param [Hash] opts Additional optional options
|
53
|
+
# @option opts [GoodData::Rest::Client] :client Client used for communication with server
|
54
|
+
# @return GoodData::Profile User Profile
|
55
|
+
def [](id, opts = { client: GoodData.connection })
|
56
|
+
return id if id.instance_of?(GoodData::Profile) || id.respond_to?(:profile?) && id.profile?
|
57
|
+
|
58
|
+
if id.to_s !~ %r{^(\/gdc\/account\/profile\/)?[a-zA-Z\d]+$}
|
59
|
+
fail(ArgumentError, 'wrong type of argument. Should be either project ID or path')
|
60
|
+
end
|
61
|
+
|
62
|
+
id = id.match(/[a-zA-Z\d]+$/)[0] if id =~ /\//
|
63
|
+
|
64
|
+
c = client(opts)
|
65
|
+
fail ArgumentError, 'No :client specified' if c.nil?
|
66
|
+
|
67
|
+
response = c.get(PROFILE_PATH % id)
|
68
|
+
c.factory.create(Profile, response)
|
69
|
+
end
|
70
|
+
|
47
71
|
# Apply changes to object.
|
48
72
|
#
|
49
73
|
# @param obj [GoodData::Profile] Object to be modified
|
@@ -110,13 +134,13 @@ module GoodData
|
|
110
134
|
next
|
111
135
|
end
|
112
136
|
|
113
|
-
if user_existing
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
137
|
+
next if user_existing == user_new
|
138
|
+
|
139
|
+
diff = self.diff(user_existing, user_new)
|
140
|
+
res[:changed] << {
|
141
|
+
:user => user_existing,
|
142
|
+
:diff => diff
|
143
|
+
}
|
120
144
|
end
|
121
145
|
|
122
146
|
tmp = Hash[list2.map { |v| [v.email, v] }]
|
@@ -250,6 +274,15 @@ module GoodData
|
|
250
274
|
@json['accountSetting']['firstName'] = val
|
251
275
|
end
|
252
276
|
|
277
|
+
# Get full name
|
278
|
+
#
|
279
|
+
# @return String Full Name
|
280
|
+
def full_name
|
281
|
+
"#{first_name} #{last_name}"
|
282
|
+
end
|
283
|
+
|
284
|
+
alias_method :title, :full_name
|
285
|
+
|
253
286
|
# Gets the last name
|
254
287
|
#
|
255
288
|
# @return [String] Last name
|
@@ -293,17 +326,21 @@ module GoodData
|
|
293
326
|
#
|
294
327
|
# @return [String] Phone
|
295
328
|
def phone
|
296
|
-
@json['accountSetting']['
|
329
|
+
@json['accountSetting']['phoneNumber'] || ''
|
297
330
|
end
|
298
331
|
|
332
|
+
alias_method :phone_number, :phone
|
333
|
+
|
299
334
|
# Set the phone
|
300
335
|
#
|
301
336
|
# @param val [String] Phone to be set
|
302
337
|
def phone=(val)
|
303
338
|
@dirty ||= phone != val
|
304
|
-
@json['accountSetting']['
|
339
|
+
@json['accountSetting']['phoneNumber'] = val
|
305
340
|
end
|
306
341
|
|
342
|
+
alias_method :phone_number=, :phone=
|
343
|
+
|
307
344
|
# Gets the position in company
|
308
345
|
#
|
309
346
|
# @return [String] Position in company
|
@@ -331,7 +368,7 @@ module GoodData
|
|
331
368
|
|
332
369
|
# Saves object if dirty, clears dirty flag
|
333
370
|
def save!
|
334
|
-
if @dirty
|
371
|
+
if @dirty # rubocop:disable Style/GuardClause
|
335
372
|
raw = @json.dup
|
336
373
|
raw['accountSetting'].delete('login')
|
337
374
|
|
@@ -51,7 +51,7 @@ module GoodData
|
|
51
51
|
# - /gdc/projects/<id>
|
52
52
|
# - <id>
|
53
53
|
#
|
54
|
-
def [](id, opts = {})
|
54
|
+
def [](id, opts = { client: GoodData.connection })
|
55
55
|
return id if id.instance_of?(GoodData::Project) || id.respond_to?(:project?) && id.project?
|
56
56
|
|
57
57
|
if id == :all
|
@@ -83,8 +83,8 @@ module GoodData
|
|
83
83
|
c = client(opts)
|
84
84
|
fail ArgumentError, 'No :client specified' if c.nil?
|
85
85
|
|
86
|
-
auth_token = opts[:auth_token]
|
87
|
-
fail 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
|
86
|
+
auth_token = opts[:auth_token]
|
87
|
+
fail ArgumentError, 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
|
88
88
|
|
89
89
|
json = {
|
90
90
|
'project' =>
|
@@ -123,7 +123,7 @@ module GoodData
|
|
123
123
|
project
|
124
124
|
end
|
125
125
|
|
126
|
-
def find(
|
126
|
+
def find(_opts = {}, client = GoodData::Rest::Client.client)
|
127
127
|
user = client.user
|
128
128
|
user.projects['projects'].map do |project|
|
129
129
|
client.create(GoodData::Project, project)
|
@@ -157,17 +157,34 @@ module GoodData
|
|
157
157
|
if metric.is_a?(String)
|
158
158
|
GoodData::Metric.xcreate(metric, options.merge(default))
|
159
159
|
else
|
160
|
-
GoodData::Metric.xcreate(metric.merge(default))
|
160
|
+
GoodData::Metric.xcreate(options[:expression], metric.merge(options.merge(default)))
|
161
161
|
end
|
162
162
|
end
|
163
163
|
alias_method :create_metric, :add_metric
|
164
164
|
|
165
|
+
# Creates new instance of report in context of project
|
166
|
+
#
|
167
|
+
# @param [options] Optional report options
|
168
|
+
# @return [GoodData::Report] Instance of new report
|
165
169
|
def add_report(options = {})
|
166
170
|
rep = GoodData::Report.create(options.merge(client: client, project: self))
|
167
171
|
rep.save
|
168
172
|
end
|
169
173
|
alias_method :create_report, :add_report
|
170
174
|
|
175
|
+
# Creates new instance of report definition in context of project
|
176
|
+
# This report definition can be used for creating of GoodData::Report
|
177
|
+
#
|
178
|
+
# @param [json] Raw report definition json
|
179
|
+
# @return [GoodData::ReportDefinition] Instance of new report definition
|
180
|
+
def add_report_definition(json)
|
181
|
+
rd = GoodData::ReportDefinition.new(json)
|
182
|
+
rd.client = client
|
183
|
+
rd.project = self
|
184
|
+
rd.save
|
185
|
+
end
|
186
|
+
alias_method :create_report_definition, :add_report_definition
|
187
|
+
|
171
188
|
# Returns an indication whether current user is admin in this project
|
172
189
|
#
|
173
190
|
# @return [Boolean] True if user has admin role in the project, false otherwise.
|
@@ -215,15 +232,38 @@ module GoodData
|
|
215
232
|
|
216
233
|
# Clones project
|
217
234
|
#
|
235
|
+
# @param options [Hash] Export options
|
236
|
+
# @option options [Boolean] :data Clone project with data
|
237
|
+
# @option options [Boolean] :users Clone project with users
|
238
|
+
# @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
|
218
239
|
# @return [GoodData::Project] Newly created project
|
219
240
|
def clone(options = {})
|
220
|
-
# TODO: Refactor so if export or import fails the new_project will be cleaned
|
221
|
-
with_data = options[:data].nil? ? true : options[:data]
|
222
|
-
with_users = options[:users].nil? ? false : options[:users]
|
223
241
|
a_title = options[:title] || "Clone of #{title}"
|
224
242
|
|
225
|
-
|
226
|
-
|
243
|
+
begin
|
244
|
+
# Create the project first so we know that it is passing.
|
245
|
+
# What most likely is wrong is the token and the export actaully takes majority of the time
|
246
|
+
new_project = GoodData::Project.create(options.merge(:title => a_title, :client => client))
|
247
|
+
export_token = export_clone(options)
|
248
|
+
new_project.import_clone(export_token)
|
249
|
+
rescue
|
250
|
+
new_project.delete if new_project
|
251
|
+
raise
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Export a clone from a project to be later imported.
|
256
|
+
# If you do not want to do anything special and you do not need fine grained
|
257
|
+
# controle use clone method which does all the heavy lifting for you.
|
258
|
+
#
|
259
|
+
# @param options [Hash] Export options
|
260
|
+
# @option options [Boolean] :data Clone project with data
|
261
|
+
# @option options [Boolean] :users Clone project with users
|
262
|
+
# @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
|
263
|
+
# @return [String] token of the export
|
264
|
+
def export_clone(options = {})
|
265
|
+
with_data = options[:data].nil? ? true : options[:data]
|
266
|
+
with_users = options[:users].nil? ? false : options[:users]
|
227
267
|
|
228
268
|
export = {
|
229
269
|
:exportProject => {
|
@@ -231,28 +271,34 @@ module GoodData
|
|
231
271
|
:exportData => with_data ? 1 : 0
|
232
272
|
}
|
233
273
|
}
|
274
|
+
export[:exportProject][:authorizedUsers] = options[:authorized_users] if options[:authorized_users]
|
234
275
|
|
235
276
|
result = client.post("/gdc/md/#{obj_id}/maintenance/export", export)
|
236
|
-
export_token = result['exportArtifact']['token']
|
237
|
-
|
238
277
|
status_url = result['exportArtifact']['status']['uri']
|
239
278
|
client.poll_on_response(status_url) do |body|
|
240
279
|
body['taskState']['status'] == 'RUNNING'
|
241
280
|
end
|
281
|
+
result['exportArtifact']['token']
|
282
|
+
end
|
242
283
|
|
284
|
+
# Imports a clone into current project. The project has to be freshly
|
285
|
+
# created.
|
286
|
+
#
|
287
|
+
# @param export_token [String] Export token of the package to be imported
|
288
|
+
# @return [Project] current project
|
289
|
+
def import_clone(export_token)
|
243
290
|
import = {
|
244
291
|
:importProject => {
|
245
292
|
:token => export_token
|
246
293
|
}
|
247
294
|
}
|
248
295
|
|
249
|
-
result = client.post("/gdc/md/#{
|
296
|
+
result = client.post("/gdc/md/#{obj_id}/maintenance/import", import)
|
250
297
|
status_url = result['uri']
|
251
298
|
client.poll_on_response(status_url) do |body|
|
252
299
|
body['taskState']['status'] == 'RUNNING'
|
253
300
|
end
|
254
|
-
|
255
|
-
new_project
|
301
|
+
self
|
256
302
|
end
|
257
303
|
|
258
304
|
def compute_report(spec = {})
|
@@ -298,7 +344,7 @@ module GoodData
|
|
298
344
|
|
299
345
|
# Deletes dashboards for project
|
300
346
|
def delete_dashboards
|
301
|
-
Dashboard.all.map { |data| Dashboard[data['link']] }.each
|
347
|
+
Dashboard.all.map { |data| Dashboard[data['link']] }.each(&:delete)
|
302
348
|
end
|
303
349
|
|
304
350
|
def deploy_process(path, options = {})
|
@@ -400,10 +446,10 @@ module GoodData
|
|
400
446
|
role_name.downcase!
|
401
447
|
role_list.each do |role|
|
402
448
|
return role if role.uri == role_name ||
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
449
|
+
role.identifier.downcase == role_name ||
|
450
|
+
role.identifier.downcase.gsub(/role$/, '') == role_name ||
|
451
|
+
role.title.downcase == role_name ||
|
452
|
+
role.summary.downcase == role_name
|
407
453
|
end
|
408
454
|
nil
|
409
455
|
end
|
@@ -419,14 +465,14 @@ module GoodData
|
|
419
465
|
name.downcase!
|
420
466
|
user_list.each do |user|
|
421
467
|
return user if user.uri.downcase == name ||
|
422
|
-
|
423
|
-
|
468
|
+
user.login.downcase == name ||
|
469
|
+
user.email.downcase == name
|
424
470
|
end
|
425
471
|
nil
|
426
472
|
end
|
427
473
|
|
428
474
|
# Exports project users to file
|
429
|
-
def import_users(path, opts = { :header => true }, &
|
475
|
+
def import_users(path, opts = { :header => true }, &_block)
|
430
476
|
opts[:path] = path
|
431
477
|
|
432
478
|
##########################
|
@@ -609,7 +655,7 @@ module GoodData
|
|
609
655
|
# @return [GoodData::Fact | Array<GoodData::Fact>] fact instance or list
|
610
656
|
def labels(id = :all, opts = {})
|
611
657
|
if id == :all
|
612
|
-
attributes.pmapcat
|
658
|
+
attributes.pmapcat(&:labels).uniq
|
613
659
|
else
|
614
660
|
GoodData::Label[id, opts.merge(project: self, client: client)]
|
615
661
|
end
|
@@ -700,7 +746,7 @@ module GoodData
|
|
700
746
|
objs = objs.pmap { |obj| objects(obj) }
|
701
747
|
export_payload = {
|
702
748
|
:partialMDExport => {
|
703
|
-
:uris => objs.map
|
749
|
+
:uris => objs.map(&:uri)
|
704
750
|
}
|
705
751
|
}
|
706
752
|
result = client.post("#{md['maintenance']}/partialmdexport", export_payload)
|
@@ -961,7 +1007,7 @@ module GoodData
|
|
961
1007
|
list = list.map do |user|
|
962
1008
|
{
|
963
1009
|
:user => user,
|
964
|
-
:roles => new_users_map[user.email].json['user']['content']['role'].split(' ').map
|
1010
|
+
:roles => new_users_map[user.email].json['user']['content']['role'].split(' ').map(&:downcase).sort
|
965
1011
|
}
|
966
1012
|
end
|
967
1013
|
|
@@ -976,9 +1022,7 @@ module GoodData
|
|
976
1022
|
#
|
977
1023
|
# @param list List of users to be disabled
|
978
1024
|
def users_remove(list)
|
979
|
-
list.pmap
|
980
|
-
user.disable
|
981
|
-
end
|
1025
|
+
list.pmap(&:disable)
|
982
1026
|
end
|
983
1027
|
|
984
1028
|
# Update user
|
@@ -1022,7 +1066,7 @@ module GoodData
|
|
1022
1066
|
#
|
1023
1067
|
# @param list List of users to be updated
|
1024
1068
|
# @param role_list Optional list of cached roles to prevent unnecessary server round-trips
|
1025
|
-
def set_users_roles(list,
|
1069
|
+
def set_users_roles(list, _role_list = roles)
|
1026
1070
|
list.pmap do |user_hash|
|
1027
1071
|
user = user_hash[:user]
|
1028
1072
|
roles = user_hash[:role] || user_hash[:roles]
|
@@ -353,16 +353,15 @@ module GoodData
|
|
353
353
|
def lint(full = false)
|
354
354
|
errors = []
|
355
355
|
find_star_centers.each do |dataset|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
end
|
356
|
+
next unless dataset.anchor?
|
357
|
+
errors << {
|
358
|
+
type: :anchor_on_fact_dataset,
|
359
|
+
dataset_name: dataset.name,
|
360
|
+
anchor_name: dataset.anchor[:name]
|
361
|
+
}
|
363
362
|
end
|
364
363
|
|
365
|
-
date_facts = datasets.mapcat
|
364
|
+
date_facts = datasets.mapcat(&:date_facts)
|
366
365
|
date_facts.each do |date_fact|
|
367
366
|
errors << {
|
368
367
|
type: :date_fact,
|
@@ -414,7 +413,7 @@ module GoodData
|
|
414
413
|
when :stupid
|
415
414
|
reports = suggest_metrics.reduce([]) do |a, e|
|
416
415
|
star, metrics = e
|
417
|
-
metrics.each
|
416
|
+
metrics.each(&:save)
|
418
417
|
reports_stubs = metrics.map do |m|
|
419
418
|
breaks = can_break(star).map { |ds, aM| ds.identifier_for(aM) }
|
420
419
|
# [breaks.sample((breaks.length/10.0).ceil), m]
|
@@ -443,7 +442,7 @@ module GoodData
|
|
443
442
|
# @return [Array<Hash>]
|
444
443
|
def suggest_metrics
|
445
444
|
stars = find_star_centers
|
446
|
-
metrics = stars.map
|
445
|
+
metrics = stars.map(&:suggest_metrics)
|
447
446
|
stars.zip(metrics)
|
448
447
|
end
|
449
448
|
|
@@ -15,7 +15,7 @@ module GoodData
|
|
15
15
|
pb
|
16
16
|
end
|
17
17
|
|
18
|
-
def create(title,
|
18
|
+
def create(title, _options = {}, &block)
|
19
19
|
pb = ProjectBuilder.new(title)
|
20
20
|
block.call(pb)
|
21
21
|
pb
|
@@ -104,7 +104,7 @@ module GoodData
|
|
104
104
|
eliminate_empty = options[:eliminate_empty] || false
|
105
105
|
|
106
106
|
if eliminate_empty
|
107
|
-
JSON.pretty_generate(to_hash.reject { |
|
107
|
+
JSON.pretty_generate(to_hash.reject { |_k, v| v.is_a?(Enumerable) && v.empty? })
|
108
108
|
else
|
109
109
|
JSON.pretty_generate(to_hash)
|
110
110
|
end
|
@@ -66,7 +66,7 @@ module GoodData
|
|
66
66
|
# pp response
|
67
67
|
while response.code != 200
|
68
68
|
sleep 1
|
69
|
-
|
69
|
+
GoodData::Rest::Client.retryable(:tries => 3, :on => RestClient::InternalServerError) do
|
70
70
|
sleep 1
|
71
71
|
response = client.get(link, :process => false)
|
72
72
|
# pp response
|
@@ -106,7 +106,7 @@ module GoodData
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
def migrate_users(
|
109
|
+
def migrate_users(_project, spec)
|
110
110
|
spec.each do |user|
|
111
111
|
puts "Would migrate user #{user}"
|
112
112
|
# project.add_user(user)
|
@@ -114,7 +114,7 @@ module GoodData
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def load(project, spec)
|
117
|
-
if spec.key?(:uploads)
|
117
|
+
if spec.key?(:uploads) # rubocop:disable Style/GuardClause
|
118
118
|
spec[:uploads].each do |load|
|
119
119
|
schema = GoodData::Model::Schema.new(spec[:datasets].find { |d| d[:name] == load[:dataset] })
|
120
120
|
project.upload(load[:source], schema, load[:mode])
|
@@ -122,7 +122,7 @@ module GoodData
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
def execute_tests(
|
125
|
+
def execute_tests(_project, spec)
|
126
126
|
spec.each do |assert|
|
127
127
|
result = GoodData::ReportDefinition.execute(assert[:report])
|
128
128
|
fail "Test did not pass. Got #{result.table.inspect}, expected #{assert[:result].inspect}" if result.table != assert[:result]
|