aleph_analytics 0.3.0 → 0.4.1
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/CHANGELOG.md +9 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -0
- data/README.md +59 -10
- data/app/models/query_execution.rb +50 -7
- data/app/models/result.rb +8 -4
- data/bin/aleph +36 -4
- data/bin/executables/lib/config_generator.rb +10 -1
- data/bin/executables/lib/playground.rb +14 -4
- data/bin/executables/setup_demo.rb +1 -1
- data/bin/executables/setup_minimal.rb +21 -9
- data/config/example/config.yml +8 -0
- data/config/example/env.yml +2 -0
- data/config/example/snowflake.yml +20 -0
- data/config/initializers/01_internalize_configurations.rb +10 -8
- data/lib/analytic_db_connection_factory.rb +12 -0
- data/lib/analytic_db_connection_pool.rb +8 -0
- data/lib/aws_s3.rb +16 -0
- data/lib/csv_serializer.rb +26 -0
- data/lib/redshift_pg/connection.rb +8 -1
- data/lib/role.rb +2 -2
- data/lib/schemas/descriptor.rb +10 -10
- data/lib/snowflake_db/connection.rb +56 -0
- data/public/assets/{.sprockets-manifest-331daedd75cbbd8f5318863713f13576.json → .sprockets-manifest-4a69de18b234914e05f19cc97d022868.json} +1 -1
- metadata +9 -6
- data/config/attribute-map.yml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e1db8aa9b5d9683d749e21595c0f3060311cf4e
|
4
|
+
data.tar.gz: 6e0f9d737de278e1cc20bfb93b8390f24f142879
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bfcbc8ed2830c89b53d21ba77db6a877981f72f1224cd01dfdf6bdb60e44b1ca249a42a247c3835e5bc249e931fbd3fb5d8e2c304da078604dba0d92c88a30f
|
7
|
+
data.tar.gz: 6ea247ebd88fcc9aa83ab22fc2ae7c6283c0a79aa7fd429d74f6154eacf9828e549d418ac7f9a418ff626da5019410958c0cb252f56e64744c5e9179e0ee2b1d
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file using [Semantic Versioning](http://semver.org/).
|
3
3
|
|
4
|
-
## [0.
|
4
|
+
## [0.4.1] - 2019-09-10
|
5
|
+
### Fixed
|
6
|
+
- [Bug fixes for v0.4.0](https://github.com/lumoslabs/aleph/pull/89)
|
7
|
+
|
8
|
+
## [0.4.0] - 2019-09-02
|
9
|
+
### Features
|
10
|
+
- Added support for Snowflake
|
11
|
+
|
12
|
+
## [0.3.0] - 2019-02-26
|
5
13
|
### Features
|
6
14
|
- [Scheduled Query Execution](https://github.com/lumoslabs/aleph/issues/42)
|
7
15
|
- Fixed s3 location for latest result (useful for GoogleSheet integration)
|
data/Gemfile
CHANGED
@@ -36,7 +36,9 @@ gem 'resque-pool', '~> 0.5.0'
|
|
36
36
|
gem 'resque-web', '0.0.6', require: 'resque_web'
|
37
37
|
gem 'roar'
|
38
38
|
gem 'rollbar', '~> 2.3.0'
|
39
|
+
gem 'ruby-odbc'
|
39
40
|
gem 'sass-rails'
|
41
|
+
gem 'sequel', '~> 4.35'
|
40
42
|
gem 'sprockets-es6', '~> 0.8.0'
|
41
43
|
gem 'therubyracer'
|
42
44
|
gem 'thin'
|
data/Gemfile.lock
CHANGED
@@ -338,6 +338,7 @@ GEM
|
|
338
338
|
rspec-mocks (~> 3.3.0)
|
339
339
|
rspec-support (~> 3.3.0)
|
340
340
|
rspec-support (3.3.0)
|
341
|
+
ruby-odbc (0.99999)
|
341
342
|
ruby-saml (1.0.0)
|
342
343
|
nokogiri (>= 1.5.10)
|
343
344
|
uuid (~> 2.3)
|
@@ -349,6 +350,7 @@ GEM
|
|
349
350
|
sprockets (>= 2.8, < 4.0)
|
350
351
|
sprockets-rails (>= 2.0, < 4.0)
|
351
352
|
tilt (>= 1.1, < 3)
|
353
|
+
sequel (4.49.0)
|
352
354
|
sham_rack (1.3.6)
|
353
355
|
rack
|
354
356
|
shoulda-matchers (3.0.0)
|
@@ -473,7 +475,9 @@ DEPENDENCIES
|
|
473
475
|
roar
|
474
476
|
rollbar (~> 2.3.0)
|
475
477
|
rspec-rails
|
478
|
+
ruby-odbc
|
476
479
|
sass-rails
|
480
|
+
sequel (~> 4.35)
|
477
481
|
sham_rack
|
478
482
|
shoulda-matchers
|
479
483
|
sprockets-es6 (~> 0.8.0)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
# Aleph
|
3
|
-
Aleph is a
|
3
|
+
Aleph is a business analytics platform that focuses on ease-of-use and operational simplicity. It allows analysts to quickly author and iterate on queries, then share result sets and visualizations. Most components are modular, but it was designed to version-control queries (and analyze their differences) using Github and store result sets long term in Amazon S3.
|
4
4
|
|
5
5
|

|
6
6
|
|
@@ -13,15 +13,30 @@ Aleph is a Redshift analytics platform that focuses on aggregating institutional
|
|
13
13
|
|
14
14
|
|
15
15
|
## Quickstart
|
16
|
-
If you want to connect to your own Redshift cluster, the follow instructions should get you up and running.
|
16
|
+
If you want to connect to your own Redshift or Snowflake cluster, the follow instructions should get you up and running.
|
17
|
+
|
18
|
+
### Database Configuration
|
19
|
+
Configure your Redshift or snowflake database and user(s).
|
20
|
+
|
21
|
+
###### Additional requirements for Snowflake
|
22
|
+
* Snowflake users must be setup with default warehouse and role; they are not configurable in Alpeh.
|
23
|
+
* Since Aleph query results are unloaded directly from Snowflake to AWS S3, S3 is required for Snowflake connection.
|
24
|
+
Configure an S3 bucket and create an external S3 stage in Snowflake. e.g.
|
25
|
+
|
26
|
+
create stage mydb.myschema.aleph_stage url='s3://<s3_bucket>/<path>/'
|
27
|
+
credentials=(aws_role = '<iam role>')
|
17
28
|
|
18
29
|
### Docker Install
|
19
30
|
The fastest way to get started: [Docker](https://docs.docker.com/mac/step_one/)
|
20
31
|
|
21
|
-
|
32
|
+
* For Redshift, run
|
22
33
|
|
23
34
|
docker run -ti -p 3000:3000 lumos/aleph-playground /bin/bash -c "aleph setup_minimal -H {host} -D {db} -p {port} -U {user} -P {password}; redis-server & aleph run_demo"
|
24
35
|
|
36
|
+
* For Snowflake, run
|
37
|
+
|
38
|
+
docker run -ti -p 3000:3000 lumos/aleph-snowflake-playground /bin/bash -c "export AWS_ACCESS_KEY_ID=\"{aws_key_id}\" ; export AWS_SECRET_ACCESS_KEY=\"{aws_secret_key}\" ; cd /usr/bin/snowflake_odbc && sed -i 's/SF_ACCOUNT/{your_snowflake_account}/g' ./unixodbc_setup.sh && ./unixodbc_setup.sh && aleph setup_minimal -t snowflake -S snowflake -U {user} -P {password} -L {snowflake_unload_target} -R {s3_region} -B {s3_bucket} -F {s3_folder}; redis-server & aleph run_demo"
|
39
|
+
`snowflake_unload_target` is the external stage and location in snowflake. e.g. `@mydb.myschema.aleph_stage/results/`
|
25
40
|
|
26
41
|
###### Open in browser
|
27
42
|
|
@@ -29,8 +44,17 @@ The fastest way to get started: [Docker](https://docs.docker.com/mac/step_one/)
|
|
29
44
|
|
30
45
|
### Gem Install
|
31
46
|
|
47
|
+
###### For Redshift
|
32
48
|
You must be using [PostgreSQL 9.2beta3 or later client libraries](https://kkob.us/2014/12/20/homebrew-and-postgresql-9-4/)
|
33
49
|
|
50
|
+
###### For Snowflake
|
51
|
+
You must install `unixodbc-dev` and setup and configure [snowflake ODBC](https://docs.snowflake.net/manuals/user-guide/odbc.html). e.g.
|
52
|
+
|
53
|
+
apt-get update && apt-get install -y unixodbc-dev
|
54
|
+
curl -o /tmp/snowflake_linux_x8664_odbc-2.19.8.tgz https://sfc-repo.snowflakecomputing.com/odbc/linux/latest/snowflake_linux_x8664_odbc-2.19.8.tgz && cd /tmp && gunzip snowflake_linux_x8664_odbc-2.19.8.tgz && tar -xvf snowflake_linux_x8664_odbc-2.19.8.tar && cp -r snowflake_odbc /usr/bin && rm -r /tmp/snowflake_odbc
|
55
|
+
cd /usr/bin/snowflake_odbc
|
56
|
+
./unixodbc_setup.sh # and following the instructions to setup Snowflake DSN
|
57
|
+
|
34
58
|
###### Install and run Redis
|
35
59
|
|
36
60
|
brew install redis && redis-server &
|
@@ -39,11 +63,22 @@ You must be using [PostgreSQL 9.2beta3 or later client libraries](https://kkob.u
|
|
39
63
|
|
40
64
|
gem install aleph_analytics
|
41
65
|
|
42
|
-
###### Configure your
|
66
|
+
###### Configure your database
|
67
|
+
See [Database Configuration](#database-configuration) above
|
68
|
+
|
69
|
+
###### Run Aleph
|
70
|
+
* For Redshift
|
43
71
|
|
44
|
-
|
45
|
-
|
72
|
+
aleph setup_minimal -H {host} -D {db} -p {port} -U {user} -P {password}
|
73
|
+
aleph run_demo
|
46
74
|
|
75
|
+
* For Snowflake
|
76
|
+
|
77
|
+
export AWS_ACCESS_KEY_ID="{aws key id}"
|
78
|
+
export AWS_SECRET_ACCESS_KEY="{aws secret key}"
|
79
|
+
aleph setup_minimal -t snowflake -S snowflake -U {user} -P {password} -L {snowflake_unload_target} -R {s3_region} -B {s3_bucket} -F {s3_folder}
|
80
|
+
aleph run_demo
|
81
|
+
|
47
82
|
Aleph should be running at `localhost:3000`
|
48
83
|
|
49
84
|
## Aleph Gem
|
@@ -60,11 +95,17 @@ For a proper production installation, Aleph needs an external Redis instance and
|
|
60
95
|
### The app
|
61
96
|
There are a number of ways to install and deploy Aleph. The simplest is to set up a Dockerfile that installs aleph as a gem:
|
62
97
|
|
63
|
-
FROM ruby:2.
|
98
|
+
FROM ruby:2.2.4
|
64
99
|
|
65
|
-
# we need postgres client libs
|
100
|
+
# we need postgres client libs for Redshift
|
66
101
|
RUN apt-get update && apt-get install -y postgresql-client --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
67
102
|
|
103
|
+
# for Snowflake, install unix odbc and Snowflake ODBC driver and setup DSN
|
104
|
+
# replace {your snowflake account} below
|
105
|
+
RUN apt-get update && apt-get install -y unixodbc-dev
|
106
|
+
RUN curl -o /tmp/snowflake_linux_x8664_odbc-2.19.8.tgz https://sfc-repo.snowflakecomputing.com/odbc/linux/latest/snowflake_linux_x8664_odbc-2.19.8.tgz && cd /tmp && gunzip snowflake_linux_x8664_odbc-2.19.8.tgz && tar -xvf snowflake_linux_x8664_odbc-2.19.8.tar && cp -r snowflake_odbc /usr/bin && rm -r /tmp/snowflake_odbc
|
107
|
+
RUN cd /usr/bin/snowflake_odbc && sed -i 's/SF_ACCOUNT/{your snowflake account}/g' ./unixodbc_setup.sh && ./unixodbc_setup.sh
|
108
|
+
|
68
109
|
# make a log location
|
69
110
|
RUN mkdir -p /var/log/aleph
|
70
111
|
ENV SERVER_LOG_ROOT /var/log/aleph
|
@@ -91,10 +132,15 @@ You can then deploy and run the main components of Aleph as separate services us
|
|
91
132
|
|
92
133
|
At runtime, you can inject all the secrets as environment variables.
|
93
134
|
|
94
|
-
|
135
|
+
S3 is required for Snowflake.
|
136
|
+
|
137
|
+
We *highly* recommend that you have a git repo for your queries and S3 location for you results.
|
95
138
|
|
96
139
|
Advanced setup and configuration details (including how to use Aleph roles for data access, using different auth providers, creating users, and more) can be found [here](docs/ADVANCED_CONFIGURATION.md).
|
97
140
|
|
141
|
+
## Limitation
|
142
|
+
The default maximum result size from Snowflake queries is 5 GB. This is due to the MAX_FILE_SIZE limit of [Snowflake copy command](https://docs.snowflake.net/manuals/sql-reference/sql/copy-into-location.html#copy-options-copyoptions). If Snowflake has changed the limit, update the setting in [snowflake.yml](docs/ADVANCED_CONFIGURATION.md#snowflake)
|
143
|
+
|
98
144
|
## Contribute
|
99
145
|
Aleph is Rails on the backend, Angular on the front end. It uses Resque workers to run queries against Redshift. Here are few things you should have before developing:
|
100
146
|
|
@@ -103,7 +149,7 @@ Aleph is Rails on the backend, Angular on the front end. It uses Resque workers
|
|
103
149
|
* Git Repo (for query versions)
|
104
150
|
* S3 Location (store results)
|
105
151
|
|
106
|
-
While the demo/playground version does not use a git repo
|
152
|
+
While the demo/playground version does not use a git repo and S3 is optional for Redshift, we *highly* recommend that you use them in general.
|
107
153
|
|
108
154
|
### Setup
|
109
155
|
*Postgres*
|
@@ -124,6 +170,7 @@ While the demo/playground version does not use a git repo or S3, we *highly* rec
|
|
124
170
|
|
125
171
|
### Testing
|
126
172
|
|
173
|
+
export PATH="$PWD/node_modules/karma-cli/bin:$PATH"
|
127
174
|
RAILS_ENV=test bundle exec rspec spec
|
128
175
|
bundle exec rake karma:run
|
129
176
|
|
@@ -135,6 +182,8 @@ You can manage your env variables in a .env file
|
|
135
182
|
## Links
|
136
183
|
|
137
184
|
- [Feature Notes](docs/FEATURES.md)
|
185
|
+
- [Development Notes](docs/DEVELOPMENT_NOTES.md)
|
186
|
+
- [Operational Notes](docs/OPERATIONAL_NOTES.md)
|
138
187
|
- [Rubygem](https://rubygems.org/gems/aleph_analytics)
|
139
188
|
- [aleph-user group](https://groups.google.com/forum/#!forum/aleph-user)
|
140
189
|
|
@@ -1,6 +1,17 @@
|
|
1
1
|
class QueryExecution
|
2
2
|
@queue = :query_exec
|
3
3
|
NUM_SAMPLE_ROWS = 100
|
4
|
+
SNOWFLAKE_UNLOAD_SQL = <<-EOF
|
5
|
+
COPY INTO %{location} FROM (
|
6
|
+
%{query}
|
7
|
+
)
|
8
|
+
FILE_FORMAT = (TYPE = 'csv' FIELD_DELIMITER = ',' RECORD_DELIMITER = '\\n' FIELD_OPTIONALLY_ENCLOSED_BY = '"'
|
9
|
+
NULL_IF = ('') COMPRESSION = NONE)
|
10
|
+
HEADER = TRUE
|
11
|
+
SINGLE = TRUE
|
12
|
+
OVERWRITE = TRUE
|
13
|
+
MAX_FILE_SIZE = %{max_file_size}
|
14
|
+
EOF
|
4
15
|
|
5
16
|
def self.perform(result_id, role)
|
6
17
|
result = Result.find(result_id)
|
@@ -14,8 +25,24 @@ class QueryExecution
|
|
14
25
|
result.mark_running!
|
15
26
|
sample_callback = ->(sample) { result.mark_processing_from_sample(sample) }
|
16
27
|
|
17
|
-
connection =
|
28
|
+
connection = AnalyticDBConnectionPool.instance.get(role)
|
29
|
+
if connection.is_a? RedshiftPG::Connection
|
30
|
+
query_redshift(connection, body, result, sample_callback, csv_service)
|
31
|
+
else
|
32
|
+
query_snowflake(connection, body, result, sample_callback)
|
33
|
+
end
|
34
|
+
|
35
|
+
rescue => e
|
36
|
+
if result && csv_service
|
37
|
+
csv_service.clear_tmp_file
|
38
|
+
result.mark_failed!(e.message)
|
39
|
+
end
|
40
|
+
raise
|
41
|
+
end
|
18
42
|
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.query_redshift(connection, body, result, sample_callback, csv_service)
|
19
46
|
connection.reconnect_on_failure do
|
20
47
|
query_stream = PgStream::Stream.new(connection.pg_connection, body)
|
21
48
|
result.headers = query_stream.headers
|
@@ -24,21 +51,37 @@ class QueryExecution
|
|
24
51
|
rrrc = result.redis_result_row_count
|
25
52
|
|
26
53
|
stream_processor = PgStream::Processor.new(query_stream)
|
27
|
-
stream_processor.register(ResultCsvGenerator.new(
|
54
|
+
stream_processor.register(ResultCsvGenerator.new(result.id, result.headers).callbacks)
|
28
55
|
stream_processor.register(SampleSkimmer.new(NUM_SAMPLE_ROWS, &sample_callback).callbacks)
|
29
56
|
stream_processor.register(CountPublisher.new(rrrc).callbacks)
|
30
57
|
|
31
58
|
row_count = stream_processor.execute
|
32
59
|
result.mark_complete_with_count(row_count)
|
33
60
|
end
|
61
|
+
|
34
62
|
rescue *RedshiftPG::USER_ERROR_CLASSES => e
|
35
63
|
csv_service.clear_tmp_file
|
36
64
|
result.mark_failed!(e.message)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.query_snowflake(connection, body, result, sample_callback)
|
68
|
+
# unload the query result from snowflake directly into s3
|
69
|
+
# then read in the first 100 rows from the file as sample rows
|
70
|
+
# Note: snowflake unload currently has a max file size of 5 GB.
|
71
|
+
connection.reconnect_on_failure do
|
72
|
+
body = body.strip.gsub(/;$/, '')
|
73
|
+
location = File.join(connection.unload_target, result.current_result_filename)
|
74
|
+
sql = SNOWFLAKE_UNLOAD_SQL % {location: location, query: body, max_file_size: connection.max_file_size}
|
75
|
+
row = connection.connection.fetch(sql).first
|
76
|
+
row_count = row[:rows_unloaded]
|
77
|
+
|
78
|
+
headers, samples = CsvSerializer.load_from_s3_file(result.current_result_s3_key, NUM_SAMPLE_ROWS)
|
79
|
+
|
80
|
+
result.headers = headers
|
81
|
+
result.save!
|
82
|
+
|
83
|
+
sample_callback.call(samples)
|
84
|
+
result.mark_complete_with_count(row_count)
|
41
85
|
end
|
42
|
-
raise
|
43
86
|
end
|
44
87
|
end
|
data/app/models/result.rb
CHANGED
@@ -53,6 +53,14 @@ class Result < ActiveRecord::Base
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
def current_result_filename
|
57
|
+
@result_filename ||= CsvHelper::Base.new(id).filename
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_result_s3_key
|
61
|
+
@result_key ||= CsvHelper::Aws.new(id).key
|
62
|
+
end
|
63
|
+
|
56
64
|
private
|
57
65
|
|
58
66
|
def duration(start_field, end_field)
|
@@ -67,8 +75,4 @@ class Result < ActiveRecord::Base
|
|
67
75
|
0
|
68
76
|
end
|
69
77
|
end
|
70
|
-
|
71
|
-
def current_result_s3_key
|
72
|
-
@result_key ||= CsvHelper::Aws.new(id).key
|
73
|
-
end
|
74
78
|
end
|
data/bin/aleph
CHANGED
@@ -33,6 +33,10 @@ class CommandParser
|
|
33
33
|
@options[:worker_processes] = w
|
34
34
|
end
|
35
35
|
|
36
|
+
opts.on('-t', '--db_type DB_TYPE', 'redshift or snowflake. Default is redshift') do |t|
|
37
|
+
@options[:db_type] = t
|
38
|
+
end
|
39
|
+
|
36
40
|
opts.on('-H', '--redshift-host REDSHIFT_HOST', 'Redshift Hostname') do |rhost|
|
37
41
|
@options[:redshift_host] = rhost
|
38
42
|
end
|
@@ -45,12 +49,40 @@ class CommandParser
|
|
45
49
|
@options[:redshift_port] = rport
|
46
50
|
end
|
47
51
|
|
48
|
-
opts.on('-U', '--
|
49
|
-
@options[:
|
52
|
+
opts.on('-U', '--db-user DB_USER', 'Redshift or Snowflake User') do |dbuser|
|
53
|
+
@options[:db_user] = dbuser
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('--redshift-user DB_USER', 'Same as --db-user (for backward compatibility)') do |dbuser|
|
57
|
+
@options[:db_user] = dbuser
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on('-P', '--db-password DB_PASSWORD', 'Redshift or Snowflake Password') do |dbpw|
|
61
|
+
@options[:db_password] = dbpw
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on('--redshift-password DB_PASSWORD', 'Same as --db-password (for backward compatibility)') do |dbpw|
|
65
|
+
@options[:db_password] = dbpw
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on('-S', '---dsn ODBC_DSN', 'Snowflake ODBC DSN') do |dsn|
|
69
|
+
@options[:dsn] = dsn
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on('-L', '---snowflake_unload_target STAGE_OR_LOCATION', 'Snowflake only. Stage or location where result files are unloaded') do |target|
|
73
|
+
@options[:snowflake_unload_target] = target
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on('-R', '---s3_region S3_REGION', 's3 Region') do |region|
|
77
|
+
@options[:s3_region] = region
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on('-B', '---s3_bucket S3_BUCKET', 's3 bucket which result files are unloaded. Required for Snowflake DB') do |bucket|
|
81
|
+
@options[:s3_bucket] = bucket
|
50
82
|
end
|
51
83
|
|
52
|
-
opts.on('-
|
53
|
-
@options[:
|
84
|
+
opts.on('-F', '---s3_bucket S3_FOLDER', 's3 folder where result files are unloaded') do |folder|
|
85
|
+
@options[:s3_folder] = folder
|
54
86
|
end
|
55
87
|
|
56
88
|
opts.on('-h', '--help', 'Halp!') do |h|
|
@@ -22,7 +22,16 @@ module AlephExecutables
|
|
22
22
|
write_yaml('redshift.yml', redshift_properties, environments: [@rails_env.to_sym])
|
23
23
|
@env_writer.merge(admin_redshift_username: user, admin_redshift_password: password)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
|
+
def write_snowflake(dsn, user, password, unload_target)
|
27
|
+
snowflake_properties = {
|
28
|
+
'dsn' => dsn,
|
29
|
+
'unload_target' => unload_target
|
30
|
+
}
|
31
|
+
write_yaml('snowflake.yml', snowflake_properties, environments: [@rails_env.to_sym])
|
32
|
+
@env_writer.merge(admin_snowflake_username: user, admin_snowflake_password: password)
|
33
|
+
end
|
34
|
+
|
26
35
|
def write_envs!
|
27
36
|
@env_writer.write!
|
28
37
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module AlephExecutables
|
2
2
|
class Playground
|
3
|
-
|
4
|
-
config_path = options[:config_path] || '/tmp/aleph/demo/configuration'
|
3
|
+
CONFIG_OPTIONS = [:s3_region, :s3_bucket, :s3_folder]
|
5
4
|
|
5
|
+
def self.setup(db_type, host, dsn, db, port, user, password, options = {})
|
6
|
+
config_path = options[:config_path] || '/tmp/aleph/demo/configuration'
|
6
7
|
seed_db = options[:seed_db]
|
7
8
|
|
8
9
|
config_generator = ConfigGenerator.new(config_path, 'playground')
|
@@ -10,9 +11,18 @@ module AlephExecutables
|
|
10
11
|
config_generator.merge_envs(redis_url: 'redis://localhost:6379')
|
11
12
|
config_generator.merge_envs(aleph_query_exec_worker_pool: 1)
|
12
13
|
config_generator.merge_envs(aleph_alert_exec_worker_pool: 1)
|
13
|
-
|
14
|
+
config_generator.merge_envs(analytic_db_type: db_type)
|
15
|
+
|
16
|
+
properties = options.select{ |k,_| CONFIG_OPTIONS.include?(k) }.map{ |k, v| [k.to_s, v] }.to_h.
|
17
|
+
merge({ 'auth_type' => 'disabled' })
|
14
18
|
config_generator.write_yaml('config.yml', properties, environments: [:playground])
|
15
|
-
|
19
|
+
|
20
|
+
if db_type == 'snowflake'
|
21
|
+
config_generator.write_snowflake(dsn, user, password, options[:snowflake_unload_target])
|
22
|
+
else
|
23
|
+
config_generator.write_redshift(host, db, port, user, password)
|
24
|
+
end
|
25
|
+
|
16
26
|
config_generator.write_envs!
|
17
27
|
|
18
28
|
Bundler.with_clean_env do
|
@@ -12,7 +12,7 @@ module AlephExecutables
|
|
12
12
|
|
13
13
|
def execute!
|
14
14
|
options = @options.select{ |k,v| k == :config_path}.merge(seed_db: true)
|
15
|
-
Playground.setup(HOST, DB, PORT, USER, PASSWORD, options)
|
15
|
+
Playground.setup('redshift', HOST, nil, DB, PORT, USER, PASSWORD, options)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -6,20 +6,32 @@ module AlephExecutables
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def execute!
|
9
|
-
options = @options.select{ |k,v|
|
9
|
+
options = @options.select{ |k,v| [:config_path, :s3_region, :s3_bucket, :s3_folder, :snowflake_unload_target].include?(k) }
|
10
10
|
host = @options[:redshift_host]
|
11
11
|
db = @options[:redshift_db]
|
12
12
|
port = @options[:redshift_port]
|
13
|
-
user = @options[:
|
14
|
-
password = @options[:
|
13
|
+
user = @options[:db_user]
|
14
|
+
password = @options[:db_password]
|
15
|
+
dsn = @options[:dsn]
|
16
|
+
db_type = @options[:db_type] || 'redshift'
|
17
|
+
snowflake_unload_target = @options[:snowflake_unload_target]
|
18
|
+
s3_bucket = @options[:s3_bucket]
|
15
19
|
|
16
|
-
Utils.fail "
|
17
|
-
Utils.fail "Missing
|
18
|
-
Utils.fail "Missing
|
19
|
-
Utils.fail "Missing Redshift User", @banner unless present? user
|
20
|
-
Utils.fail "Missing Redshift Password", @banner unless present? password
|
20
|
+
Utils.fail "Invalid database type (must be redshift or snowflake)", @banner unless ['redshift', 'snowflake'].include?(db_type)
|
21
|
+
Utils.fail "Missing DB User", @banner unless present? user
|
22
|
+
Utils.fail "Missing DB Password", @banner unless present? password
|
21
23
|
|
22
|
-
|
24
|
+
if db_type == 'redshift'
|
25
|
+
Utils.fail "Missing Redshift Host", @banner unless present? host
|
26
|
+
Utils.fail "Missing Redshift Db", @banner unless present? db
|
27
|
+
Utils.fail "Missing Redshift Port", @banner unless present? port
|
28
|
+
else
|
29
|
+
Utils.fail "Missing Snowflake ODBC DSN", @banner unless present? dsn
|
30
|
+
Utils.fail "Missing Snowflake Unload Target", @banner unless present? snowflake_unload_target
|
31
|
+
Utils.fail "Missing s3 bucket (This is required for Snowflake connection)", @banner unless present? s3_bucket
|
32
|
+
end
|
33
|
+
|
34
|
+
Playground.setup db_type, host, dsn, db, port, user, password, options
|
23
35
|
end
|
24
36
|
|
25
37
|
def present?(v)
|