gooddata 2.1.12 → 2.1.19

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gdc-ii-config.yaml +1 -1
  3. data/.sonar.settings +4 -0
  4. data/.travis.yml +78 -12
  5. data/CHANGELOG.md +37 -0
  6. data/Dockerfile +9 -3
  7. data/Dockerfile.jruby +11 -1
  8. data/LICENSE +30 -22
  9. data/LICENSE.rb +1 -1
  10. data/README.md +19 -1
  11. data/Rakefile +8 -1
  12. data/SDK_VERSION +1 -1
  13. data/VERSION +1 -1
  14. data/bin/test_projects_cleanup.rb +45 -3
  15. data/ci/postgresql/pom.xml +57 -0
  16. data/dev-gooddata-sso.pub.encrypted +40 -40
  17. data/docker-compose.lcm.yml +3 -0
  18. data/gdc_fossa_ruby_sdk.yaml +1 -0
  19. data/gooddata.gemspec +8 -5
  20. data/k8s/charts/lcm-bricks/Chart.yaml +1 -1
  21. data/k8s/charts/lcm-bricks/templates/prometheus/alertingRules.yaml +11 -1
  22. data/lcm.rake +10 -4
  23. data/lib/gooddata.rb +2 -0
  24. data/lib/gooddata/cloud_resources/{cloud_resouce_factory.rb → cloud_resource_factory.rb} +8 -0
  25. data/lib/gooddata/cloud_resources/cloud_resources.rb +1 -1
  26. data/lib/gooddata/cloud_resources/postgresql/drivers/.gitkeepme +0 -0
  27. data/lib/gooddata/cloud_resources/postgresql/postgresql_client.rb +107 -0
  28. data/lib/gooddata/commands/scaffold.rb +9 -10
  29. data/lib/gooddata/core/nil_logger.rb +3 -1
  30. data/lib/gooddata/helpers/data_helper.rb +1 -2
  31. data/lib/gooddata/helpers/global_helpers.rb +6 -5
  32. data/lib/gooddata/helpers/global_helpers_params.rb +2 -2
  33. data/lib/gooddata/lcm/actions/associate_clients.rb +8 -2
  34. data/lib/gooddata/lcm/actions/base_action.rb +0 -2
  35. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +2 -1
  36. data/lib/gooddata/lcm/actions/migrate_gdc_date_dimension.rb +116 -0
  37. data/lib/gooddata/lcm/actions/provision_clients.rb +31 -10
  38. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +3 -1
  39. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +4 -0
  40. data/lib/gooddata/lcm/actions/synchronize_users.rb +7 -6
  41. data/lib/gooddata/lcm/lcm2.rb +1 -2
  42. data/lib/gooddata/lcm/types/base_type.rb +0 -2
  43. data/lib/gooddata/mixins/md_object_query.rb +8 -6
  44. data/lib/gooddata/models/blueprint/project_blueprint.rb +0 -2
  45. data/lib/gooddata/models/client.rb +14 -12
  46. data/lib/gooddata/models/data_source.rb +664 -0
  47. data/lib/gooddata/models/domain.rb +3 -2
  48. data/lib/gooddata/models/from_wire.rb +1 -0
  49. data/lib/gooddata/models/metadata/analytical_dashboard.rb +49 -0
  50. data/lib/gooddata/models/metadata/analytical_visualization_object.rb +30 -0
  51. data/lib/gooddata/models/metadata/scheduled_mail.rb +1 -1
  52. data/lib/gooddata/models/metadata/visualization_object.rb +50 -0
  53. data/lib/gooddata/models/process.rb +11 -3
  54. data/lib/gooddata/models/project.rb +104 -13
  55. data/lib/gooddata/models/user_filters/user_filter_builder.rb +0 -1
  56. data/lib/gooddata/models/user_group.rb +0 -1
  57. data/lib/gooddata/rest/connection.rb +6 -4
  58. data/lib/gooddata/rest/phmap.rb +1 -1
  59. data/rubydev_public.gpg.encrypted +51 -51
  60. data/rubydev_secret_keys.gpg.encrypted +109 -109
  61. metadata +21 -22
  62. data/DEPENDENCIES.md +0 -880
@@ -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>
@@ -1,40 +1,40 @@
1
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- +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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- +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
- 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
- +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
- 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
- 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
- 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
- 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
- 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
- yI9aTA48UfTN/VazBpTomxrA44ChjLMR7WFwdWXaNGw00faCdhm0fLZo2Kox
36
- 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
- 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
- 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
- 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
40
- PHRjAjc=
1
+ SRNgp8VSJ8HqV2LnLD3kYkMO39u9rn3ssPvJHQuNHnPUDcc/FkCh529uTiqq
2
+ ON9+j5fFTjsKHr437hwnUCAq5Nn3ANSAhOSXehi3wqxicQrUU2xgbQbI+hk7
3
+ mLWrLOsm9Cn19kz9yblDh4aHTQBydJ6JwdPVnd6igIDnfLMVVVpzWK08aFfc
4
+ Y5KAeyIlLn5RQPQJL85LhVTOEG871z8wCAigeGaP2vnLzBj/9GQdwdDTsQzL
5
+ k1Rz2K3tL9SoUIVZ56dr1U11MYXduRzYJMawk21t9B7yNeKyuZCXx9U8VxAr
6
+ dqecLJoBAQI2ppPikJS3ycna/lRYD0OsGv6B7AR8sAkAB0XjpJZ9nNJys/PK
7
+ bBnmmKq+hvDu9zsIba8ptz0L3F5bi+Cfa+5c/Hyj7Jm3xiq5IWyh5LmtTmOI
8
+ MQa/fUPlerGe+7VZYlIm17fjd99cgqRM8yII/bTMvAEQREu1UxEwC4JFe9Bz
9
+ eFHeg6EorQJyBBV+LCDk86WS5RJBhBoTVj/LOm3BIUVr7Xee7naJxuRpQjgl
10
+ iTft/IfVhiwEPPonasXRjD1XwPKXUz8rX1C5JWDreOQB4hCPcNm29y/dV7Z4
11
+ 7hv4ki9YgIhhmc/sNqvSE7JO2w5dvyKo05mYQj1CQUdvqpbge68J8cV84wp5
12
+ Lj3jHRXyDf/2x0IdpJTACGUy4R8XQUYpLDAfbtmgTuHu8HndxVb3O+rpwk+K
13
+ ipXb0mj4YQvc2SbCJ58HryX9i9ZfzW1/PwNtHHw4q5+BhNVvRaqJ61aIS5LP
14
+ DzjqlJ4OtpZfNjgmwgk9pfDRmYS8MOld8lNfhIh9WjyuLAW+MiaMZy8o6hTS
15
+ 5vI65QGpD7HbgKQ4tX8LXAPVB8/rF0ReRcb1wiWydeP1eh4Dz6vXvYaJ0Jju
16
+ Q0/yCzbXyGFqv4P6FcOkVAyWhtF2kH/H114DxLq759r3Hoh+IMZutWlWFWhA
17
+ qslFPWN4P9R0kPO2KeiRsLOvBplQIANExar26dRg8hFHx0y3aT3CB7sa9bYw
18
+ DE7t2gVdMEU765f+bZhZQ2M6N2GKQv/UtXUT8xJ9skxFf1aVLDNwFh+3xs1d
19
+ f2WosiqrQ/bsagdZVmuDob9qREdbRP+EF4toWFJyL4wAhTUht1jJFogIkHBl
20
+ GtuT9c/CDQ4je4gANU0vyNf0XmlwYnZ6oQfMl7XBmYeEtXBA5uQAWeFcy6vL
21
+ zqfzwksASCo9LdUqfctD3gjMsm2J+IdAh99OxRcfHvnbV6xL9m+4Ng0GJppJ
22
+ t+w42XqznLRXLTS9RcFD2GFm7mNZziDT2Mb9L4e6Bjy5SoqCftiCbDzGJyka
23
+ BHK/4+l1MsS+J4Qr4qGFF9+HVTP/EF8InQwQECaujyzsrfX8Wn4GuSX4ZdMt
24
+ F0kakkN8A+9LpmFlb8oi4bsmzFTo1tQPRJwann/5TO0jm+Vt6ETmepE0EZ1K
25
+ SIXfQT+a9laF/UJ3bGGxLXIRp3g/ICz0ofBDeSHOCjOVhXVfKnRs/2KpPPex
26
+ yPKLTUdIAtOsKTEtF9JF97C7D/JzxHbssTCj6518BHGxBepn0HZUpeGOlClj
27
+ HiKh8PGKtP0tix1NI/tmhSHCdoi6L/XEryU2pm87qKrlKJU/6z5w7rtpCxto
28
+ X5ztrFk91a3VPEzGRmh7Hw5oNzCi5jmSzZeVgIXxEkVfdUrGAi7ZmJtgEUz5
29
+ 1BJYd2MSBlqHGHF1iIQoqtyklLuqOJR1GvS1/OxQXpXXcVTy47fzlNuKuYkg
30
+ 7beiD5H0Sz/d6J4YNgaJnde+FscHuwOfjzH6uOGQMa6A1NEBW5J1TrAPiVh9
31
+ nm7pPtDg41dScUp3JqeMRA1Akm5wyGna8yocb3CwvSBEy7KrW/8mUR/TpLao
32
+ f9HuWE8UNPjqUl6nTzVpZ2TJFM4ffZbX3NsjS+wsZFtyRAD4z0bBKveUTm19
33
+ pMTBvNljgvGlS6mzYZybPh00l3kiRU9z4Xf7Y1KQH4oSxTpwmgmqiESD0Xv8
34
+ ZmJCU/4VAxbzHwogyeaQvX4pAeC2C1lqgwYdAh6lO7OwgAhkGg3p41V1j6BA
35
+ aOcqaHk+zKpP3pL3jzAZdLvL49y430UXDNN3M6nSafFzSMrPWPjGNyIXVx68
36
+ uDNKCSIcgwAGPtossk0qRKygoQUlKdKull+gOjP/bSIoENKE4rz8RdCsG5qA
37
+ 5T7/iJflhrWGlXfI0MgIe7Lpl41jQ769rI6tSuHu9EsMFOW6/W55IsUR2+p7
38
+ RxClPslQd3tR/TSZvOM5onHK8sM/Lk+rG9BTi0h0ghwVYEiTXPSKPw70z3WY
39
+ 1YlVQS9RSr0AVn9O/Esju2XFtkcE4spXgqiQx0Wx3Y9+21UryNu1amI8rzIH
40
+ N/WeNcE=
@@ -13,6 +13,9 @@ services:
13
13
  - JRUBY_OPTS=-J-Xmx1g
14
14
  - GD_SPEC_PASSWORD
15
15
  - VCR_ON
16
+ - POSTGRES_DB=gooddata
17
+ - POSTGRES_USER=gooddata
18
+ - POSTGRES_PASSWORD=changeit
16
19
  volumes:
17
20
  - .:/src
18
21
  volumes_from:
@@ -1,4 +1,5 @@
1
1
  ---
2
+ generate_attribution_file: true
2
3
  fossa_project: "gooddata-ruby-sdk"
3
4
  ignored_paths:
4
5
  - 'ci/.*'
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=
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.email = 'lcm@gooddata.com'
25
25
  s.extra_rdoc_files = %w(LICENSE README.md)
26
26
 
27
- s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
27
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR).map { |f| f unless %w(NOTICES.txt LICENSE_FOR_RUBY_SDK_COMPONENT.txt).include?(f) }
28
28
  s.files.reject! { |fn| fn.start_with? 'spec/' }
29
29
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
30
30
 
@@ -55,14 +55,17 @@ Gem::Specification.new do |s|
55
55
  s.add_development_dependency 'sqlite3' if RUBY_PLATFORM != 'java'
56
56
 
57
57
  if RUBY_VERSION >= '2.5'
58
- s.add_dependency 'activesupport', '>= 6.0.3.1', '< 6.1'
58
+ s.add_dependency 'activesupport', '>= 6.0.3.1', '< 6.2'
59
59
  else
60
60
  s.add_dependency 'activesupport', '>= 5.2.4.3', '< 6.0'
61
61
  end
62
62
 
63
63
  s.add_dependency 'aws-sdk-s3', '~> 1.16'
64
- s.add_dependency 'docile', '~> 1.1'
65
- s.add_dependency 'erubis', '~> 2.7'
64
+ if RUBY_VERSION >= '2.5'
65
+ s.add_dependency 'docile', '~> 1.1'
66
+ else
67
+ s.add_dependency 'docile', '> 1.1', '< 1.4.0'
68
+ end
66
69
  s.add_dependency 'gli', '~> 2.15'
67
70
  s.add_dependency 'gooddata_datawarehouse', '~> 0.0.10' if RUBY_PLATFORM == 'java'
68
71
  s.add_dependency 'highline', '= 2.0.0.pre.develop.14'
@@ -1,4 +1,4 @@
1
1
  apiVersion: v1
2
2
  name: lcm-bricks
3
3
  description: LCM Bricks
4
- version: 2.0.3
4
+ version: 2.0.6
@@ -92,4 +92,14 @@ data:
92
92
  annotations:
93
93
  description: "We are hitting CPU limit in LCM namespace."
94
94
  summary: "We are hitting CPU limit in LCM namespace."
95
-
95
+ - alert: "[LCM] POD is in undesirable state on cluster={{ .Values.clusterId }}"
96
+ expr: kube_pod_status_phase{namespace='{{ .Release.Namespace }}', phase!~"Running|Succeeded|Failed"} > 0
97
+ for: 5m
98
+ labels:
99
+ cluster_id: {{ .Values.clusterId }}
100
+ severity: critical
101
+ team: lcm
102
+ annotations:
103
+ description: "POD {{`{{ $labels.pod }}`}} is not in desirable state"
104
+ summary: "POD is not in desirable state"
105
+ runbook: "https://confluence.intgdc.com/display/plat/Generic+runbooks#Genericrunbooks-Podisinundesirablestate"
data/lcm.rake CHANGED
@@ -3,7 +3,7 @@ require 'fileutils'
3
3
  require 'pathname'
4
4
  require 'rspec/core/rake_task'
5
5
 
6
- test_cases = %i[integration slow userprov load]
6
+ test_cases = %i[integration-e2e integration-release integration-others slow userprov load]
7
7
 
8
8
  # Schema for new Bricks.
9
9
  brick_info_schema = {
@@ -79,7 +79,7 @@ namespace :test do
79
79
  test_cases.each do |test_case|
80
80
  desc "Run #{test_case} tests"
81
81
  RSpec::Core::RakeTask.new(test_case) do |task|
82
- task.pattern = "spec/lcm/#{test_case}/**/*_spec.rb"
82
+ task.pattern = test_case['integration'] ? "spec/lcm/integration/spec/#{test_case.to_s.split('-')[-1]}/*_spec.rb" : "spec/lcm/#{test_case}/**/*_spec.rb"
83
83
  end
84
84
  end
85
85
 
@@ -101,8 +101,14 @@ namespace :test do
101
101
  test_cases.each do |t|
102
102
  desc "Run #{t} tests in Docker"
103
103
  task t do
104
- system("docker-compose -f docker-compose.lcm.yml run --rm appstore bundle exec rake -f lcm.rake test:#{t}") ||
105
- fail('Test execution failed!')
104
+ if t.to_s == 'integration'
105
+ system("docker-compose -f docker-compose.lcm.yml run --rm appstore /bin/bash -c ./spec/integration_with_postgresql.sh") ||
106
+ fail('Test execution failed!')
107
+ else
108
+ system("docker-compose -f docker-compose.lcm.yml run --rm appstore bundle exec rake -f lcm.rake test:#{t}") ||
109
+ fail('Test execution failed!')
110
+ end
111
+
106
112
  end
107
113
  end
108
114
  end
data/lib/gooddata.rb CHANGED
@@ -37,3 +37,5 @@ require 'backports/2.1.0/array/to_h'
37
37
 
38
38
  # Helpers
39
39
  require 'gooddata/helpers/global_helpers'
40
+
41
+ require 'active_support/core_ext/hash/compact' unless RUBY_VERSION >= '2.5'
@@ -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