flare-up 0.1 → 0.2
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/.gitignore +3 -1
- data/.rspec +3 -0
- data/.ruby-version +1 -1
- data/.travis.yml +6 -0
- data/Gemfile.lock +25 -1
- data/README.md +29 -0
- data/Rakefile +10 -0
- data/bin/flare-up +5 -0
- data/flare-up.gemspec +24 -0
- data/lib/flare_up/boot.rb +51 -0
- data/lib/flare_up/cli.rb +60 -0
- data/lib/flare_up/connection.rb +74 -0
- data/lib/flare_up/copy_command.rb +73 -0
- data/lib/flare_up/env_wrap.rb +11 -0
- data/lib/flare_up/stl_load_error.rb +67 -0
- data/lib/flare_up/stl_load_error_fetcher.rb +16 -0
- data/lib/flare_up/version.rb +1 -1
- data/lib/flare_up.rb +13 -0
- data/resources/README.md +7 -0
- data/resources/hearthstone_cards.csv +3 -0
- data/resources/load_hearthstone_cards.rb +64 -0
- data/resources/postgresql-8.4-703.jdbc4.jar +0 -0
- data/resources/test_schema.sql +10 -0
- data/spec/lib/flare_up/boot_spec.rb +100 -0
- data/spec/lib/flare_up/cli_spec.rb +162 -0
- data/spec/lib/flare_up/connection_spec.rb +114 -0
- data/spec/lib/flare_up/copy_command_spec.rb +134 -0
- data/spec/lib/flare_up/stl_load_error_fetcher_spec.rb +45 -0
- data/spec/lib/flare_up/stl_load_error_spec.rb +61 -0
- data/spec/spec_helper.rb +5 -0
- metadata +110 -9
- data/flareup.gemspec +0 -17
@@ -0,0 +1,100 @@
|
|
1
|
+
describe FlareUp::Boot do
|
2
|
+
|
3
|
+
describe '.boot' do
|
4
|
+
let(:copy_command) { instance_double('FlareUp::CopyCommand') }
|
5
|
+
|
6
|
+
context 'when there is an error' do
|
7
|
+
before do
|
8
|
+
expect(FlareUp::Boot).to receive(:create_copy_command).and_return(copy_command)
|
9
|
+
expect(copy_command).to receive(:execute).and_raise(copy_command_error)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when there is a DataSourceError' do
|
13
|
+
let(:copy_command_error) { FlareUp::DataSourceError }
|
14
|
+
it 'should handle the error' do
|
15
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
16
|
+
expect { FlareUp::Boot.boot({}) }.not_to raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when there is a OtherZoneBucketError' do
|
21
|
+
let(:copy_command_error) { FlareUp::OtherZoneBucketError }
|
22
|
+
it 'should handle the error' do
|
23
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
24
|
+
expect { FlareUp::Boot.boot({}) }.not_to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when there is a OtherZoneBucketError' do
|
29
|
+
let(:copy_command_error) { FlareUp::SyntaxError }
|
30
|
+
it 'should handle the error' do
|
31
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
32
|
+
expect { FlareUp::Boot.boot({}) }.not_to raise_error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.create_connection' do
|
41
|
+
let(:options) {
|
42
|
+
{
|
43
|
+
:redshift_endpoint => 'TEST_REDSHIFT_ENDPOINT',
|
44
|
+
:database => 'TEST_DATABASE',
|
45
|
+
:redshift_username => 'TEST_REDSHIFT_USERNAME',
|
46
|
+
:redshift_password => 'TEST_REDSHIFT_PASSWORD'
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
it 'should create a connection' do
|
51
|
+
connection = FlareUp::Boot.create_connection(options)
|
52
|
+
expect(connection.host).to eq('TEST_REDSHIFT_ENDPOINT')
|
53
|
+
expect(connection.dbname).to eq('TEST_DATABASE')
|
54
|
+
expect(connection.user).to eq('TEST_REDSHIFT_USERNAME')
|
55
|
+
expect(connection.password).to eq('TEST_REDSHIFT_PASSWORD')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.create_copy_command' do
|
60
|
+
|
61
|
+
let(:options) {
|
62
|
+
{
|
63
|
+
:table => 'TEST_TABLE',
|
64
|
+
:data_source => 'TEST_DATA_SOURCE',
|
65
|
+
:aws_access_key => 'TEST_ACCESS_KEY',
|
66
|
+
:aws_secret_key => 'TEST_SECRET_KEY'
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
it 'should create a proper copy command' do
|
71
|
+
command = FlareUp::Boot.create_copy_command(options)
|
72
|
+
expect(command.table_name).to eq('TEST_TABLE')
|
73
|
+
expect(command.data_source).to eq('TEST_DATA_SOURCE')
|
74
|
+
expect(command.aws_access_key_id).to eq('TEST_ACCESS_KEY')
|
75
|
+
expect(command.aws_secret_access_key).to eq('TEST_SECRET_KEY')
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when columns are specified' do
|
79
|
+
before do
|
80
|
+
options.merge!(:column_list => ['c1'])
|
81
|
+
end
|
82
|
+
it 'should create a proper copy command' do
|
83
|
+
command = FlareUp::Boot.create_copy_command(options)
|
84
|
+
expect(command.columns).to eq(['c1'])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when options are specified' do
|
89
|
+
before do
|
90
|
+
options.merge!(:copy_options => '_')
|
91
|
+
end
|
92
|
+
it 'should create a proper copy command' do
|
93
|
+
command = FlareUp::Boot.create_copy_command(options)
|
94
|
+
expect(command.options).to eq('_')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
describe FlareUp::CLI do
|
2
|
+
|
3
|
+
let(:required_arguments) { %w(copy TEST_DATA_SOURCE TEST_REDSHIFT_ENDPOINT TEST_DATABASE TEST_TABLE) }
|
4
|
+
let(:required_options) do
|
5
|
+
{
|
6
|
+
:data_source => 'TEST_DATA_SOURCE',
|
7
|
+
:redshift_endpoint => 'TEST_REDSHIFT_ENDPOINT',
|
8
|
+
:database => 'TEST_DATABASE',
|
9
|
+
:table => 'TEST_TABLE',
|
10
|
+
:redshift_username => 'TEST_REDSHIFT_USERNAME',
|
11
|
+
:redshift_password => 'TEST_REDSHIFT_PASSWORD',
|
12
|
+
:aws_access_key => 'TEST_AWS_ACCESS_KEY',
|
13
|
+
:aws_secret_key => 'TEST_AWS_SECRET_KEY'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('AWS_ACCESS_KEY_ID').and_return('TEST_AWS_ACCESS_KEY')
|
19
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('AWS_SECRET_ACCESS_KEY').and_return('TEST_AWS_SECRET_KEY')
|
20
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('REDSHIFT_USERNAME').and_return('TEST_REDSHIFT_USERNAME')
|
21
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('REDSHIFT_PASSWORD').and_return('TEST_REDSHIFT_PASSWORD')
|
22
|
+
allow(FlareUp::Boot).to receive(:boot)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#copy' do
|
26
|
+
|
27
|
+
context 'when no options are specified' do
|
28
|
+
it 'should boot with the proper options' do
|
29
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options)
|
30
|
+
FlareUp::CLI.start(required_arguments)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when column ordering is specified' do
|
35
|
+
it 'should boot with the proper options' do
|
36
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:column_list => %w(c1 c2 c3)))
|
37
|
+
FlareUp::CLI.start(required_arguments + %w(--column_list c1 c2 c3))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when COPY options are specified' do
|
42
|
+
it 'should boot with the proper options' do
|
43
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:copy_options => 'TEST_COPY_OPTIONS WITH A SPACE'))
|
44
|
+
FlareUp::CLI.start(required_arguments + ['--copy_options', 'TEST_COPY_OPTIONS WITH A SPACE'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'Redshift credentials' do
|
49
|
+
|
50
|
+
describe 'username' do
|
51
|
+
context 'when it is specified on the CLI' do
|
52
|
+
it 'should boot with the proper options' do
|
53
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:redshift_username => 'CLI_VALUE'))
|
54
|
+
FlareUp::CLI.start(required_arguments + %w(--redshift_username CLI_VALUE))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
context 'when it is not specified on the CLI' do
|
58
|
+
context 'when it is available via ENV' do
|
59
|
+
it 'should boot with the key from the environment' do
|
60
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:redshift_username => 'TEST_REDSHIFT_USERNAME'))
|
61
|
+
FlareUp::CLI.start(required_arguments)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
context 'when it is not available via ENV' do
|
65
|
+
before do
|
66
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('REDSHIFT_USERNAME').and_return(nil)
|
67
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
68
|
+
end
|
69
|
+
it 'should be an error' do
|
70
|
+
FlareUp::CLI.start(required_arguments)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'password' do
|
77
|
+
context 'when it is specified on the CLI' do
|
78
|
+
it 'should boot with the proper options' do
|
79
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:redshift_password => 'CLI_VALUE'))
|
80
|
+
FlareUp::CLI.start(required_arguments + %w(--redshift_password CLI_VALUE))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
context 'when it is not specified on the CLI' do
|
84
|
+
context 'when it is available via ENV' do
|
85
|
+
it 'should boot with the key from the environment' do
|
86
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:redshift_password => 'TEST_REDSHIFT_PASSWORD'))
|
87
|
+
FlareUp::CLI.start(required_arguments)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
context 'when it is not available via ENV' do
|
91
|
+
before do
|
92
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('REDSHIFT_PASSWORD').and_return(nil)
|
93
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
94
|
+
end
|
95
|
+
it 'should be an error' do
|
96
|
+
FlareUp::CLI.start(required_arguments)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'AWS credentials' do
|
105
|
+
|
106
|
+
describe 'access key' do
|
107
|
+
context 'when an AWS access key is specified' do
|
108
|
+
it 'should boot with the proper options' do
|
109
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:aws_access_key => 'CLI_KEY'))
|
110
|
+
FlareUp::CLI.start(required_arguments + %w(--aws_access_key CLI_KEY))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
context 'when an AWS access key is not specified' do
|
114
|
+
context 'when the key is available via ENV' do
|
115
|
+
it 'should boot with the key from the environment' do
|
116
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:aws_access_key => 'TEST_AWS_ACCESS_KEY'))
|
117
|
+
FlareUp::CLI.start(required_arguments)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
context 'when the key is not available via ENV' do
|
121
|
+
before do
|
122
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('AWS_ACCESS_KEY_ID').and_return(nil)
|
123
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
124
|
+
end
|
125
|
+
it 'should be an error' do
|
126
|
+
FlareUp::CLI.start(required_arguments)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe 'secret key' do
|
133
|
+
context 'when an AWS secret key is specified' do
|
134
|
+
it 'should boot with the proper options' do
|
135
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:aws_secret_key => 'CLI_KEY'))
|
136
|
+
FlareUp::CLI.start(required_arguments + %w(--aws_secret_key CLI_KEY))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
context 'when an AWS secret key is not specified' do
|
140
|
+
context 'when the key is available via ENV' do
|
141
|
+
it 'should boot with the key from the environment' do
|
142
|
+
expect(FlareUp::Boot).to receive(:boot).with(required_options.merge(:aws_secret_key => 'TEST_AWS_SECRET_KEY'))
|
143
|
+
FlareUp::CLI.start(required_arguments)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
context 'when the key is not available via ENV' do
|
147
|
+
before do
|
148
|
+
allow(FlareUp::ENVWrap).to receive(:get).with('AWS_SECRET_ACCESS_KEY').and_return(nil)
|
149
|
+
expect(FlareUp::CLI).to receive(:bailout).with(1)
|
150
|
+
end
|
151
|
+
it 'should be an error' do
|
152
|
+
FlareUp::CLI.start(required_arguments)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
describe FlareUp::Connection do
|
2
|
+
|
3
|
+
subject do
|
4
|
+
FlareUp::Connection.new('TEST_HOST', 'TEST_DB_NAME', 'TEST_USER', 'TEST_PASSWORD')
|
5
|
+
end
|
6
|
+
|
7
|
+
its(:host) { should == 'TEST_HOST' }
|
8
|
+
its(:port) { should == 5439 }
|
9
|
+
its(:dbname) { should == 'TEST_DB_NAME' }
|
10
|
+
its(:user) { should == 'TEST_USER' }
|
11
|
+
its(:password) { should == 'TEST_PASSWORD' }
|
12
|
+
its(:connect_timeout) { should == 5 }
|
13
|
+
|
14
|
+
describe 'Writers' do
|
15
|
+
subject do
|
16
|
+
FlareUp::Connection.new('', '', '', '').tap do |c|
|
17
|
+
c.host = 'TEST_HOST'
|
18
|
+
c.port = 111
|
19
|
+
c.dbname = 'TEST_DB_NAME'
|
20
|
+
c.user = 'TEST_USER'
|
21
|
+
c.password = 'TEST_PASSWORD'
|
22
|
+
c.connect_timeout = 222
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
its(:host) { should == 'TEST_HOST' }
|
27
|
+
its(:port) { should == 111 }
|
28
|
+
its(:dbname) { should == 'TEST_DB_NAME' }
|
29
|
+
its(:user) { should == 'TEST_USER' }
|
30
|
+
its(:password) { should == 'TEST_PASSWORD' }
|
31
|
+
its(:connect_timeout) { should == 222 }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#connect' do
|
35
|
+
|
36
|
+
context 'when the connection succeeds' do
|
37
|
+
let(:mock_params) { { :foo => 'bar' } }
|
38
|
+
|
39
|
+
before do
|
40
|
+
allow(subject).to receive(:connection_parameters).and_return(mock_params)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should connect to Redshift with the appropriate parameters' do
|
44
|
+
expect(PG).to receive(:connect).with(mock_params)
|
45
|
+
|
46
|
+
subject.send(:connect)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when the connection does not succeed' do
|
51
|
+
|
52
|
+
before do
|
53
|
+
expect(PG).to receive(:connect).and_raise(PG::ConnectionBad, message)
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when the host name is invalid' do
|
57
|
+
# PG::ConnectionBad: could not translate host name "redshift.amazonaws.co" to address: nodename nor servname provided, or not known
|
58
|
+
let(:message) { 'could not translate host name "TEST_HOSTNAME" to address: nodename nor servname provided, or not known' }
|
59
|
+
it 'should be an error' do
|
60
|
+
expect { subject.send(:connect) }.to raise_error(FlareUp::HostUnknownOrInaccessibleError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when the connection times out' do
|
65
|
+
# PG::ConnectionBad: timeout expired
|
66
|
+
let(:message) { 'timeout expired' }
|
67
|
+
it 'should be an error' do
|
68
|
+
expect { subject.send(:connect) }.to raise_error(FlareUp::TimeoutError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the database does not exist' do
|
73
|
+
# PG::ConnectionBad: FATAL: database "de" does not exist
|
74
|
+
let(:message) { 'FATAL: database "TEST_DB_NAME" does not exist' }
|
75
|
+
it 'should be an error' do
|
76
|
+
expect { subject.send(:connect) }.to raise_error(FlareUp::NoDatabaseError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when authenication credentials are invalid' do
|
81
|
+
# PG::ConnectionBad: FATAL: password authentication failed for user "slif1"
|
82
|
+
let(:message) { 'password authentication failed for user "slif1"' }
|
83
|
+
it 'should be an error' do
|
84
|
+
expect { subject.send(:connect) }.to raise_error(FlareUp::AuthenticationError)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when the error is unknown' do
|
89
|
+
let(:message) { '_'}
|
90
|
+
it 'should be an error' do
|
91
|
+
expect { subject.send(:connect) }.to raise_error(FlareUp::UnknownError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#connection_parameters' do
|
100
|
+
|
101
|
+
it 'should return the required parameters' do
|
102
|
+
expect(subject.send(:connection_parameters)).to eq({
|
103
|
+
:host => 'TEST_HOST',
|
104
|
+
:port => 5439,
|
105
|
+
:dbname => 'TEST_DB_NAME',
|
106
|
+
:user => 'TEST_USER',
|
107
|
+
:password => 'TEST_PASSWORD',
|
108
|
+
:connect_timeout => 5,
|
109
|
+
})
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
describe FlareUp::CopyCommand do
|
2
|
+
|
3
|
+
subject do
|
4
|
+
FlareUp::CopyCommand.new('TEST_TABLE_NAME', 'TEST_DATA_SOURCE', 'TEST_ACCESS_KEY', 'TEST_SECRET_KEY')
|
5
|
+
end
|
6
|
+
|
7
|
+
its(:table_name) { should == 'TEST_TABLE_NAME' }
|
8
|
+
its(:data_source) { should == 'TEST_DATA_SOURCE' }
|
9
|
+
its(:aws_access_key_id) { should == 'TEST_ACCESS_KEY' }
|
10
|
+
its(:aws_secret_access_key) { should == 'TEST_SECRET_KEY' }
|
11
|
+
its(:columns) { should == [] }
|
12
|
+
its(:options) { should == '' }
|
13
|
+
|
14
|
+
describe '#get_command' do
|
15
|
+
context 'when no optional fields are provided' do
|
16
|
+
it 'should return a basic COPY command' do
|
17
|
+
expect(subject.get_command).to eq("COPY TEST_TABLE_NAME FROM 'TEST_DATA_SOURCE' CREDENTIALS 'aws_access_key_id=TEST_ACCESS_KEY;aws_secret_access_key=TEST_SECRET_KEY' ")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when column names are provided' do
|
22
|
+
before do
|
23
|
+
subject.columns = %w(column_name1 column_name2)
|
24
|
+
end
|
25
|
+
it 'should include the column names in the command' do
|
26
|
+
expect(subject.get_command).to start_with('COPY TEST_TABLE_NAME (column_name1, column_name2) FROM')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when options are provided' do
|
31
|
+
before do
|
32
|
+
subject.options = 'OPTION1 OPTION2'
|
33
|
+
end
|
34
|
+
it 'should include the options in the command' do
|
35
|
+
expect(subject.get_command).to end_with(' OPTION1 OPTION2')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#columns=' do
|
41
|
+
context 'when an array' do
|
42
|
+
it 'should assign the property' do
|
43
|
+
subject.columns = %w(column_name1 column_name2)
|
44
|
+
expect(subject.columns).to eq(%w(column_name1 column_name2))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when not an array' do
|
49
|
+
it 'should not assign the property and be an error' do
|
50
|
+
subject.columns = %w(column_name1)
|
51
|
+
expect {
|
52
|
+
subject.columns = '_'
|
53
|
+
}.to raise_error(ArgumentError)
|
54
|
+
expect(subject.columns).to eq(%w(column_name1))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#execute' do
|
60
|
+
|
61
|
+
let(:conn) { instance_double('FlareUp::Connection') }
|
62
|
+
|
63
|
+
context 'when successful' do
|
64
|
+
before do
|
65
|
+
expect(conn).to receive(:execute)
|
66
|
+
end
|
67
|
+
it 'should do something' do
|
68
|
+
expect(subject.execute(conn)).to eq([])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when unsuccessful' do
|
73
|
+
|
74
|
+
before do
|
75
|
+
expect(conn).to receive(:execute).and_raise(exception, message)
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when there was an internal error' do
|
79
|
+
|
80
|
+
let(:exception) { PG::InternalError }
|
81
|
+
|
82
|
+
context 'when there was an error loading' do
|
83
|
+
let(:message) { "Check 'stl_load_errors' system table for details" }
|
84
|
+
before do
|
85
|
+
allow(FlareUp::STLLoadErrorFetcher).to receive(:fetch_errors).and_return('FOO')
|
86
|
+
end
|
87
|
+
it 'should respond with a list of errors' do
|
88
|
+
expect(subject.execute(conn)).to eq('FOO')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when there was an error with the S3 prefix' do
|
93
|
+
let(:message) { "The specified S3 prefix 'test_filename.csv' does not exist" }
|
94
|
+
it 'should be an error' do
|
95
|
+
expect { subject.execute(conn) }.to raise_error(FlareUp::DataSourceError)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when the bucket is not in the same zone as the Redshift instance' do
|
100
|
+
let(:message) { 'The bucket you are attempting to access must be addressed using the specified endpoint' }
|
101
|
+
it 'should be an error' do
|
102
|
+
expect { subject.execute(conn) }.to raise_error(FlareUp::OtherZoneBucketError)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'when there was another kind of internal error' do
|
107
|
+
let(:message) { '_' }
|
108
|
+
it 'should respond with a list of errors' do
|
109
|
+
expect { subject.execute(conn) }.to raise_error(PG::InternalError, '_')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when there is a syntax error in the command' do
|
114
|
+
let(:message) { 'ERROR: syntax error at or near "lmlkmlk3" (PG::SyntaxError)' }
|
115
|
+
it 'should be error' do
|
116
|
+
expect { subject.execute(conn) }.to raise_error(FlareUp::SyntaxError, 'Syntax error in the COPY command: [at or near "lmlkmlk3"].')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'when there was another type of error' do
|
123
|
+
let(:exception) { PG::ConnectionBad }
|
124
|
+
let(:message) { '_' }
|
125
|
+
it 'should do something' do
|
126
|
+
expect { subject.execute(conn) }.to raise_error(PG::ConnectionBad, '_')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
describe FlareUp::STLLoadErrorFetcher do
|
2
|
+
|
3
|
+
describe '.fetch_errors' do
|
4
|
+
|
5
|
+
let(:connection) { instance_double('FlareUp::Connection') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
expect(connection).to receive(:execute).
|
9
|
+
with('SELECT * FROM stl_load_errors ORDER BY query DESC, line_number, position LIMIT 1').
|
10
|
+
and_return([
|
11
|
+
{
|
12
|
+
'err_reason' => 'TEST_REASON',
|
13
|
+
'raw_field_value' => 'TEST_RAW_FIELD_VALUE',
|
14
|
+
'raw_line' => 'TEST_RAW_LINE',
|
15
|
+
'col_length' => '1',
|
16
|
+
'type' => 'TEST_TYPE',
|
17
|
+
'colname' => 'TEST_COLNAME',
|
18
|
+
'filename' => 'TEST_FILENAME',
|
19
|
+
'position' => '2',
|
20
|
+
'line_number' => '3'
|
21
|
+
}
|
22
|
+
])
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return the load errors' do
|
26
|
+
expect(FlareUp::STLLoadErrorFetcher.fetch_errors(connection)).to eq(
|
27
|
+
[
|
28
|
+
FlareUp::STLLoadError.new(
|
29
|
+
'TEST_REASON',
|
30
|
+
'TEST_RAW_FIELD_VALUE',
|
31
|
+
'TEST_RAW_LINE',
|
32
|
+
1,
|
33
|
+
'TEST_TYPE',
|
34
|
+
'TEST_COLNAME',
|
35
|
+
'TEST_FILENAME',
|
36
|
+
2,
|
37
|
+
3
|
38
|
+
)
|
39
|
+
]
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
describe FlareUp::STLLoadError do
|
2
|
+
|
3
|
+
subject do
|
4
|
+
FlareUp::STLLoadError.new(
|
5
|
+
'TEST_REASON',
|
6
|
+
'TEST_RAW_FIELD_VALUE',
|
7
|
+
'TEST_RAW_LINE',
|
8
|
+
1,
|
9
|
+
'TEST_TYPE',
|
10
|
+
'TEST_COLNAME',
|
11
|
+
'TEST_FILENAME',
|
12
|
+
2,
|
13
|
+
3
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
its(:err_reason) { should == 'TEST_REASON' }
|
18
|
+
its(:raw_field_value) { should == 'TEST_RAW_FIELD_VALUE' }
|
19
|
+
its(:raw_line) { should == 'TEST_RAW_LINE' }
|
20
|
+
its(:col_length) { should == 1 }
|
21
|
+
its(:type) { should == 'TEST_TYPE' }
|
22
|
+
its(:colname) { should == 'TEST_COLNAME' }
|
23
|
+
its(:filename) { should == 'TEST_FILENAME' }
|
24
|
+
its(:position) { should == 2 }
|
25
|
+
its(:line_number) { should == 3 }
|
26
|
+
|
27
|
+
describe '.from_pg_results_row' do
|
28
|
+
let(:values) do
|
29
|
+
{
|
30
|
+
'err_reason' => 'TEST_REASON ',
|
31
|
+
'raw_field_value' => 'TEST_RAW_FIELD_VALUE ',
|
32
|
+
'raw_line' => 'TEST_RAW_LINE ',
|
33
|
+
'col_length' => '1 ',
|
34
|
+
'type' => 'TEST_TYPE ',
|
35
|
+
'colname' => 'TEST_COLNAME ',
|
36
|
+
'filename' => 'TEST_FILENAME ',
|
37
|
+
'position' => '2 ',
|
38
|
+
'line_number' => '3 '
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:load_error_from_hash) { FlareUp::STLLoadError.from_pg_results_row(values) }
|
43
|
+
|
44
|
+
it 'should be an STLLoadError' do
|
45
|
+
expect(load_error_from_hash).to be_a(FlareUp::STLLoadError)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should store the values properly' do
|
49
|
+
expect(load_error_from_hash.err_reason).to eq('TEST_REASON')
|
50
|
+
expect(load_error_from_hash.raw_field_value).to eq('TEST_RAW_FIELD_VALUE')
|
51
|
+
expect(load_error_from_hash.raw_line).to eq('TEST_RAW_LINE')
|
52
|
+
expect(load_error_from_hash.col_length).to eq(1)
|
53
|
+
expect(load_error_from_hash.type).to eq('TEST_TYPE')
|
54
|
+
expect(load_error_from_hash.colname).to eq('TEST_COLNAME')
|
55
|
+
expect(load_error_from_hash.filename).to eq('TEST_FILENAME')
|
56
|
+
expect(load_error_from_hash.position).to eq(2)
|
57
|
+
expect(load_error_from_hash.line_number).to eq(3)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|