flare-up 0.2 → 0.3
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 +8 -8
- data/Gemfile.lock +1 -1
- data/README.md +34 -11
- data/lib/flare_up/boot.rb +1 -1
- data/lib/flare_up/stl_load_error.rb +7 -2
- data/lib/flare_up/stl_load_error_fetcher.rb +1 -1
- data/lib/flare_up/version.rb +1 -1
- data/spec/lib/flare_up/stl_load_error_fetcher_spec.rb +5 -3
- data/spec/lib/flare_up/stl_load_error_spec.rb +5 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NmI5NGU5NTk4NjAzNDE1ODY4YTQ1ODRjNGVhZmZjYjFkNjlhYjEzNQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzhiOTAyMDk5YTlmODg3NmJlM2M5OWI5ZWYyOTJjMzZjMDdhZmI5ZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZDQ1MjFiZjkyMGU1MTUyYjU2ZTVlYjQyNzAyMGYwMmM0MGVhYmZkMWM3NzFj
|
10
|
+
NDI0NmRmOGYwNDdiYWYwZTNhODBiZmZkZDVhYmUxNzhlODlkMGNlYTAzY2Nk
|
11
|
+
NmQ1MzFjMWQwODY1YjliMzM3NTkxNjY1ODRjYTlhN2Y4YjllY2Q=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjRlOGVmMGFjYzdiYTUyMWU3NTlhODcwNmM2NTc1NTJhNjU3MjBmYzZhY2Jj
|
14
|
+
ZTAwNmU4NzgwZGJkMmFjMDE3MTc5YTllOGFkOTVjMjkyZTc1MjEyMjkyZTA2
|
15
|
+
MjU2YjFhOGJhZTYzMGJhNTg2ODhiY2MwZTM4NGM1YmE5YmJmYTg=
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -3,27 +3,50 @@
|
|
3
3
|
|
4
4
|
## Why?
|
5
5
|
|
6
|
-
Redshift prefers a bulk COPY operation over indidivual INSERTs which Redshift is not optimized for, and Amazon does not recommend it as a strategy for
|
6
|
+
Redshift prefers a bulk COPY operation over indidivual INSERTs which Redshift is not optimized for, and Amazon does not recommend it as a strategy for loading. COPY is a SQL command, not something issued via the AWS Redshift REST API, meaning you need a SQL connection to your Redshift instance to bulk load data.
|
7
7
|
|
8
8
|
The astute consumer of the AWS toolchain will note that [Data Pipeline](http://aws.amazon.com/datapipeline/) is one way this import may be completed however, we use Azkaban and the only thing worse one than one job flow control tool is two job flow control tools :)
|
9
9
|
|
10
|
-
Additionally, access to COPY errors is a bit cumbersome. On failure, Redshift populates the ```stl_load_errors``` table which inherently must be accessed via SQL. Flare-up will pretty print any errors that occur during import so that you may examine your logs
|
10
|
+
Additionally, access to COPY errors is a bit cumbersome. On failure, Redshift populates the ```stl_load_errors``` table which inherently must be accessed via SQL. Flare-up will pretty print any errors that occur during import so that you may examine your logs rather than establishing a connection to Redshift to understand what went wrong.
|
11
|
+
|
12
|
+
## Requirements and Installation
|
13
|
+
|
14
|
+
The `pg` gem is a dependency (required to issue SQL commands to Redshift) and will be pulled down with flare-up.
|
11
15
|
|
12
16
|
```
|
13
|
-
|
17
|
+
> gem install flare-up
|
14
18
|
```
|
15
19
|
|
16
|
-
##
|
20
|
+
## Syntax
|
21
|
+
|
22
|
+
Available via `flare-up help copy`.
|
17
23
|
|
18
|
-
|
24
|
+
While we'd prefer if everyone stored configuration variables (esp. credentials) as environment variables (re: [Twelve-Factor App](http://12factor.net/)), it can be a pain to export variables when you're testing a tool and as such, we support specifying all of these on the command-line.
|
25
|
+
|
26
|
+
```
|
27
|
+
Usage:
|
28
|
+
flare-up copy DATA_SOURCE REDSHIFT_ENDPOINT DATABASE TABLE
|
29
|
+
|
30
|
+
Options:
|
31
|
+
[--aws-access-key=AWS_ACCESS_KEY] # Required unless ENV['AWS_ACCESS_KEY_ID'] is set.
|
32
|
+
[--aws-secret-key=AWS_SECRET_KEY] # Required unless ENV['AWS_SECRET_ACCESS_KEY'] is set.
|
33
|
+
[--redshift-username=REDSHIFT_USERNAME] # Required unless ENV['REDSHIFT_USERNAME'] is set.
|
34
|
+
[--redshift-password=REDSHIFT_PASSWORD] # Required unless ENV['REDSHIFT_PASSWORD'] is set.
|
35
|
+
[--column-list=one two three] # A space-separated list of columns, should your DATA_SOURCE require it
|
36
|
+
[--copy-options=COPY_OPTIONS] # Appended to the end of the COPY command; enclose "IN QUOTES"
|
37
|
+
```
|
19
38
|
|
20
|
-
|
39
|
+
## Sample Usage
|
21
40
|
|
22
|
-
|
41
|
+
Note that this example assumes you have credentials set as environment variables.
|
23
42
|
|
24
43
|
```
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
44
|
+
> flare-up \
|
45
|
+
copy \
|
46
|
+
s3://slif-redshift/hearthstone_cards_short_list.csv \
|
47
|
+
flare-up-test.cskjnp4xvaje.us-west-2.redshift.amazonaws.com \
|
48
|
+
dev \
|
49
|
+
hearthstone_cards \
|
50
|
+
--column-list name cost attack health description \
|
51
|
+
--copy_options "REGION 'us-east-1' CSV"
|
29
52
|
```
|
data/lib/flare_up/boot.rb
CHANGED
@@ -40,7 +40,7 @@ module FlareUp
|
|
40
40
|
# TODO: How can we test this?
|
41
41
|
def self.handle_load_errors(stl_load_errors)
|
42
42
|
return if stl_load_errors.empty?
|
43
|
-
puts "\x1b[31mThere was an error processing the COPY command
|
43
|
+
puts "\x1b[31mThere was an error processing the COPY command. Displaying the last (#{stl_load_errors.length}) errors."
|
44
44
|
stl_load_errors.each do |e|
|
45
45
|
puts e.pretty_print
|
46
46
|
end
|
@@ -11,8 +11,9 @@ module FlareUp
|
|
11
11
|
attr_reader :filename
|
12
12
|
attr_reader :position
|
13
13
|
attr_reader :line_number
|
14
|
+
attr_reader :start_time
|
14
15
|
|
15
|
-
def initialize(err_reason, raw_field_value, raw_line, col_length, type, colname, filename, position, line_number)
|
16
|
+
def initialize(err_reason, raw_field_value, raw_line, col_length, type, colname, filename, position, line_number, start_time)
|
16
17
|
@err_reason = err_reason
|
17
18
|
@raw_field_value = raw_field_value
|
18
19
|
@raw_line = raw_line
|
@@ -22,6 +23,7 @@ module FlareUp
|
|
22
23
|
@filename = filename
|
23
24
|
@position = position
|
24
25
|
@line_number = line_number
|
26
|
+
@start_time = start_time
|
25
27
|
end
|
26
28
|
|
27
29
|
def ==(other_error)
|
@@ -34,11 +36,13 @@ module FlareUp
|
|
34
36
|
return false unless @filename == other_error.filename
|
35
37
|
return false unless @position == other_error.position
|
36
38
|
return false unless @line_number == other_error.line_number
|
39
|
+
return false unless @start_time == other_error.start_time
|
37
40
|
true
|
38
41
|
end
|
39
42
|
|
40
43
|
def pretty_print
|
41
44
|
output = ''
|
45
|
+
output += "\e[33mSTART : \e[37m#{@start_time} (#{@start_time - 7 * 60 * 60} PST)\n"
|
42
46
|
output += "\e[33mREASON: \e[37m#{@err_reason}\n"
|
43
47
|
output += "\e[33mLINE : \e[37m#{@line_number}\n"
|
44
48
|
output += "\e[33mPOS : \e[37m#{@position}\n"
|
@@ -58,7 +62,8 @@ module FlareUp
|
|
58
62
|
row['colname'].strip,
|
59
63
|
row['filename'].strip,
|
60
64
|
row['position'].strip.to_i,
|
61
|
-
row['line_number'].strip.to_i
|
65
|
+
row['line_number'].strip.to_i,
|
66
|
+
Time.parse("#{row['starttime'].strip} UTC'")
|
62
67
|
)
|
63
68
|
end
|
64
69
|
|
@@ -3,7 +3,7 @@ module FlareUp
|
|
3
3
|
class STLLoadErrorFetcher
|
4
4
|
|
5
5
|
def self.fetch_errors(connection)
|
6
|
-
query_result = connection.execute('SELECT * FROM stl_load_errors ORDER BY query DESC, line_number, position LIMIT
|
6
|
+
query_result = connection.execute('SELECT * FROM stl_load_errors ORDER BY query DESC, line_number, position LIMIT 3')
|
7
7
|
errors = []
|
8
8
|
query_result.each do |row|
|
9
9
|
errors << STLLoadError.from_pg_results_row(row)
|
data/lib/flare_up/version.rb
CHANGED
@@ -6,7 +6,7 @@ describe FlareUp::STLLoadErrorFetcher do
|
|
6
6
|
|
7
7
|
before do
|
8
8
|
expect(connection).to receive(:execute).
|
9
|
-
with('SELECT * FROM stl_load_errors ORDER BY query DESC, line_number, position LIMIT
|
9
|
+
with('SELECT * FROM stl_load_errors ORDER BY query DESC, line_number, position LIMIT 3').
|
10
10
|
and_return([
|
11
11
|
{
|
12
12
|
'err_reason' => 'TEST_REASON',
|
@@ -17,7 +17,8 @@ describe FlareUp::STLLoadErrorFetcher do
|
|
17
17
|
'colname' => 'TEST_COLNAME',
|
18
18
|
'filename' => 'TEST_FILENAME',
|
19
19
|
'position' => '2',
|
20
|
-
'line_number' => '3'
|
20
|
+
'line_number' => '3',
|
21
|
+
'starttime' => '2014-08-11 06:06:59'
|
21
22
|
}
|
22
23
|
])
|
23
24
|
end
|
@@ -34,7 +35,8 @@ describe FlareUp::STLLoadErrorFetcher do
|
|
34
35
|
'TEST_COLNAME',
|
35
36
|
'TEST_FILENAME',
|
36
37
|
2,
|
37
|
-
3
|
38
|
+
3,
|
39
|
+
Time.parse('2014-08-11 06:06:59 UTC')
|
38
40
|
)
|
39
41
|
]
|
40
42
|
)
|
@@ -10,7 +10,8 @@ describe FlareUp::STLLoadError do
|
|
10
10
|
'TEST_COLNAME',
|
11
11
|
'TEST_FILENAME',
|
12
12
|
2,
|
13
|
-
3
|
13
|
+
3,
|
14
|
+
Time.parse('2014-08-11 06:06:59 UTC')
|
14
15
|
)
|
15
16
|
end
|
16
17
|
|
@@ -35,7 +36,8 @@ describe FlareUp::STLLoadError do
|
|
35
36
|
'colname' => 'TEST_COLNAME ',
|
36
37
|
'filename' => 'TEST_FILENAME ',
|
37
38
|
'position' => '2 ',
|
38
|
-
'line_number' => '3 '
|
39
|
+
'line_number' => '3 ',
|
40
|
+
'starttime' => '2014-08-11 06:06:59 '
|
39
41
|
}
|
40
42
|
end
|
41
43
|
|
@@ -55,6 +57,7 @@ describe FlareUp::STLLoadError do
|
|
55
57
|
expect(load_error_from_hash.filename).to eq('TEST_FILENAME')
|
56
58
|
expect(load_error_from_hash.position).to eq(2)
|
57
59
|
expect(load_error_from_hash.line_number).to eq(3)
|
60
|
+
expect(load_error_from_hash.start_time).to eq(Time.parse('2014-08-11 06:06:59 UTC'))
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|