gooddata 2.1.10-java → 2.1.15-java

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.
@@ -49,6 +49,8 @@ module GoodData
49
49
  param :include_deprecated, instance_of(Type::BooleanType), required: false, default: false
50
50
  end
51
51
 
52
+ RESULT_HEADER = %i[from to status]
53
+
52
54
  class << self
53
55
  def call(params)
54
56
  results = []
@@ -76,9 +78,9 @@ module GoodData
76
78
  include_deprecated = params.include_deprecated.to_b
77
79
  from_pid = segment_info[:from]
78
80
  from = params.development_client.projects(from_pid) || fail("Invalid 'from' project specified - '#{from_pid}'")
79
-
80
81
  GoodData.logger.info "Creating Blueprint, project: '#{from.title}', PID: #{from_pid}"
81
82
  blueprint = from.blueprint(include_ca: params.include_computed_attributes.to_b)
83
+ segment_info[:from_blueprint] = blueprint
82
84
  maql_diff = nil
83
85
  previous_master = segment_info[:previous_master]
84
86
  diff_against_master = %w(diff_against_master_with_fallback diff_against_master)
@@ -89,6 +91,13 @@ module GoodData
89
91
  maql_diff_params << :excludeFactRule if exclude_fact_rule
90
92
  maql_diff_params << :includeDeprecated if include_deprecated
91
93
  maql_diff = previous_master.maql_diff(blueprint: blueprint, params: maql_diff_params)
94
+ chunks = maql_diff['projectModelDiff']['updateScripts']
95
+ if chunks.empty?
96
+ GoodData.logger.info "Synchronize LDM to clients will not proceed in mode \
97
+ '#{params[:synchronize_ldm].downcase}' due to no LDM changes in the new master project. \
98
+ If you had changed LDM of clients manually, please use mode 'diff_against_clients' \
99
+ to force synchronize LDM to clients"
100
+ end
92
101
  end
93
102
 
94
103
  segment_info[:to] = segment_info[:to].pmap do |entry|
@@ -13,8 +13,6 @@ require 'gooddata/extensions/integer'
13
13
  require 'gooddata/extensions/string'
14
14
  require 'gooddata/extensions/nil'
15
15
 
16
- require 'active_support/core_ext/hash/compact'
17
-
18
16
  require_relative 'actions/actions'
19
17
  require_relative 'dsl/dsl'
20
18
  require_relative 'helpers/helpers'
@@ -138,6 +136,7 @@ module GoodData
138
136
  EnsureTechnicalUsersDomain,
139
137
  EnsureTechnicalUsersProject,
140
138
  SynchronizeLdm,
139
+ MigrateGdcDateDimension,
141
140
  SynchronizeClients,
142
141
  SynchronizeComputedAttributes,
143
142
  CollectDymanicScheduleParams,
@@ -8,8 +8,6 @@
8
8
  require_relative '../dsl/dsl'
9
9
  require_relative '../helpers/helpers'
10
10
 
11
- require 'active_support/core_ext/hash/compact'
12
-
13
11
  require 'gooddata/extensions/class'
14
12
 
15
13
  module GoodData
@@ -2,8 +2,6 @@
2
2
  # This source code is licensed under the BSD-style license found in the
3
3
  # LICENSE file in the root directory of this source tree.
4
4
 
5
- require 'active_support/core_ext/hash/compact'
6
-
7
5
  module GoodData
8
6
  module Model
9
7
  class ProjectBlueprint
@@ -0,0 +1,662 @@
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 '../rest/resource'
9
+
10
+ module GoodData
11
+ class DataSource < Rest::Resource
12
+ attr_accessor :connection_info
13
+
14
+ DATA_SOURCES_URL = '/gdc/dataload/dataSources'
15
+ SNOWFLAKE = 'snowflake'
16
+ REDSHIFT = 'redshift'
17
+ BIGQUERY = 'bigQuery'
18
+ GENERIC = 'generic'
19
+ S3 = 's3'
20
+ ADS = 'ads'
21
+
22
+ class << self
23
+ # Get all data sources or get a specify data source from data source identify
24
+ # Expected parameter value:
25
+ # - :all return all data sources
26
+ # - :data_source_id return a data source with the specify data source identify
27
+ def [](id = :all, options = { client: GoodData.client })
28
+ c = GoodData.get_client(options)
29
+
30
+ if id == :all
31
+ data = c.get(DATA_SOURCES_URL)
32
+ data['dataSources']['items'].map do |ds_data|
33
+ c.create(DataSource, ds_data)
34
+ end
35
+ else
36
+ c.create(DataSource, c.get("#{DATA_SOURCES_URL}/#{id}"))
37
+ end
38
+ end
39
+
40
+ # Get a specify data source from data source identify
41
+ #
42
+ # @param [String] id Data source identify
43
+ # @return [DataSource] Data source corresponding in backend or throw exception if the data source identify doesn't exist
44
+ def from_id(id, options = { client: GoodData.client })
45
+ DataSource[id, options]
46
+ end
47
+
48
+ # Get a specify data source from data source alias
49
+ #
50
+ # @param [String] data_source_alias Data source alias
51
+ # @return [DataSource] Data source corresponding in backend or throw exception if the data source alias doesn't exist
52
+ def from_alias(data_source_alias, options = { client: GoodData.client })
53
+ data_sources = all(options)
54
+ result = data_sources.find do |data_source|
55
+ data_source.alias == data_source_alias
56
+ end
57
+ fail "Data source alias '#{data_source_alias}' has not found" unless result
58
+
59
+ result
60
+ end
61
+
62
+ # Get all data sources
63
+ def all(options = { client: GoodData.client })
64
+ DataSource[:all, options]
65
+ end
66
+
67
+ # Create data source from json
68
+ # Expected keys:
69
+ # - :name (mandatory)
70
+ # - :alias (optional)
71
+ # - :prefix (optional)
72
+ # - :connectionInfo (mandatory)
73
+ # - :client (mandatory)
74
+ def create(opts)
75
+ ds_name = opts[:name]
76
+ ds_alias = opts[:alias]
77
+ ds_prefix = opts[:prefix]
78
+ ds_connection_info = opts[:connectionInfo]
79
+
80
+ GoodData.logger.info "Creating data source '#{ds_name}'"
81
+ fail ArgumentError, 'Data source name has to be provided' if ds_name.nil? || ds_name.blank?
82
+ fail ArgumentError, 'Data source connection info has to be provided' if ds_connection_info.nil?
83
+
84
+ json = {
85
+ 'dataSource' => {
86
+ 'name' => ds_name,
87
+ 'connectionInfo' => ds_connection_info
88
+ }
89
+ }
90
+ json['dataSource']['alias'] = ds_alias if ds_alias
91
+ json['dataSource']['prefix'] = ds_prefix if ds_prefix
92
+
93
+ # Create data source
94
+ c = GoodData.get_client(opts)
95
+ res = c.post(DATA_SOURCES_URL, json)
96
+
97
+ # create the public facing object
98
+ c.create(DataSource, res)
99
+ end
100
+ end
101
+
102
+ # Save data source to backend. The saving will validate existing data source name and connection info. So need set
103
+ # values for them.
104
+ #
105
+ # Input info:
106
+ # - :name (mandatory)
107
+ # - :alias (optional)
108
+ # - :prefix (optional)
109
+ # - :connectionInfo (mandatory)
110
+ #
111
+ # Return: create data source in backend and return data source object corresponding with data source in backend.
112
+ def save
113
+ validate
114
+ validate_connection_info
115
+ if saved?
116
+ update_obj_json = client.put(uri, to_update_payload)
117
+ @json = update_obj_json
118
+ else
119
+ res = client.post(DATA_SOURCES_URL, to_update_payload)
120
+ fail 'Unable to create new Data Source' if res.nil?
121
+
122
+ @json = res
123
+ end
124
+ @connection_info = build_connection_info
125
+ self
126
+ end
127
+
128
+ def delete
129
+ saved? ? client.delete(uri) : nil
130
+ end
131
+
132
+ def initialize(json)
133
+ super
134
+ @json = json
135
+ validate
136
+ @connection_info = build_connection_info
137
+ end
138
+
139
+ def saved?
140
+ !uri.blank?
141
+ end
142
+
143
+ def name
144
+ @json['dataSource']['name']
145
+ end
146
+
147
+ def name=(new_name)
148
+ @json['dataSource']['name'] = new_name
149
+ end
150
+
151
+ def alias
152
+ @json['dataSource']['alias']
153
+ end
154
+
155
+ def alias=(new_alias)
156
+ @json['dataSource']['alias'] = new_alias
157
+ end
158
+
159
+ def prefix
160
+ @json['dataSource']['prefix']
161
+ end
162
+
163
+ def prefix=(new_prefix)
164
+ @json['dataSource']['prefix'] = new_prefix
165
+ end
166
+
167
+ def uri
168
+ @json['dataSource']['links']['self'] if @json && @json['dataSource'] && @json['dataSource']['links']
169
+ end
170
+
171
+ def id
172
+ uri.split('/')[-1]
173
+ end
174
+
175
+ def is(type)
176
+ @json['dataSource']['connectionInfo'][type]
177
+ end
178
+
179
+ private
180
+
181
+ def build_connection_info
182
+ return snowflake_connection_info if is(SNOWFLAKE)
183
+ return redshift_connection_info if is(REDSHIFT)
184
+ return bigquery_connection_info if is(BIGQUERY)
185
+ return generic_connection_info if is(GENERIC)
186
+ return s3_connection_info if is(S3)
187
+ return ads_connection_info if is(ADS)
188
+
189
+ # In case don't know data source type then support get or set directly json data for connection info
190
+ ConnectionInfo.new(@json['dataSource']['connectionInfo'])
191
+ end
192
+
193
+ def support_connection_info(connection_info)
194
+ [SnowflakeConnectionInfo, RedshiftConnectionInfo, BigQueryConnectionInfo,
195
+ GenericConnectionInfo, S3ConnectionInfo, AdsConnectionInfo].include? connection_info.class
196
+ end
197
+
198
+ def snowflake_connection_info
199
+ return nil unless is(SNOWFLAKE)
200
+
201
+ SnowflakeConnectionInfo.new(@json['dataSource']['connectionInfo'])
202
+ end
203
+
204
+ def redshift_connection_info
205
+ return nil unless is(REDSHIFT)
206
+
207
+ RedshiftConnectionInfo.new(@json['dataSource']['connectionInfo'])
208
+ end
209
+
210
+ def bigquery_connection_info
211
+ return nil unless is(BIGQUERY)
212
+
213
+ BigQueryConnectionInfo.new(@json['dataSource']['connectionInfo'])
214
+ end
215
+
216
+ def generic_connection_info
217
+ return nil unless is(GENERIC)
218
+
219
+ GenericConnectionInfo.new(@json['dataSource']['connectionInfo'])
220
+ end
221
+
222
+ def s3_connection_info
223
+ return nil unless is(S3)
224
+
225
+ S3ConnectionInfo.new(@json['dataSource']['connectionInfo'])
226
+ end
227
+
228
+ def ads_connection_info
229
+ return nil unless is(ADS)
230
+
231
+ AdsConnectionInfo.new(@json['dataSource']['connectionInfo'])
232
+ end
233
+
234
+ def to_update_payload
235
+ json_data = {
236
+ 'dataSource' => {
237
+ 'name' => name,
238
+ 'connectionInfo' => @connection_info.to_update_payload
239
+ }
240
+ }
241
+ json_data['dataSource']['alias'] = self.alias if self.alias
242
+ json_data['dataSource']['prefix'] = prefix if prefix
243
+ json_data
244
+ end
245
+
246
+ def validate
247
+ fail 'Invalid data source json data' unless @json['dataSource']
248
+ fail 'Data source connection info has to be provided' unless @json['dataSource']['connectionInfo']
249
+ fail 'Data source name has to be provided' if name.nil? || name.blank?
250
+ end
251
+
252
+ def validate_connection_info
253
+ @connection_info.validate
254
+ end
255
+
256
+ class ConnectionInfo < Rest::Resource
257
+ def initialize(connection_info_json)
258
+ @json = connection_info_json
259
+ end
260
+
261
+ def connection_info
262
+ @json
263
+ end
264
+
265
+ def connection_info=(connection_info_json)
266
+ @json = connection_info_json
267
+ end
268
+
269
+ def to_update_payload
270
+ @json
271
+ end
272
+
273
+ def validate
274
+ end
275
+ end
276
+
277
+ class SnowflakeConnectionInfo < ConnectionInfo
278
+ def initialize(connection_info_json)
279
+ @json = connection_info_json[GoodData::DataSource::SNOWFLAKE]
280
+ end
281
+
282
+ def url
283
+ @json['url']
284
+ end
285
+
286
+ def url=(new_url)
287
+ @json['url'] = new_url
288
+ end
289
+
290
+ def user_name
291
+ @json['authentication']['basic']['userName'] if @json && @json['authentication'] && @json['authentication']['basic']
292
+ end
293
+
294
+ def user_name=(new_user_name)
295
+ @json['authentication']['basic']['userName'] = new_user_name
296
+ end
297
+
298
+ def password
299
+ @json['authentication']['basic']['password'] if @json && @json['authentication'] && @json['authentication']['basic']
300
+ end
301
+
302
+ def password=(new_password)
303
+ @json['authentication']['basic']['password'] = new_password
304
+ end
305
+
306
+ def database
307
+ @json['database']
308
+ end
309
+
310
+ def database=(new_database)
311
+ @json['database'] = new_database
312
+ end
313
+
314
+ def schema
315
+ @json['schema']
316
+ end
317
+
318
+ def schema=(new_schema)
319
+ @json['schema'] = new_schema
320
+ end
321
+
322
+ def warehouse
323
+ @json['warehouse']
324
+ end
325
+
326
+ def warehouse=(new_warehouse)
327
+ @json['warehouse'] = new_warehouse
328
+ end
329
+
330
+ def to_update_payload
331
+ {
332
+ 'snowflake' => {
333
+ 'url' => url,
334
+ 'authentication' => {
335
+ 'basic' => {
336
+ 'userName' => user_name,
337
+ 'password' => password
338
+ }
339
+ },
340
+ 'database' => database,
341
+ 'schema' => schema,
342
+ 'warehouse' => warehouse
343
+ }
344
+ }
345
+ end
346
+
347
+ def validate
348
+ fail 'Data source url has to be provided' if url.nil? || url.blank?
349
+ fail 'Data source database has to be provided' if database.nil? || database.blank?
350
+ fail 'Data source schema has to be provided' if schema.nil? || schema.blank?
351
+ fail 'Data source warehouse has to be provided' if warehouse.nil? || warehouse.blank?
352
+ fail 'Data source username has to be provided' if user_name.nil? || user_name.blank?
353
+ end
354
+ end
355
+
356
+ class RedshiftConnectionInfo < ConnectionInfo
357
+ def initialize(connection_info_json)
358
+ @json = connection_info_json[GoodData::DataSource::REDSHIFT]
359
+ end
360
+
361
+ def url
362
+ @json['url']
363
+ end
364
+
365
+ def url=(new_url)
366
+ @json['url'] = new_url
367
+ end
368
+
369
+ def user_name
370
+ @json['authentication']['basic']['userName'] if basic_authentication
371
+ end
372
+
373
+ def user_name=(new_user_name)
374
+ @json['authentication']['basic']['userName'] = new_user_name
375
+ end
376
+
377
+ def password
378
+ @json['authentication']['basic']['password'] if basic_authentication
379
+ end
380
+
381
+ def password=(new_password)
382
+ @json['authentication']['basic']['password'] = new_password
383
+ end
384
+
385
+ def db_user
386
+ @json['authentication']['iam']['dbUser'] if iam_authentication
387
+ end
388
+
389
+ def db_user=(new_db_user)
390
+ @json['authentication']['iam']['dbUser'] = new_db_user
391
+ end
392
+
393
+ def access_key_id
394
+ @json['authentication']['iam']['accessKeyId'] if iam_authentication
395
+ end
396
+
397
+ def access_key_id=(new_access_key_id)
398
+ @json['authentication']['iam']['accessKeyId'] = new_access_key_id
399
+ end
400
+
401
+ def secret_access_key
402
+ @json['authentication']['iam']['secretAccessKey'] if iam_authentication
403
+ end
404
+
405
+ def secret_access_key=(new_secret_access_key)
406
+ @json['authentication']['iam']['secretAccessKey'] = new_secret_access_key
407
+ end
408
+
409
+ def basic_authentication
410
+ @json && @json['authentication'] && @json['authentication']['basic']
411
+ end
412
+
413
+ def iam_authentication
414
+ @json && @json['authentication'] && @json['authentication']['iam']
415
+ end
416
+
417
+ def database
418
+ @json['database']
419
+ end
420
+
421
+ def database=(new_database)
422
+ @json['database'] = new_database
423
+ end
424
+
425
+ def schema
426
+ @json['schema']
427
+ end
428
+
429
+ def schema=(new_schema)
430
+ @json['schema'] = new_schema
431
+ end
432
+
433
+ def to_update_payload
434
+ if basic_authentication
435
+ {
436
+ 'redshift' => {
437
+ 'url' => url,
438
+ 'authentication' => {
439
+ 'basic' => {
440
+ 'userName' => user_name,
441
+ 'password' => password
442
+ }
443
+ },
444
+ 'database' => database,
445
+ 'schema' => schema
446
+ }
447
+ }
448
+ else
449
+ {
450
+ 'redshift' => {
451
+ 'url' => url,
452
+ 'authentication' => {
453
+ 'iam' => {
454
+ 'dbUser' => db_user,
455
+ 'accessKeyId' => access_key_id,
456
+ 'secretAccessKey' => secret_access_key
457
+ }
458
+ },
459
+ 'database' => database,
460
+ 'schema' => schema
461
+ }
462
+ }
463
+ end
464
+ end
465
+
466
+ def validate
467
+ fail 'Data source url has to be provided' if url.nil? || url.blank?
468
+ fail 'Data source database has to be provided' if database.nil? || database.blank?
469
+ fail 'Data source schema has to be provided' if schema.nil? || schema.blank?
470
+
471
+ if basic_authentication
472
+ fail 'Data source username has to be provided' if user_name.nil? || user_name.blank?
473
+ elsif iam_authentication
474
+ fail 'Data source db_user has to be provided' if db_user.nil? || db_user.blank?
475
+ fail 'Data source access key has to be provided' if access_key_id.nil? || access_key_id.blank?
476
+ end
477
+ end
478
+ end
479
+
480
+ class BigQueryConnectionInfo < ConnectionInfo
481
+ def initialize(connection_info_json)
482
+ @json = connection_info_json[GoodData::DataSource::BIGQUERY]
483
+ end
484
+
485
+ def client_email
486
+ @json['authentication']['serviceAccount']['clientEmail'] if @json && @json['authentication'] && @json['authentication']['serviceAccount']
487
+ end
488
+
489
+ def client_email=(new_client_email)
490
+ @json['authentication']['serviceAccount']['clientEmail'] = new_client_email
491
+ end
492
+
493
+ def private_key
494
+ @json['authentication']['serviceAccount']['privateKey'] if @json && @json['authentication'] && @json['authentication']['serviceAccount']
495
+ end
496
+
497
+ def private_key=(new_private_key)
498
+ @json['authentication']['serviceAccount']['privateKey'] = new_private_key
499
+ end
500
+
501
+ def project
502
+ @json['project']
503
+ end
504
+
505
+ def project=(new_project)
506
+ @json['project'] = new_project
507
+ end
508
+
509
+ def schema
510
+ @json['schema']
511
+ end
512
+
513
+ def schema=(new_schema)
514
+ @json['schema'] = new_schema
515
+ end
516
+
517
+ def to_update_payload
518
+ {
519
+ 'bigQuery' => {
520
+ 'authentication' => {
521
+ 'serviceAccount' => {
522
+ 'clientEmail' => client_email,
523
+ 'privateKey' => private_key
524
+ }
525
+ },
526
+ 'project' => project,
527
+ 'schema' => schema
528
+ }
529
+ }
530
+ end
531
+
532
+ def validate
533
+ fail 'Data source client email has to be provided' if client_email.nil? || client_email.blank?
534
+ fail 'Data source project has to be provided' if project.nil? || project.blank?
535
+ fail 'Data source schema has to be provided' if schema.nil? || schema.blank?
536
+ end
537
+ end
538
+
539
+ class GenericConnectionInfo < ConnectionInfo
540
+ def initialize(connection_info_json)
541
+ @json = connection_info_json[GoodData::DataSource::GENERIC]
542
+ end
543
+
544
+ def params
545
+ @json['params']
546
+ end
547
+
548
+ def params=(new_params)
549
+ @json['params'] = new_params
550
+ end
551
+
552
+ def secure_params
553
+ @json['secureParams']
554
+ end
555
+
556
+ def secure_params=(new_secure_params)
557
+ @json['secureParams'] = new_secure_params
558
+ end
559
+
560
+ def to_update_payload
561
+ {
562
+ 'generic' => {
563
+ 'params' => params,
564
+ 'secureParams' => secure_params
565
+ }
566
+ }
567
+ end
568
+
569
+ def validate
570
+ end
571
+ end
572
+
573
+ class S3ConnectionInfo < ConnectionInfo
574
+ def initialize(connection_info_json)
575
+ @json = connection_info_json[GoodData::DataSource::S3]
576
+ end
577
+
578
+ def bucket
579
+ @json['bucket']
580
+ end
581
+
582
+ def bucket=(new_bucket)
583
+ @json['bucket'] = new_bucket
584
+ end
585
+
586
+ def access_key
587
+ @json['accessKey']
588
+ end
589
+
590
+ def access_key=(new_access_key)
591
+ @json['accessKey'] = new_access_key
592
+ end
593
+
594
+ def secret_key
595
+ @json['secretKey']
596
+ end
597
+
598
+ def secret_key=(new_secret_key)
599
+ @json['secretKey'] = new_secret_key
600
+ end
601
+
602
+ def server_side_encryption
603
+ @json['serverSideEncryption']
604
+ end
605
+
606
+ def server_side_encryption=(new_server_side_encryption)
607
+ @json['serverSideEncryption'] = new_server_side_encryption
608
+ end
609
+
610
+ def to_update_payload
611
+ {
612
+ 's3' => {
613
+ 'bucket' => bucket,
614
+ 'accessKey' => access_key,
615
+ 'secretKey' => secret_key,
616
+ 'serverSideEncryption' => server_side_encryption
617
+ }
618
+ }
619
+ end
620
+
621
+ def validate
622
+ fail 'S3 bucket has to be provided' if bucket.nil? || bucket.blank?
623
+ fail 'S3 access key has to be provided' if access_key.nil? || access_key.blank?
624
+ end
625
+ end
626
+
627
+ class AdsConnectionInfo < ConnectionInfo
628
+ def initialize(connection_info_json)
629
+ @json = connection_info_json[GoodData::DataSource::ADS]
630
+ end
631
+
632
+ def instance
633
+ @json['instance']
634
+ end
635
+
636
+ def instance=(new_instance)
637
+ @json['instance'] = new_instance
638
+ end
639
+
640
+ def exportable
641
+ @json['exportable']
642
+ end
643
+
644
+ def exportable=(new_exportable)
645
+ @json['exportable'] = new_exportable
646
+ end
647
+
648
+ def to_update_payload
649
+ {
650
+ 'ads' => {
651
+ 'instance' => instance,
652
+ 'exportable' => exportable
653
+ }
654
+ }
655
+ end
656
+
657
+ def validate
658
+ fail 'Data source instance has to be provided' if instance.nil? || instance.blank?
659
+ end
660
+ end
661
+ end
662
+ end