flare-up 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|