gooddata 2.1.15 → 2.1.16

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of gooddata might be problematic. Click here for more details.

data/README.md CHANGED
@@ -95,4 +95,5 @@ For full contributor info see [contributors page](https://github.com/gooddata/go
95
95
 
96
96
  ## Copyright
97
97
 
98
- Copyright (c) 2010 - 2018 GoodData Corporation and Thomas Watson Steen. See [LICENSE](/LICENSE) for details.
98
+ (c) 2010-2021 GoodData Corporation
99
+ This repository is governed by the terms and conditions in the LICENSE. This repository contains a number of open source packages detailed in NOTICES, including the GoodData Ruby SDK, which is licensed under the BSD-3-Clause license and contains additional open source components detailed in the file called LICENSE_FOR_RUBY_SDK_COMPONENT.
data/Rakefile CHANGED
@@ -33,7 +33,11 @@ namespace :gem do
33
33
  desc "Release gem version #{GoodData::VERSION} to rubygems"
34
34
  task :release do
35
35
  gem = "gooddata-#{GoodData::VERSION}.gem"
36
-
36
+ origin_license_file = 'LICENSE'
37
+ new_license_file = 'LICENSE_FOR_RUBY_SDK_COMPONENT.txt'
38
+ File.delete(origin_license_file) if File.exist?(origin_license_file)
39
+ File.cp(new_license_file, origin_license_file) if File.exists?(new_license_file)
40
+ puts "Copied file #{new_license_file} to #{origin_license_file}"
37
41
  puts "Building #{gem} ..."
38
42
  res = `gem build ./gooddata.gemspec`
39
43
  file = res.match('File: (.*)')[1]
data/SDK_VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.15
1
+ 2.1.16
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.7.24
1
+ 3.7.25
@@ -1,6 +1,6 @@
1
1
  require 'optparse'
2
2
 
3
- example = 'Usage example: GD_ENV=testing GD_SPEC_PASSWORD=secret bundle exec ruby bin/test_projects_cleanup.rb'
3
+ example = 'Usage example: GD_ENV=testing GD_SPEC_PASSWORD= bundle exec ruby bin/test_projects_cleanup.rb'
4
4
 
5
5
  options = {}
6
6
  OptionParser.new do |opts|
@@ -0,0 +1,57 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+ <modelVersion>4.0.0</modelVersion>
6
+
7
+ <groupId>com.gooddata.lcm</groupId>
8
+ <artifactId>lcm-postgresql-driver</artifactId>
9
+ <version>1.0-SNAPSHOT</version>
10
+
11
+ <dependencies>
12
+ <dependency>
13
+ <groupId>org.postgresql</groupId>
14
+ <artifactId>postgresql</artifactId>
15
+ <version>42.2.19</version>
16
+ </dependency>
17
+ <dependency>
18
+ <groupId>org.slf4j</groupId>
19
+ <artifactId>slf4j-api</artifactId>
20
+ <version>1.7.2</version>
21
+ </dependency>
22
+ </dependencies>
23
+
24
+ <profiles>
25
+ <profile>
26
+ <id>binary-packaging</id>
27
+ <build>
28
+ <plugins>
29
+ <plugin>
30
+ <artifactId>maven-dependency-plugin</artifactId>
31
+ <executions>
32
+ <execution>
33
+ <phase>package</phase>
34
+ <goals>
35
+ <goal>copy-dependencies</goal>
36
+ </goals>
37
+ <configuration>
38
+ <outputDirectory>${project.build.directory}</outputDirectory>
39
+ <!-- compile scope gives runtime and compile dependencies (skips test deps) -->
40
+ <includeScope>runtime</includeScope>
41
+ </configuration>
42
+ </execution>
43
+ </executions>
44
+ </plugin>
45
+ </plugins>
46
+ </build>
47
+ </profile>
48
+ </profiles>
49
+
50
+ <repositories>
51
+ <repository>
52
+ <id>my-repo1</id>
53
+ <name>my custom repo</name>
54
+ <url>https://repository.mulesoft.org/nexus/content/repositories/public/</url>
55
+ </repository>
56
+ </repositories>
57
+ </project>
data/gooddata.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'gooddata/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'gooddata'
7
7
  s.version = GoodData::VERSION
8
- s.licenses = ['BSD']
8
+ s.licenses = ['BSD-3-Clause']
9
9
  s.platform = 'java' if RUBY_PLATFORM =~ /java/
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
@@ -62,7 +62,6 @@ Gem::Specification.new do |s|
62
62
 
63
63
  s.add_dependency 'aws-sdk-s3', '~> 1.16'
64
64
  s.add_dependency 'docile', '~> 1.1'
65
- s.add_dependency 'erubis', '~> 2.7'
66
65
  s.add_dependency 'gli', '~> 2.15'
67
66
  s.add_dependency 'gooddata_datawarehouse', '~> 0.0.10' if RUBY_PLATFORM == 'java'
68
67
  s.add_dependency 'highline', '= 2.0.0.pre.develop.14'
@@ -11,7 +11,15 @@ module GoodData
11
11
  module CloudResources
12
12
  class CloudResourceFactory
13
13
  class << self
14
+ def load_cloud_resource(type)
15
+ base = "#{Pathname(__FILE__).dirname.expand_path}#{File::SEPARATOR}#{type}#{File::SEPARATOR}"
16
+ Dir.glob(base + '**/*.rb').each do |file|
17
+ require file
18
+ end
19
+ end
20
+
14
21
  def create(type, data = {}, opts = {})
22
+ load_cloud_resource(type)
15
23
  clients = CloudResourceClient.descendants.select { |c| c.respond_to?("accept?") && c.send("accept?", type) }
16
24
  raise "DataSource does not support type \"#{type}\"" if clients.empty?
17
25
 
@@ -7,6 +7,6 @@
7
7
  require 'pathname'
8
8
 
9
9
  base = Pathname(__FILE__).dirname.expand_path
10
- Dir.glob(base + '**/*.rb').each do |file|
10
+ Dir.glob(base + '*.rb').each do |file|
11
11
  require file
12
12
  end
@@ -0,0 +1,107 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+ #
4
+ # Copyright (c) 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 'securerandom'
9
+ require 'java'
10
+ require 'pathname'
11
+ require_relative '../cloud_resource_client'
12
+
13
+ base = Pathname(__FILE__).dirname.expand_path
14
+ Dir.glob(base + 'drivers/*.jar').each do |file|
15
+ require file unless file.start_with?('lcm-postgresql-driver')
16
+ end
17
+
18
+ module GoodData
19
+ module CloudResources
20
+ class PostgresClient < CloudResourceClient
21
+ JDBC_POSTGRES_PATTERN = %r{jdbc:postgresql:\/\/([^:^\/]+)(:([0-9]+))?(\/)?}
22
+ POSTGRES_DEFAULT_PORT = 5432
23
+ JDBC_POSTGRES_PROTOCOL = 'jdbc:postgresql://'
24
+ SSL_JAVA_FACTORY = '&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory'
25
+ VERIFY_FULL = 'verify-full'
26
+ PREFER = 'prefer'
27
+ REQUIRE = 'require'
28
+ POSTGRES_SET_SCHEMA_COMMAND = "set search_path to"
29
+ POSTGRES_FETCH_SIZE = 1000
30
+
31
+ class << self
32
+ def accept?(type)
33
+ type == 'postgresql'
34
+ end
35
+ end
36
+
37
+ def initialize(options = {})
38
+ raise("Data Source needs a client to Postgres to be able to query the storage but 'postgresql_client' is empty.") unless options['postgresql_client']
39
+
40
+ if options['postgresql_client']['connection'].is_a?(Hash)
41
+ @database = options['postgresql_client']['connection']['database']
42
+ @schema = options['postgresql_client']['connection']['schema'] || 'public'
43
+ @authentication = options['postgresql_client']['connection']['authentication']
44
+ @ssl_mode = options['postgresql_client']['connection']['sslMode']
45
+ raise "SSL Mode should be prefer, require and verify-full" unless @ssl_mode == 'prefer' || @ssl_mode == 'require' || @ssl_mode == 'verify-full'
46
+
47
+ @url = build_url(options['postgresql_client']['connection']['url'])
48
+ else
49
+ raise('Missing connection info for Postgres client')
50
+ end
51
+
52
+ Java.org.postgresql.Driver
53
+ end
54
+
55
+ def realize_query(query, _params)
56
+ GoodData.gd_logger.info("Realize SQL query: type=postgresql status=started")
57
+
58
+ connect
59
+ filename = "#{SecureRandom.urlsafe_base64(6)}_#{Time.now.to_i}.csv"
60
+ measure = Benchmark.measure do
61
+ statement = @connection.create_statement
62
+ statement.set_fetch_size(POSTGRES_FETCH_SIZE)
63
+ has_result = statement.execute(query)
64
+ if has_result
65
+ result = statement.get_result_set
66
+ metadata = result.get_meta_data
67
+ col_count = metadata.column_count
68
+ CSV.open(filename, 'wb') do |csv|
69
+ csv << Array(1..col_count).map { |i| metadata.get_column_name(i) } # build the header
70
+ csv << Array(1..col_count).map { |i| result.get_string(i)&.to_s } while result.next
71
+ end
72
+ end
73
+ end
74
+ GoodData.gd_logger.info("Realize SQL query: type=postgresql status=finished duration=#{measure.real}")
75
+ filename
76
+ ensure
77
+ @connection&.close
78
+ @connection = nil
79
+ end
80
+
81
+ def connect
82
+ GoodData.logger.info "Setting up connection to Postgresql #{@url}"
83
+
84
+ prop = java.util.Properties.new
85
+ prop.setProperty('user', @authentication['basic']['userName'])
86
+ prop.setProperty('password', @authentication['basic']['password'])
87
+ prop.setProperty('schema', @schema)
88
+
89
+ @connection = java.sql.DriverManager.getConnection(@url, prop)
90
+ statement = @connection.create_statement
91
+ statement.execute("#{POSTGRES_SET_SCHEMA_COMMAND} #{@schema}")
92
+ @connection.set_auto_commit(false)
93
+ end
94
+
95
+ def build_url(url)
96
+ matches = url.scan(JDBC_POSTGRES_PATTERN)
97
+ raise 'Cannot reach the url' unless matches
98
+
99
+ host = matches[0][0]
100
+ port = matches[0][2]&.to_i || POSTGRES_DEFAULT_PORT
101
+ raise "Custom port #{port} is not supported. Remove it or use the default port '5432'" if POSTGRES_DEFAULT_PORT != port
102
+
103
+ "#{JDBC_POSTGRES_PROTOCOL}#{host}:#{port}/#{@database}?sslmode=#{@ssl_mode}#{VERIFY_FULL == @ssl_mode ? SSL_JAVA_FACTORY : ''}"
104
+ end
105
+ end
106
+ end
107
+ end
@@ -4,7 +4,7 @@
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
- require 'erubis'
7
+ require 'erb'
8
8
  require 'fileutils'
9
9
  require 'pathname'
10
10
 
@@ -18,15 +18,14 @@ module GoodData
18
18
  # TODO: Add option for custom output dir
19
19
  def project(name)
20
20
  fail ArgumentError, 'No name specified' if name.nil?
21
-
22
21
  FileUtils.mkdir(name)
23
22
  FileUtils.cd(name) do
24
23
  FileUtils.mkdir('model')
25
24
  FileUtils.cd('model') do
26
25
  input = File.read(TEMPLATES_PATH + 'project/model/model.rb.erb')
27
- eruby = Erubis::Eruby.new(input)
26
+ erb = ERB.new(input)
28
27
  File.open('model.rb', 'w') do |f|
29
- f.write(eruby.result(:name => name))
28
+ f.write(erb.result_with_hash(:name => name))
30
29
  end
31
30
  end
32
31
 
@@ -36,9 +35,9 @@ module GoodData
36
35
  end
37
36
 
38
37
  input = File.read(TEMPLATES_PATH + 'project/Goodfile.erb')
39
- eruby = Erubis::Eruby.new(input)
38
+ erb = ERB.new(input)
40
39
  File.open('Goodfile', 'w') do |f|
41
- f.write(eruby.result)
40
+ f.write(erb.result)
42
41
  end
43
42
  end
44
43
  end
@@ -51,15 +50,15 @@ module GoodData
51
50
  FileUtils.mkdir(name)
52
51
  FileUtils.cd(name) do
53
52
  input = File.read(TEMPLATES_PATH + 'bricks/brick.rb.erb')
54
- eruby = Erubis::Eruby.new(input)
53
+ erb = ERB.new(input)
55
54
  File.open('brick.rb', 'w') do |f|
56
- f.write(eruby.result)
55
+ f.write(erb.result)
57
56
  end
58
57
 
59
58
  input = File.read(TEMPLATES_PATH + 'bricks/main.rb.erb')
60
- eruby = Erubis::Eruby.new(input)
59
+ erb = ERB.new(input)
61
60
  File.open('main.rb', 'w') do |f|
62
- f.write(eruby.result)
61
+ f.write(erb.result)
63
62
  end
64
63
  end
65
64
  end
@@ -1,4 +1,5 @@
1
- # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
1
+ # frozen_string_literal: true
2
+ # Copyright (c) 2010-2021 GoodData Corporation. All rights reserved.
2
3
  # This source code is licensed under the BSD-style license found in the
3
4
  # LICENSE file in the root directory of this source tree.
4
5
 
@@ -11,6 +12,7 @@ module GoodData
11
12
  @level = nil
12
13
  end
13
14
 
15
+ # No body define need for dummy logger
14
16
  def debug(*_args)
15
17
  end
16
18
 
@@ -44,9 +44,8 @@ module GoodData
44
44
  realize_link
45
45
  when 's3'
46
46
  realize_s3(params)
47
- when 'redshift', 'snowflake', 'bigquery'
47
+ when 'redshift', 'snowflake', 'bigquery', 'postgresql'
48
48
  raise GoodData::InvalidEnvError, "DataSource does not support type \"#{source}\" on the platform #{RUBY_PLATFORM}" unless RUBY_PLATFORM =~ /java/
49
-
50
49
  require_relative '../cloud_resources/cloud_resources'
51
50
  realize_cloud_resource(source, params)
52
51
  else
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2021 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -34,6 +34,7 @@ module GoodData
34
34
  end
35
35
 
36
36
  set_const :GD_MAX_RETRY, (ENV['GD_MAX_RETRY'] && ENV['GD_MAX_RETRY'].to_i) || 12
37
+ AES_256_CBC_CIPHER = 'aes-256-cbc'
37
38
 
38
39
  class << self
39
40
  def error(msg)
@@ -222,7 +223,7 @@ module GoodData
222
223
  # encrypts data with the given key. returns a binary data with the
223
224
  # unhashed random iv in the first 16 bytes
224
225
  def encrypt(data, key)
225
- cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
226
+ cipher = OpenSSL::Cipher::Cipher.new(AES_256_CBC_CIPHER)
226
227
  cipher.encrypt
227
228
  cipher.key = key = Digest::SHA256.digest(key)
228
229
  random_iv = cipher.random_iv
@@ -236,7 +237,7 @@ module GoodData
236
237
 
237
238
  # Simple encrypt data with given key
238
239
  def simple_encrypt(data, key)
239
- cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
240
+ cipher = OpenSSL::Cipher::Cipher.new(AES_256_CBC_CIPHER)
240
241
  cipher.encrypt
241
242
  cipher.key = key
242
243
  encrypted = cipher.update(data)
@@ -253,7 +254,7 @@ module GoodData
253
254
 
254
255
  data = Base64.decode64(database64)
255
256
 
256
- cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
257
+ cipher = OpenSSL::Cipher::Cipher.new(AES_256_CBC_CIPHER)
257
258
  cipher.decrypt
258
259
  cipher.key = cipher_key = Digest::SHA256.digest(key)
259
260
  random_iv = data[0..15] # extract iv from first 16 bytes
@@ -273,7 +274,7 @@ module GoodData
273
274
 
274
275
  data = Base64.decode64(database64)
275
276
 
276
- cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
277
+ cipher = OpenSSL::Cipher::Cipher.new(AES_256_CBC_CIPHER)
277
278
  cipher.decrypt
278
279
  cipher.key = key
279
280
  decrypted = cipher.update(data)
@@ -167,6 +167,10 @@ module GoodData
167
167
  fail "Client id cannot be empty" if client_id.blank?
168
168
 
169
169
  c = all_clients.detect { |specific_client| specific_client.id == client_id }
170
+ if c.nil?
171
+ params.gdc_logger.warn "Client #{client_id} is not found"
172
+ next
173
+ end
170
174
  if params.segments && !segment_uris.include?(c.segment_uri)
171
175
  params.gdc_logger.warn "Client #{client_id} is outside segments_filter #{params.segments}"
172
176
  next
@@ -182,11 +182,11 @@ module GoodData
182
182
  # value of a project id in the data since he does not know it upfront
183
183
  # and we cannot influence its value.
184
184
  common_params = {
185
- domain: domain,
186
- whitelists: whitelists,
187
- ignore_failures: ignore_failures,
188
- remove_users_from_project: remove_users_from_project,
189
- do_not_touch_users_that_are_not_mentioned: do_not_touch_users_that_are_not_mentioned,
185
+ domain: domain,
186
+ whitelists: whitelists,
187
+ ignore_failures: ignore_failures,
188
+ remove_users_from_project: remove_users_from_project,
189
+ do_not_touch_users_that_are_not_mentioned: do_not_touch_users_that_are_not_mentioned,
190
190
  create_non_existing_user_groups: create_non_existing_user_groups,
191
191
  user_groups_cache: nil
192
192
  }
@@ -198,7 +198,8 @@ module GoodData
198
198
  domain.create_users(new_users.uniq { |u| u[:login] || u[:email] })
199
199
  when 'remove_from_organization'
200
200
  user_ids = new_users.uniq { |u| u[:login] || u[:email] }.map { |u| u[:login] || u[:email] }
201
- users = user_ids.map { |u| domain.users(u, client: client) }
201
+ users = user_ids.map { |u| domain.users(u, client: client) }.reject(&:nil?)
202
+ params.gdc_logger.info "#{user_ids.count - users.count} users were not found (or were deleted) in domain #{domain_name}" if user_ids.count > users.count
202
203
  params.gdc_logger.warn "Deleting #{users.count} users from domain #{domain_name}"
203
204
 
204
205
  GoodData.gd_logger.info("Synchronizing in mode=#{mode}, domain=#{domain_name}, data_rows=#{users.count}")
@@ -1,12 +1,14 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2021 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
7
  module GoodData
8
8
  module Mixin
9
9
  module MdObjectQuery
10
+ ERROR_MESSAGE_NO_PROJECT = 'No :project specified'
11
+
10
12
  # Method intended to get all objects of that type in a specified project
11
13
  #
12
14
  # @param options [Hash] the options hash
@@ -38,7 +40,7 @@ module GoodData
38
40
  fail ArgumentError, 'No :client specified' if client.nil?
39
41
 
40
42
  p = options[:project]
41
- fail ArgumentError, 'No :project specified' if p.nil?
43
+ fail ArgumentError, ERROR_MESSAGE_NO_PROJECT if p.nil?
42
44
 
43
45
  project = GoodData::Project[p, options]
44
46
  fail ArgumentError, 'Wrong :project specified' if project.nil?
@@ -98,10 +100,10 @@ module GoodData
98
100
  # Returns which objects uses this MD resource
99
101
  def usedby(uri, key = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
100
102
  p = opts[:project]
101
- fail ArgumentError, 'No :project specified' if p.nil?
103
+ fail ArgumentError, ERROR_MESSAGE_NO_PROJECT if p.nil?
102
104
 
103
105
  project = GoodData::Project[p, opts]
104
- fail ArgumentError, 'No :project specified' if project.nil?
106
+ fail ArgumentError, ERROR_MESSAGE_NO_PROJECT if project.nil?
105
107
 
106
108
  dependency("#{project.md['usedby2']}/#{uri_obj_id(uri)}", key, opts)
107
109
  end
@@ -111,10 +113,10 @@ module GoodData
111
113
  # Returns which objects this MD resource uses
112
114
  def using(uri, key = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
113
115
  p = opts[:project]
114
- fail ArgumentError, 'No :project specified' if p.nil?
116
+ fail ArgumentError, ERROR_MESSAGE_NO_PROJECT if p.nil?
115
117
 
116
118
  project = GoodData::Project[p, opts]
117
- fail ArgumentError, 'No :project specified' if project.nil?
119
+ fail ArgumentError, ERROR_MESSAGE_NO_PROJECT if project.nil?
118
120
 
119
121
  dependency("#{project.md['using2']}/#{uri_obj_id(uri)}", key, opts)
120
122
  end