aleph_analytics 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
![aleph](images/aleph_repo_banner.png)
|
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)
|