flydata 0.8.9 → 0.8.9.11
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 +5 -5
- data/.gitsha +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +38 -27
- data/Rakefile +4 -1
- data/VERSION +1 -1
- data/circle.yml +1 -1
- data/fd-build +26 -0
- data/flydata-core/lib/flydata-core/errors.rb +3 -0
- data/flydata-core/lib/flydata-core/mysql/compatibility_checker.rb +39 -1
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +14 -4
- data/flydata-core/spec/mysql/compatibility_checker_spec.rb +140 -0
- data/flydata.gemspec +0 -0
- data/gemset.nix +580 -0
- data/lib/flydata/cli.rb +3 -0
- data/lib/flydata/error_reporting.rb +89 -0
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +2 -0
- data/lib/flydata/fluent-plugins/in_postgresql_query_based_flydata.rb +5 -1
- data/lib/flydata/query_based_sync/client.rb +6 -1
- data/lib/flydata/source_mysql/mysql_compatibility_check.rb +9 -1
- data/replication.nix +30 -0
- data/shell.nix +47 -0
- data/spec/flydata/error_reporting_spec.rb +107 -0
- data/spec/flydata/source_mysql/mysql_compatibility_check_spec.rb +38 -0
- data/spec/flydata/source_mysql/parser/dump_parser_spec.rb +3 -1
- data/spec/flydata/source_mysql/sync_generate_table_ddl_spec.rb +12 -0
- metadata +122 -100
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 35a3d0077661045cac6a3431b1e26370d9d4b3c3734ad13fd41ab3e06e99530e
|
|
4
|
+
data.tar.gz: 32e5f53766192e1a9ecb384176314095018ee5ee2c1b751ec140a479e8c578ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cd8938432ec340ae74f8f4968d4282c3e42532c54a61c2fa7aef43177d0d0a72847d3059e21a9c777d12ba2a3940a51c93505048c6ab00e5a53e1d4092fe646e
|
|
7
|
+
data.tar.gz: 280fda7d5b9cff89f079196d5ea86c35178afafc94bef9e3be48fb0cb4c0594a08201568d56eef7dea3ffcd1e9f6d48181986c71f276db0f3f602aa963afaddc
|
data/.gitsha
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d37dcb936ffe8940b3dd34695df8291b8ea92e5b
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.0-p648
|
data/Gemfile
CHANGED
|
@@ -18,7 +18,7 @@ gem "kodama", '~> 0.1', '>= 0.1.12'
|
|
|
18
18
|
gem "serverengine", '~> 1.5'
|
|
19
19
|
|
|
20
20
|
group :development do
|
|
21
|
-
gem "jeweler", '~>
|
|
21
|
+
gem "jeweler", '~> 2.0', '>= 2.0.1'
|
|
22
22
|
gem "rspec", '~> 3.0'
|
|
23
23
|
gem 'test-unit'
|
|
24
24
|
gem 'timecop', '~> 0.7', '>= 0.7.1'
|
|
@@ -31,4 +31,5 @@ group :development do
|
|
|
31
31
|
gem 'rake'
|
|
32
32
|
#gem 'ruby-oci8'
|
|
33
33
|
gem 'rake-compiler', '~> 0.9', '>= 0.9.5'
|
|
34
|
+
gem 'rollbar'
|
|
34
35
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -17,14 +17,17 @@ GEM
|
|
|
17
17
|
multi_json (~> 1.3)
|
|
18
18
|
thread_safe (~> 0.1)
|
|
19
19
|
tzinfo (~> 0.3.37)
|
|
20
|
-
addressable (2.
|
|
20
|
+
addressable (2.5.2)
|
|
21
|
+
public_suffix (>= 2.0.2, < 4.0)
|
|
21
22
|
arel (4.0.2)
|
|
22
23
|
builder (3.1.4)
|
|
23
24
|
coderay (1.1.0)
|
|
24
25
|
cool.io (1.4.1)
|
|
26
|
+
descendants_tracker (0.0.4)
|
|
27
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
25
28
|
diff-lcs (1.2.5)
|
|
26
|
-
faraday (0.
|
|
27
|
-
multipart-post (
|
|
29
|
+
faraday (0.9.2)
|
|
30
|
+
multipart-post (>= 1.2, < 3)
|
|
28
31
|
ffi (1.9.6)
|
|
29
32
|
fluent-plugin-mysql-binlog (0.0.2)
|
|
30
33
|
activesupport
|
|
@@ -37,48 +40,52 @@ GEM
|
|
|
37
40
|
msgpack (>= 0.4.4, < 0.6.0, != 0.5.3, != 0.5.2, != 0.5.1, != 0.5.0)
|
|
38
41
|
sigdump (~> 0.2.2)
|
|
39
42
|
yajl-ruby (~> 1.0)
|
|
40
|
-
git (1.
|
|
41
|
-
github_api (0.
|
|
42
|
-
addressable
|
|
43
|
-
|
|
43
|
+
git (1.5.0)
|
|
44
|
+
github_api (0.11.3)
|
|
45
|
+
addressable (~> 2.3)
|
|
46
|
+
descendants_tracker (~> 0.0.1)
|
|
47
|
+
faraday (~> 0.8, < 0.10)
|
|
44
48
|
hashie (>= 1.2)
|
|
45
|
-
multi_json (
|
|
46
|
-
nokogiri (~> 1.
|
|
49
|
+
multi_json (>= 1.7.5, < 2.0)
|
|
50
|
+
nokogiri (~> 1.6.0)
|
|
47
51
|
oauth2
|
|
48
|
-
hashie (3.
|
|
52
|
+
hashie (3.6.0)
|
|
49
53
|
highline (1.6.21)
|
|
50
54
|
http_parser.rb (0.6.0)
|
|
51
55
|
i18n (0.6.11)
|
|
52
56
|
io-console (0.4.6)
|
|
53
|
-
jeweler (1.
|
|
57
|
+
jeweler (2.1.2)
|
|
54
58
|
builder
|
|
55
|
-
bundler (
|
|
59
|
+
bundler (>= 1.0)
|
|
56
60
|
git (>= 1.2.5)
|
|
57
|
-
github_api (
|
|
61
|
+
github_api (~> 0.11.0)
|
|
58
62
|
highline (>= 1.6.15)
|
|
59
|
-
nokogiri (
|
|
63
|
+
nokogiri (>= 1.5.10)
|
|
60
64
|
rake
|
|
61
65
|
rdoc
|
|
66
|
+
semver
|
|
62
67
|
json (1.8.1)
|
|
63
|
-
jwt (1.
|
|
68
|
+
jwt (1.5.6)
|
|
64
69
|
kodama (0.1.12)
|
|
65
70
|
ruby-binlog (~> 1.0, >= 1.0.10)
|
|
66
71
|
method_source (0.8.2)
|
|
67
72
|
mime-types (2.3)
|
|
73
|
+
mini_portile2 (2.1.0)
|
|
68
74
|
minitest (4.7.5)
|
|
69
75
|
msgpack (0.5.8)
|
|
70
76
|
multi_json (1.10.1)
|
|
71
|
-
multi_xml (0.
|
|
72
|
-
multipart-post (
|
|
77
|
+
multi_xml (0.6.0)
|
|
78
|
+
multipart-post (2.0.0)
|
|
73
79
|
mysql2 (0.3.18)
|
|
74
80
|
netrc (0.7.7)
|
|
75
|
-
nokogiri (1.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
nokogiri (1.6.8.1)
|
|
82
|
+
mini_portile2 (~> 2.1.0)
|
|
83
|
+
oauth2 (1.4.1)
|
|
84
|
+
faraday (>= 0.8, < 0.16.0)
|
|
85
|
+
jwt (>= 1.0, < 3.0)
|
|
79
86
|
multi_json (~> 1.3)
|
|
80
87
|
multi_xml (~> 0.5)
|
|
81
|
-
rack (
|
|
88
|
+
rack (>= 1.2, < 3)
|
|
82
89
|
pg (0.18.4)
|
|
83
90
|
polyglot (0.3.5)
|
|
84
91
|
power_assert (1.0.1)
|
|
@@ -88,15 +95,17 @@ GEM
|
|
|
88
95
|
coderay (~> 1.1.0)
|
|
89
96
|
method_source (~> 0.8.1)
|
|
90
97
|
slop (~> 3.4)
|
|
91
|
-
|
|
98
|
+
public_suffix (2.0.5)
|
|
99
|
+
rack (1.6.11)
|
|
92
100
|
rake (10.3.2)
|
|
93
101
|
rake-compiler (0.9.5)
|
|
94
102
|
rake
|
|
95
|
-
rdoc (
|
|
96
|
-
json (~> 1.4)
|
|
103
|
+
rdoc (5.1.0)
|
|
97
104
|
rest-client (1.7.2)
|
|
98
105
|
mime-types (>= 1.16, < 3.0)
|
|
99
106
|
netrc (~> 0.7)
|
|
107
|
+
rollbar (2.18.0)
|
|
108
|
+
multi_json
|
|
100
109
|
rspec (3.0.0)
|
|
101
110
|
rspec-core (~> 3.0.0)
|
|
102
111
|
rspec-expectations (~> 3.0.0)
|
|
@@ -111,6 +120,7 @@ GEM
|
|
|
111
120
|
rspec-support (3.0.3)
|
|
112
121
|
ruby-binlog (1.0.10)
|
|
113
122
|
ruby-prof (0.15.1)
|
|
123
|
+
semver (1.0.1)
|
|
114
124
|
serverengine (1.5.10)
|
|
115
125
|
sigdump (~> 0.2.2)
|
|
116
126
|
sigdump (0.2.2)
|
|
@@ -139,7 +149,7 @@ DEPENDENCIES
|
|
|
139
149
|
highline (~> 1.6, >= 1.6.19)
|
|
140
150
|
i18n (~> 0.6, >= 0.6.5)
|
|
141
151
|
io-console (~> 0.4.6, >= 0.4.6)
|
|
142
|
-
jeweler (~>
|
|
152
|
+
jeweler (~> 2.0, >= 2.0.1)
|
|
143
153
|
json (~> 1.8, >= 1.8.0)
|
|
144
154
|
kodama (~> 0.1, >= 0.1.12)
|
|
145
155
|
mysql2 (~> 0.3, >= 0.3.17)
|
|
@@ -149,6 +159,7 @@ DEPENDENCIES
|
|
|
149
159
|
rake
|
|
150
160
|
rake-compiler (~> 0.9, >= 0.9.5)
|
|
151
161
|
rest-client (~> 1.6, >= 1.6.7)
|
|
162
|
+
rollbar
|
|
152
163
|
rspec (~> 3.0)
|
|
153
164
|
ruby-prof (~> 0.15, >= 0.15.1)
|
|
154
165
|
serverengine (~> 1.5)
|
|
@@ -160,4 +171,4 @@ DEPENDENCIES
|
|
|
160
171
|
treetop (~> 1.5, >= 1.5.3)
|
|
161
172
|
|
|
162
173
|
BUNDLED WITH
|
|
163
|
-
1.
|
|
174
|
+
1.17.1
|
data/Rakefile
CHANGED
|
@@ -21,7 +21,10 @@ Jeweler::Tasks.new do |gem|
|
|
|
21
21
|
gem.description = %Q{FlyData Agent}
|
|
22
22
|
gem.email = "sysadmin@flydata.com"
|
|
23
23
|
gem.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS", "Chie Inada"]
|
|
24
|
-
|
|
24
|
+
|
|
25
|
+
sha=`git rev-parse --verify HEAD`
|
|
26
|
+
File.open(File.join(File.dirname(__FILE__), ".gitsha"), "w") { |f| f << sha }
|
|
27
|
+
gem.files << ".gitsha"
|
|
25
28
|
end
|
|
26
29
|
Jeweler::RubygemsDotOrgTasks.new
|
|
27
30
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.8.9
|
|
1
|
+
0.8.9.11
|
data/circle.yml
CHANGED
|
@@ -6,7 +6,7 @@ dependencies:
|
|
|
6
6
|
pre:
|
|
7
7
|
- sudo dpkg -l |grep libboost|grep 1.48|awk '{print $2}'|xargs sudo apt-get purge -y
|
|
8
8
|
- sudo apt-get autoremove
|
|
9
|
-
- sudo apt-get update
|
|
9
|
+
- sudo apt-get update || true
|
|
10
10
|
- sudo apt-get install -y libboost-system1.54.0
|
|
11
11
|
- sudo apt-get install -y libboost-system1.54-dev
|
|
12
12
|
- sudo apt-get install -y libboost-thread1.54.0
|
data/fd-build
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#! /usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
set -o pipefail
|
|
5
|
+
|
|
6
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
7
|
+
while [ -h "$SOURCE" ]; do
|
|
8
|
+
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
9
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
10
|
+
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
11
|
+
done
|
|
12
|
+
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
13
|
+
|
|
14
|
+
FD_BUILD=$(which fd-build)
|
|
15
|
+
source $(dirname $FD_BUILD)/../lib/fd-scripts/utils.sh
|
|
16
|
+
|
|
17
|
+
cd $DIR
|
|
18
|
+
|
|
19
|
+
# bundle to install gems.
|
|
20
|
+
nix-shell --run "bundle install --path vendor/bundle"
|
|
21
|
+
nix-shell --run "bundle exec rake compile"
|
|
22
|
+
|
|
23
|
+
# Bundix updates the gemset.nix file so that nix-build can operate using fixed builds.
|
|
24
|
+
$(nix-build '<nixpkgs>' -A fd-bundix --no-out-link --show-trace)/bin/bundix --ruby=fd-ruby
|
|
25
|
+
|
|
26
|
+
echo -e "${BLUE}Done!${RESTORE} Everything should be up to date!"
|
|
@@ -61,6 +61,8 @@ module FlydataCore
|
|
|
61
61
|
def rds?(hostname = @option[:host])
|
|
62
62
|
return true if hostname.match(/rds.amazonaws.com$/) != nil
|
|
63
63
|
|
|
64
|
+
ExecutePrivilegeChecker.new(@option).do_check
|
|
65
|
+
|
|
64
66
|
# To distinguish RDS customers using Secure Tunnel
|
|
65
67
|
begin
|
|
66
68
|
exec_query(RDS_CHECK_QUERY)
|
|
@@ -358,7 +360,7 @@ EOT
|
|
|
358
360
|
param_hash = convert_result_to_hash(result)
|
|
359
361
|
|
|
360
362
|
if param_hash["expire_logs_days"].to_s != '0' &&
|
|
361
|
-
param_hash["expire_logs_days"].to_i
|
|
363
|
+
param_hash["expire_logs_days"].to_i < EXPIRE_LOGS_DAYS_LIMIT
|
|
362
364
|
raise FlydataCore::MysqlCompatibilityError,
|
|
363
365
|
"Binary log retention is too short\n " +
|
|
364
366
|
" We recommend the system variable '@@expire_logs_days' to be either set to 0 or at least #{EXPIRE_LOGS_DAYS_LIMIT} day(s)"
|
|
@@ -389,6 +391,12 @@ EOT
|
|
|
389
391
|
"call mysql.rds_show_configuration;"
|
|
390
392
|
end
|
|
391
393
|
|
|
394
|
+
def do_check(option = @option, &block)
|
|
395
|
+
ExecutePrivilegeChecker.new(option).do_check
|
|
396
|
+
|
|
397
|
+
super(option, &block)
|
|
398
|
+
end
|
|
399
|
+
|
|
392
400
|
def check_result(result, option = @option)
|
|
393
401
|
if result.first["name"] == "binlog retention hours"
|
|
394
402
|
if result.first["value"].nil? ||
|
|
@@ -403,5 +411,35 @@ EOT
|
|
|
403
411
|
end
|
|
404
412
|
end
|
|
405
413
|
end
|
|
414
|
+
|
|
415
|
+
class ExecutePrivilegeChecker < MysqlCompatibilityChecker
|
|
416
|
+
def create_query(option = @option)
|
|
417
|
+
"SHOW GRANTS FOR '#{option[:username]}'"
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def check_result(result, option = @option)
|
|
421
|
+
valid_privileges = ['EXECUTE', 'ALL PRIVILEGES']
|
|
422
|
+
|
|
423
|
+
get_grant_regex = /GRANT (?<privs>.*) ON (`)?(?<db_name>[^`]*)(`)?\.\* TO '#{option[:username]}/
|
|
424
|
+
|
|
425
|
+
result.each do |res|
|
|
426
|
+
# SHOW GRANTS should only return one column
|
|
427
|
+
res_value = res.values.first
|
|
428
|
+
matched_values = res_value.match(get_grant_regex)
|
|
429
|
+
|
|
430
|
+
next unless matched_values
|
|
431
|
+
matched_privileges = matched_values['privs'].split(', ')
|
|
432
|
+
|
|
433
|
+
next unless ['*', option[:database]].include?(matched_values['db_name'])
|
|
434
|
+
next if (matched_privileges & valid_privileges).empty? # array intersection
|
|
435
|
+
|
|
436
|
+
return true
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
error_text = "The user '#{option[:username]}' does not have the EXECUTE permission"
|
|
440
|
+
|
|
441
|
+
raise MissingExecutePermissionMysqlCompatibilityError, error_text
|
|
442
|
+
end
|
|
443
|
+
end
|
|
406
444
|
end
|
|
407
445
|
end
|
|
@@ -301,7 +301,12 @@ EOS
|
|
|
301
301
|
"'#{self.parse_timestamp(remove_single_quote(default_value))}'"
|
|
302
302
|
end
|
|
303
303
|
when 'date'
|
|
304
|
-
|
|
304
|
+
val = self.parse_date(remove_single_quote(default_value))
|
|
305
|
+
if val =~ /SYSDATE/
|
|
306
|
+
"#{val}"
|
|
307
|
+
else
|
|
308
|
+
"'#{val}'"
|
|
309
|
+
end
|
|
305
310
|
when 'boolean'
|
|
306
311
|
default_value.to_s.upcase
|
|
307
312
|
else
|
|
@@ -517,9 +522,14 @@ EOS
|
|
|
517
522
|
|
|
518
523
|
def self.parse_date(value)
|
|
519
524
|
return nil if value.nil?
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
525
|
+
case value.to_s.upcase
|
|
526
|
+
when /^CURRENT_TIMESTAMP\b/, /^CURRENT_TIME\b/, /^NOW\(\)/
|
|
527
|
+
'SYSDATE'
|
|
528
|
+
else
|
|
529
|
+
value_str = value.to_s
|
|
530
|
+
dt = Date.parse(convert_date(value_str))
|
|
531
|
+
dt.strftime('%Y-%m-%d')
|
|
532
|
+
end
|
|
523
533
|
rescue ArgumentError => ae
|
|
524
534
|
# '0000-00-00' is valid for mysql date column
|
|
525
535
|
return '0001-01-01' if value_str == '0000-00-00'
|
|
@@ -52,6 +52,21 @@ module FlydataCore
|
|
|
52
52
|
describe '#rds?' do
|
|
53
53
|
subject { subject_object.rds? }
|
|
54
54
|
|
|
55
|
+
let(:execute_privilege_checker) { ExecutePrivilegeChecker.new }
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
allow(ExecutePrivilegeChecker).to receive(:new).and_return(execute_privilege_checker)
|
|
59
|
+
allow(execute_privilege_checker).to receive(:do_check).and_return(nil)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'calls ExecutePrivilegeChecker' do
|
|
63
|
+
allow(subject_object).to receive(:exec_query).with(MysqlCompatibilityChecker::RDS_CHECK_QUERY).and_return(nil)
|
|
64
|
+
|
|
65
|
+
expect(execute_privilege_checker).to receive(:do_check)
|
|
66
|
+
|
|
67
|
+
subject
|
|
68
|
+
end
|
|
69
|
+
|
|
55
70
|
context 'When called for non-rds host' do
|
|
56
71
|
let(:mysql2_error_msg) { "PROCEDURE mysql.rds_show_configuration does not exist" }
|
|
57
72
|
before do
|
|
@@ -107,6 +122,18 @@ module FlydataCore
|
|
|
107
122
|
expect { subject }.to raise_error(Mysql2::Error, mysql2_error_msg)
|
|
108
123
|
end
|
|
109
124
|
end
|
|
125
|
+
|
|
126
|
+
context 'when FlydataCore::MissingExecutePermissionMysqlCompatibilityError raised' do
|
|
127
|
+
let(:error_msg) { "The user 'sync' does not have the EXECUTE permission" }
|
|
128
|
+
|
|
129
|
+
before do
|
|
130
|
+
allow(ExecutePrivilegeChecker).to receive(:new).and_return(execute_privilege_checker)
|
|
131
|
+
allow(execute_privilege_checker).to receive(:do_check).and_raise(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, error_msg)
|
|
132
|
+
end
|
|
133
|
+
it do
|
|
134
|
+
expect { subject }.to raise_error(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, error_msg)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
110
137
|
end
|
|
111
138
|
end
|
|
112
139
|
|
|
@@ -339,6 +366,119 @@ EOT
|
|
|
339
366
|
end
|
|
340
367
|
end
|
|
341
368
|
end
|
|
369
|
+
|
|
370
|
+
describe ExecutePrivilegeChecker do
|
|
371
|
+
let(:subject_object) { described_class.new(option.merge(username: 'sync')) }
|
|
372
|
+
|
|
373
|
+
describe '#check_result' do
|
|
374
|
+
subject { subject_object.check_result(result) }
|
|
375
|
+
|
|
376
|
+
context 'when ALL PRIVILEGES is granted' do
|
|
377
|
+
let(:result) do
|
|
378
|
+
[{"Grants for sync@%" => "GRANT ALL PRIVILEGES ON *.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it { expect{subject}.to_not raise_error }
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context 'when EXECUTE privilege is granted in all databases' do
|
|
385
|
+
let(:result) do
|
|
386
|
+
[{"Grants for sync@%" => "GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, EXECUTE ON *.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
it { expect{subject}.to_not raise_error }
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
context 'when EXECUTE privilege is granted in the test_db database' do
|
|
393
|
+
let(:result) do
|
|
394
|
+
[{"Grants for sync@%" => "GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, EXECUTE ON test_db.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
it { expect{subject}.to_not raise_error }
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
context 'when ALL PRIVILEGES is granted in a different database' do
|
|
401
|
+
let(:result) do
|
|
402
|
+
[{"Grants for sync@%" => "GRANT ALL PRIVILEGES ON different_db.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it { expect{subject}.to raise_error(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, "The user 'sync' does not have the EXECUTE permission") }
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
context 'when EXECUTE privilege is granted in a different database' do
|
|
409
|
+
let(:result) do
|
|
410
|
+
[{"Grants for sync@%" => "GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, EXECUTE ON different_db.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
it { expect{subject}.to raise_error(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, "The user 'sync' does not have the EXECUTE permission") }
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
context 'when EXECUTE privilege is not granted' do
|
|
417
|
+
let(:result) do
|
|
418
|
+
[{"Grants for sync@%" => "GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'sync'@'%' IDENTIFIED BY PASSWORD 'password'"}]
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it { expect{subject}.to raise_error(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, "The user 'sync' does not have the EXECUTE permission") }
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
describe RdsRetentionChecker do
|
|
427
|
+
let(:options) { option.merge(username: 'sync') }
|
|
428
|
+
let(:mysql_options) { options.merge(port: nil, password: nil, ssl_ca: nil, ssl_cipher: nil) }
|
|
429
|
+
let(:subject_object) { described_class.new(options) }
|
|
430
|
+
|
|
431
|
+
describe '#do_check' do
|
|
432
|
+
subject { subject_object.do_check }
|
|
433
|
+
|
|
434
|
+
let(:execute_privilege_checker) { ExecutePrivilegeChecker.new(options) }
|
|
435
|
+
|
|
436
|
+
before do
|
|
437
|
+
@rds_show_configuration_result = [{name: 'binlog retention hours', value: '144'}]
|
|
438
|
+
|
|
439
|
+
allow(subject_object).to receive(:create_query).and_return('call mysql.rds_show_configuration;')
|
|
440
|
+
allow(subject_object).to receive(:exec_query).with('call mysql.rds_show_configuration;').and_return(@rds_show_configuration_result)
|
|
441
|
+
allow(subject_object).to receive(:check_result).with(@rds_show_configuration_result, mysql_options).and_return(nil)
|
|
442
|
+
|
|
443
|
+
allow(ExecutePrivilegeChecker).to receive(:new).and_return(execute_privilege_checker)
|
|
444
|
+
allow(execute_privilege_checker).to receive(:do_check).and_return(nil)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it { expect{subject}.to_not raise_error }
|
|
448
|
+
|
|
449
|
+
it 'calls ExecutePrivilegeChecker' do
|
|
450
|
+
expect(execute_privilege_checker).to receive(:do_check)
|
|
451
|
+
|
|
452
|
+
subject
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
context 'when database user has EXECUTE privilege' do
|
|
456
|
+
it { expect{subject}.to_not raise_error }
|
|
457
|
+
|
|
458
|
+
context 'when binlog is too low' do
|
|
459
|
+
before do
|
|
460
|
+
@error_message = "Binary log retention is too short\n" +
|
|
461
|
+
" We recommend setting RDS binlog retention " +
|
|
462
|
+
"to be at least 96 hours. To do this, " +
|
|
463
|
+
"run this on your RDS MySQL database:\n" +
|
|
464
|
+
" $> call mysql.rds_set_configuration('binlog retention hours', 96);"
|
|
465
|
+
|
|
466
|
+
allow(subject_object).to receive(:check_result).with(@rds_show_configuration_result, mysql_options).and_raise(FlydataCore::MysqlCompatibilityError, @error_message)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it { expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, @error_message) }
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
context 'when database user does not have EXECUTE privilege' do
|
|
474
|
+
before do
|
|
475
|
+
allow(execute_privilege_checker).to receive(:do_check).and_raise(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, "The user 'sync' does not have the EXECUTE permission")
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it { expect{subject}.to raise_error(FlydataCore::MissingExecutePermissionMysqlCompatibilityError, "The user 'sync' does not have the EXECUTE permission") }
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
end
|
|
342
482
|
end
|
|
343
483
|
|
|
344
484
|
describe BinlogParameterChecker do
|