flydata 0.3.13 → 0.3.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -3
- data/Gemfile.lock +6 -7
- data/VERSION +1 -1
- data/flydata-core/lib/flydata-core/config/user_maintenance.rb +19 -11
- data/flydata-core/lib/flydata-core/fluent/config_helper.rb +21 -0
- data/flydata-core/spec/config/user_maintenance_spec.rb +10 -0
- data/flydata-core/spec/fluent/config_helper_spec.rb +78 -0
- data/flydata.gemspec +12 -13
- data/lib/flydata/command/base.rb +12 -0
- data/lib/flydata/command/status.rb +1 -0
- data/lib/flydata/command/sync.rb +15 -1
- data/lib/flydata/compatibility_check.rb +20 -1
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +22 -4
- data/lib/flydata/fluent-plugins/mysql/table_meta.rb +8 -3
- data/lib/flydata/fluent-plugins/preference.rb +1 -0
- data/lib/flydata/parser/mysql/dump_parser.rb +2 -2
- data/lib/flydata/parser/mysql/mysql_alter_table.treetop +7 -0
- data/lib/flydata/sync_file_manager.rb +15 -0
- data/lib/flydata/util/mysql_util.rb +8 -2
- data/spec/flydata/command/base_spec.rb +9 -2
- data/spec/flydata/command/status_spec.rb +1 -0
- data/spec/flydata/compatibility_check_spec.rb +44 -1
- data/spec/flydata/fluent-plugins/mysql/table_meta_spec.rb +2 -3
- data/spec/flydata/parser/mysql/alter_table_parser_spec.rb +11 -0
- data/spec/flydata/sync_file_manager_spec.rb +30 -0
- data/spec/flydata/util/mysql_util_spec.rb +31 -5
- metadata +9 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de14c5ba0b4b0b3c1b98e93f9e41c59a32db18fd
|
4
|
+
data.tar.gz: 685e70c882291fe387d7aaf14657a879b8c1d73e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c735cbf41f4e9448175bb38c5dac9b5e5365e7a8f9710f86e7399feab2eecd5e018165f2224e8749e8c7169941b33bc1a01e122d7eb1d510056010508c0a793a
|
7
|
+
data.tar.gz: efc559f6b9536c45078f63b1416fc5da759bbd99249176b51dc15e7ec4016a5dfb5942262db0e4a87d13ba843d90ae00a91a9b731d670881c5467b5b642fac87
|
data/Gemfile
CHANGED
@@ -7,14 +7,13 @@ gem "activesupport", '~> 4.0.0'
|
|
7
7
|
gem "json", '~> 1.8', '>= 1.8.0'
|
8
8
|
gem "highline", '~> 1.6', '>= 1.6.19'
|
9
9
|
gem "fluentd", "0.10.46"
|
10
|
-
gem "ruby-binlog", '~> 1.0', '>= 1.0.2'
|
11
10
|
gem "fluent-plugin-mysql-binlog", '~> 0.0', '>= 0.0.2'
|
12
|
-
gem "mysql2", '~> 0.3', '>= 0.3.
|
11
|
+
gem "mysql2", '~> 0.3', '>= 0.3.17'
|
13
12
|
gem "slop", '~> 3.4', '>= 3.4.6'
|
14
13
|
gem "treetop", '~> 1.5', '>= 1.5.3'
|
15
14
|
gem "sys-filesystem", '~> 1.1', '>= 1.1.3'
|
16
15
|
gem "io-console", '~> 0.4.2', '>= 0.4.2'
|
17
|
-
gem "kodama", '~> 0.1.2', '>= 0.1.
|
16
|
+
gem "kodama", '~> 0.1.2', '>= 0.1.3'
|
18
17
|
|
19
18
|
group :development do
|
20
19
|
gem "jeweler", '~> 1.8', '>= 1.8.8'
|
data/Gemfile.lock
CHANGED
@@ -61,8 +61,8 @@ GEM
|
|
61
61
|
rdoc
|
62
62
|
json (1.8.1)
|
63
63
|
jwt (1.0.0)
|
64
|
-
kodama (0.1.
|
65
|
-
ruby-binlog (>= 0.
|
64
|
+
kodama (0.1.3)
|
65
|
+
ruby-binlog (~> 1.0, >= 1.0.4)
|
66
66
|
method_source (0.8.2)
|
67
67
|
mime-types (2.3)
|
68
68
|
minitest (4.7.5)
|
@@ -70,7 +70,7 @@ GEM
|
|
70
70
|
multi_json (1.10.1)
|
71
71
|
multi_xml (0.5.5)
|
72
72
|
multipart-post (1.2.0)
|
73
|
-
mysql2 (0.3.
|
73
|
+
mysql2 (0.3.18)
|
74
74
|
netrc (0.7.7)
|
75
75
|
nokogiri (1.5.10)
|
76
76
|
oauth2 (1.0.0)
|
@@ -105,7 +105,7 @@ GEM
|
|
105
105
|
rspec-mocks (3.0.3)
|
106
106
|
rspec-support (~> 3.0.0)
|
107
107
|
rspec-support (3.0.3)
|
108
|
-
ruby-binlog (1.0.
|
108
|
+
ruby-binlog (1.0.4)
|
109
109
|
ruby-prof (0.15.1)
|
110
110
|
sigdump (0.2.2)
|
111
111
|
slop (3.6.0)
|
@@ -133,13 +133,12 @@ DEPENDENCIES
|
|
133
133
|
io-console (~> 0.4.2, >= 0.4.2)
|
134
134
|
jeweler (~> 1.8, >= 1.8.8)
|
135
135
|
json (~> 1.8, >= 1.8.0)
|
136
|
-
kodama (~> 0.1.2, >= 0.1.
|
137
|
-
mysql2 (~> 0.3, >= 0.3.
|
136
|
+
kodama (~> 0.1.2, >= 0.1.3)
|
137
|
+
mysql2 (~> 0.3, >= 0.3.17)
|
138
138
|
protected_attributes (~> 1.0, >= 1.0.8)
|
139
139
|
pry
|
140
140
|
rest-client (~> 1.6, >= 1.6.7)
|
141
141
|
rspec (~> 3.0)
|
142
|
-
ruby-binlog (~> 1.0, >= 1.0.2)
|
143
142
|
ruby-prof (~> 0.15, >= 0.15.1)
|
144
143
|
slop (~> 3.4, >= 3.4.6)
|
145
144
|
sqlite3 (~> 1.3, >= 1.3.9)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.14
|
@@ -25,6 +25,9 @@ module FlydataCore
|
|
25
25
|
# - discard_[data-port-id]_[data-entry-id]_[(schema-name.)table-name]
|
26
26
|
#
|
27
27
|
class UserMaintenance
|
28
|
+
|
29
|
+
SUPPORTED_MODES = [:maintenance, :discard]
|
30
|
+
|
28
31
|
def initialize(base_dir_path)
|
29
32
|
@base_dir_path = base_dir_path
|
30
33
|
end
|
@@ -48,6 +51,18 @@ module FlydataCore
|
|
48
51
|
mode_file_path(:discard, params)
|
49
52
|
end
|
50
53
|
|
54
|
+
# /mnt/flydata/system/user_maintenance/[dp-id]/[mode]_[data-port-id]_[data-entry-id]_[table-name]
|
55
|
+
def mode_file_path(mode, params)
|
56
|
+
validate_mode(mode)
|
57
|
+
validate_params(params)
|
58
|
+
File.join(dp_mode_dir_path(params), mode_file_name(mode, params))
|
59
|
+
end
|
60
|
+
|
61
|
+
# /mnt/flydata/system/user_maintenance/[dp-id]
|
62
|
+
def dp_mode_dir_path(params)
|
63
|
+
File.join(@base_dir_path, params[:data_port_id].to_s)
|
64
|
+
end
|
65
|
+
|
51
66
|
# For fluentd plugin and copy handler
|
52
67
|
|
53
68
|
def maintenance_mode?(params)
|
@@ -70,6 +85,10 @@ module FlydataCore
|
|
70
85
|
|
71
86
|
private
|
72
87
|
|
88
|
+
def validate_mode(mode)
|
89
|
+
raise ArgumentError.new("Unsupported mode:#{mode}") unless SUPPORTED_MODES.include?(mode)
|
90
|
+
end
|
91
|
+
|
73
92
|
def validate_params(params)
|
74
93
|
raise ArgumentError.new("params must be hash") unless params.kind_of?(Hash)
|
75
94
|
raise ArgumentError.new("params must have 'data_port_id' key") unless params[:data_port_id]
|
@@ -90,17 +109,6 @@ module FlydataCore
|
|
90
109
|
Dir.glob("#{de_mode_file_path}_*").any?{|fp| File.join(File.dirname(fp), File.basename(fp).downcase) == tn_mode_file_path}
|
91
110
|
end
|
92
111
|
|
93
|
-
# /mnt/flydata/system/user_maintenance/[dp-id]/[mode]_[data-port-id]_[data-entry-id]_[table-name]
|
94
|
-
def mode_file_path(mode, params)
|
95
|
-
validate_params(params)
|
96
|
-
File.join(dp_mode_dir_path(mode, params), mode_file_name(mode, params))
|
97
|
-
end
|
98
|
-
|
99
|
-
# /mnt/flydata/system/user_maintenance/[dp-id]
|
100
|
-
def dp_mode_dir_path(mode, params)
|
101
|
-
File.join(@base_dir_path, params[:data_port_id].to_s)
|
102
|
-
end
|
103
|
-
|
104
112
|
# [mode]_[data-port-id]_[data-entry-id]_[table-name]
|
105
113
|
def mode_file_name(mode, params)
|
106
114
|
return nil unless params[:data_port_id]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module FlydataCore
|
2
|
+
module Fluent
|
3
|
+
class ConfigHelper
|
4
|
+
ESCAPE_REGEXP = /\r|\n|\t|"|\\|/
|
5
|
+
ESCAPE_HASH_TABLE = {"\r" => "\\r", "\n" => "\\n", "\t" => "\\t", '"' => '\\"', "\\" => "\\\\"}
|
6
|
+
|
7
|
+
UNESCAPE_REGEXP = /\\r|\\n|\\t|\\"|\\\\|/
|
8
|
+
UNESCAPE_HASH_TABLE = {"\\r" => "\r", "\\n" => "\n", "\\t" => "\t", '\\"' => '"', "\\\\" => "\\"}
|
9
|
+
|
10
|
+
def self.escape_conf(str)
|
11
|
+
return "" if str.nil? || str.empty?
|
12
|
+
str.gsub(ESCAPE_REGEXP, ESCAPE_HASH_TABLE)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.unescape_conf(str)
|
16
|
+
return "" if str.nil? || str.empty?
|
17
|
+
str.gsub(UNESCAPE_REGEXP, UNESCAPE_HASH_TABLE)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -68,6 +68,16 @@ module FlydataCore::Config
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
describe '#mode_file_path' do
|
72
|
+
let(:mode) { nil }
|
73
|
+
subject { user_maintenance.mode_file_path(mode, params) }
|
74
|
+
|
75
|
+
context 'with invalid mode' do
|
76
|
+
let(:mode) { :unknown }
|
77
|
+
it { expect{ subject }.to raise_error(ArgumentError, "Unsupported mode:unknown") }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
71
81
|
describe '#maintenance_mode?' do
|
72
82
|
subject { user_maintenance.maintenance_mode?(params) }
|
73
83
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'flydata-core/fluent/config_helper'
|
3
|
+
|
4
|
+
module FlydataCore::Fluent
|
5
|
+
describe ConfigHelper do
|
6
|
+
describe '.escape_conf' do
|
7
|
+
|
8
|
+
let(:input) { "" }
|
9
|
+
let(:output) { "" }
|
10
|
+
subject { ConfigHelper.escape_conf(input) }
|
11
|
+
|
12
|
+
shared_examples 'escape conf expectedly' do
|
13
|
+
it { is_expected.to eq(output) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when input contains escape characters' do
|
17
|
+
let(:input) { %Q|aa\nbb\r\ncc\tdd"ee\\ff| }
|
18
|
+
let(:output) { %Q|aa\\nbb\\r\\ncc\\tdd\\"ee\\\\ff| }
|
19
|
+
|
20
|
+
it_behaves_like 'escape conf expectedly'
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when input does not contain escape characters' do
|
24
|
+
let(:input) { %Q|aabbccddeeff| }
|
25
|
+
let(:output) { %Q|aabbccddeeff| }
|
26
|
+
|
27
|
+
it_behaves_like 'escape conf expectedly'
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when input is nil' do
|
31
|
+
let(:input) { nil }
|
32
|
+
it { is_expected.to eq("") }
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when input is empty' do
|
36
|
+
let(:input) { "" }
|
37
|
+
it { is_expected.to eq("") }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.unescape_conf' do
|
42
|
+
|
43
|
+
let(:input) { "" }
|
44
|
+
let(:output) { "" }
|
45
|
+
subject { ConfigHelper.unescape_conf(input) }
|
46
|
+
|
47
|
+
shared_examples 'unescape conf expectedly' do
|
48
|
+
it { is_expected.to eq(output) }
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when input contains escaped characters' do
|
52
|
+
let(:input) { %Q|aa\\nbb\\r\\ncc\\tdd\\"ee\\\\ff| }
|
53
|
+
let(:output) { %Q|aa\nbb\r\ncc\tdd"ee\\ff| }
|
54
|
+
|
55
|
+
it_behaves_like 'unescape conf expectedly'
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when input does not contain escape characters' do
|
59
|
+
let(:input) { %Q|aabbccddeeff| }
|
60
|
+
let(:output) { %Q|aabbccddeeff| }
|
61
|
+
|
62
|
+
it_behaves_like 'unescape conf expectedly'
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when input is nil' do
|
66
|
+
let(:input) { nil }
|
67
|
+
it { is_expected.to eq("") }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when input is empty' do
|
71
|
+
let(:input) { "" }
|
72
|
+
it { is_expected.to eq("") }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
data/flydata.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: flydata 0.3.
|
5
|
+
# stub: flydata 0.3.14 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "flydata"
|
9
|
-
s.version = "0.3.
|
9
|
+
s.version = "0.3.14"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
|
14
|
-
s.date = "2015-04-
|
14
|
+
s.date = "2015-04-19"
|
15
15
|
s.description = "FlyData Agent"
|
16
16
|
s.email = "sysadmin@flydata.com"
|
17
17
|
s.executables = ["fdmysqldump", "flydata", "serverinfo"]
|
@@ -45,12 +45,14 @@ Gem::Specification.new do |s|
|
|
45
45
|
"flydata-core/lib/flydata-core/core_ext/object/prepend.rb",
|
46
46
|
"flydata-core/lib/flydata-core/errors.rb",
|
47
47
|
"flydata-core/lib/flydata-core/fluent-plugins/multi_buffer.rb",
|
48
|
+
"flydata-core/lib/flydata-core/fluent/config_helper.rb",
|
48
49
|
"flydata-core/lib/flydata-core/logger.rb",
|
49
50
|
"flydata-core/lib/flydata-core/table_def.rb",
|
50
51
|
"flydata-core/lib/flydata-core/table_def/mysql_table_def.rb",
|
51
52
|
"flydata-core/lib/flydata-core/table_def/redshift_table_def.rb",
|
52
53
|
"flydata-core/lib/flydata-core/thread_context.rb",
|
53
54
|
"flydata-core/spec/config/user_maintenance_spec.rb",
|
55
|
+
"flydata-core/spec/fluent/config_helper_spec.rb",
|
54
56
|
"flydata-core/spec/logger_spec.rb",
|
55
57
|
"flydata-core/spec/spec_helper.rb",
|
56
58
|
"flydata-core/spec/table_def/mysql_table_def_spec.rb",
|
@@ -172,7 +174,7 @@ Gem::Specification.new do |s|
|
|
172
174
|
]
|
173
175
|
s.homepage = "http://flydata.com/"
|
174
176
|
s.licenses = ["All right reserved."]
|
175
|
-
s.rubygems_version = "2.4.
|
177
|
+
s.rubygems_version = "2.4.6"
|
176
178
|
s.summary = "FlyData Agent"
|
177
179
|
|
178
180
|
if s.respond_to? :specification_version then
|
@@ -185,14 +187,13 @@ Gem::Specification.new do |s|
|
|
185
187
|
s.add_runtime_dependency(%q<json>, [">= 1.8.0", "~> 1.8"])
|
186
188
|
s.add_runtime_dependency(%q<highline>, [">= 1.6.19", "~> 1.6"])
|
187
189
|
s.add_runtime_dependency(%q<fluentd>, ["= 0.10.46"])
|
188
|
-
s.add_runtime_dependency(%q<ruby-binlog>, [">= 1.0.2", "~> 1.0"])
|
189
190
|
s.add_runtime_dependency(%q<fluent-plugin-mysql-binlog>, [">= 0.0.2", "~> 0.0"])
|
190
|
-
s.add_runtime_dependency(%q<mysql2>, [">= 0.3.
|
191
|
+
s.add_runtime_dependency(%q<mysql2>, [">= 0.3.17", "~> 0.3"])
|
191
192
|
s.add_runtime_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
|
192
193
|
s.add_runtime_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
|
193
194
|
s.add_runtime_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
|
194
195
|
s.add_runtime_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
|
195
|
-
s.add_runtime_dependency(%q<kodama>, [">= 0.1.
|
196
|
+
s.add_runtime_dependency(%q<kodama>, [">= 0.1.3", "~> 0.1.2"])
|
196
197
|
s.add_development_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
|
197
198
|
s.add_development_dependency(%q<rspec>, ["~> 3.0"])
|
198
199
|
s.add_development_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
|
@@ -209,14 +210,13 @@ Gem::Specification.new do |s|
|
|
209
210
|
s.add_dependency(%q<json>, [">= 1.8.0", "~> 1.8"])
|
210
211
|
s.add_dependency(%q<highline>, [">= 1.6.19", "~> 1.6"])
|
211
212
|
s.add_dependency(%q<fluentd>, ["= 0.10.46"])
|
212
|
-
s.add_dependency(%q<ruby-binlog>, [">= 1.0.2", "~> 1.0"])
|
213
213
|
s.add_dependency(%q<fluent-plugin-mysql-binlog>, [">= 0.0.2", "~> 0.0"])
|
214
|
-
s.add_dependency(%q<mysql2>, [">= 0.3.
|
214
|
+
s.add_dependency(%q<mysql2>, [">= 0.3.17", "~> 0.3"])
|
215
215
|
s.add_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
|
216
216
|
s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
|
217
217
|
s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
|
218
218
|
s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
|
219
|
-
s.add_dependency(%q<kodama>, [">= 0.1.
|
219
|
+
s.add_dependency(%q<kodama>, [">= 0.1.3", "~> 0.1.2"])
|
220
220
|
s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
|
221
221
|
s.add_dependency(%q<rspec>, ["~> 3.0"])
|
222
222
|
s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
|
@@ -234,14 +234,13 @@ Gem::Specification.new do |s|
|
|
234
234
|
s.add_dependency(%q<json>, [">= 1.8.0", "~> 1.8"])
|
235
235
|
s.add_dependency(%q<highline>, [">= 1.6.19", "~> 1.6"])
|
236
236
|
s.add_dependency(%q<fluentd>, ["= 0.10.46"])
|
237
|
-
s.add_dependency(%q<ruby-binlog>, [">= 1.0.2", "~> 1.0"])
|
238
237
|
s.add_dependency(%q<fluent-plugin-mysql-binlog>, [">= 0.0.2", "~> 0.0"])
|
239
|
-
s.add_dependency(%q<mysql2>, [">= 0.3.
|
238
|
+
s.add_dependency(%q<mysql2>, [">= 0.3.17", "~> 0.3"])
|
240
239
|
s.add_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
|
241
240
|
s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
|
242
241
|
s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
|
243
242
|
s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
|
244
|
-
s.add_dependency(%q<kodama>, [">= 0.1.
|
243
|
+
s.add_dependency(%q<kodama>, [">= 0.1.3", "~> 0.1.2"])
|
245
244
|
s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
|
246
245
|
s.add_dependency(%q<rspec>, ["~> 3.0"])
|
247
246
|
s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
|
data/lib/flydata/command/base.rb
CHANGED
@@ -30,6 +30,18 @@ module Flydata
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
def show_purpose_name
|
35
|
+
de = data_entry
|
36
|
+
log_info_stdout("Your current application name is '#{de['purpose_name']}'")
|
37
|
+
end
|
38
|
+
|
39
|
+
def data_entry
|
40
|
+
@de ||= retrieve_data_entries.first
|
41
|
+
raise "There are no data entries." unless @de
|
42
|
+
@de
|
43
|
+
end
|
44
|
+
|
33
45
|
def register_crontab
|
34
46
|
data_entries = retrieve_data_entries
|
35
47
|
if data_entries.any?{|e| e['log_deletion']}
|
data/lib/flydata/command/sync.rb
CHANGED
@@ -137,6 +137,7 @@ EOS
|
|
137
137
|
# Command: flydata sync:reset
|
138
138
|
# - Entry method
|
139
139
|
def reset(*tables)
|
140
|
+
show_purpose_name
|
140
141
|
# Flush client buffer
|
141
142
|
msg = tables.empty? ? '' : " for these tables : #{tables.join(" ")}"
|
142
143
|
return unless ask_yes_no("This resets the current sync#{msg}. Are you sure?")
|
@@ -285,9 +286,10 @@ EOS
|
|
285
286
|
de = data_entry
|
286
287
|
|
287
288
|
unless @new_tables.empty?
|
289
|
+
show_purpose_name
|
288
290
|
unsynced_table_message = "We've noticed that these tables have not been synced yet: #{@new_tables.join(", ")}\n"
|
289
291
|
unless @ddl_tables.empty?
|
290
|
-
unsynced_table_message <<
|
292
|
+
unsynced_table_message <<
|
291
293
|
" WARNING: We've noticed that at least one of these tables have not had their DDL generated yet.\n" +
|
292
294
|
" We recommend you run our 'flydata sync:generate_table_ddl > create_table.sql'\n" +
|
293
295
|
" to generate SQL to run on Redshift to create the correct tables\n" +
|
@@ -385,6 +387,10 @@ FlyData Sync will start synchronizing the following database tables
|
|
385
387
|
database: #{de['mysql_data_entry_preference']['database']}
|
386
388
|
tables: #{tables.join(", ")}#{data_servers}
|
387
389
|
EOM
|
390
|
+
|
391
|
+
confirmation_text << <<-EOM if de['mysql_data_entry_preference']['ssl_ca']
|
392
|
+
ssl: Yes
|
393
|
+
EOM
|
388
394
|
confirmation_text << <<-EOM if file_dump
|
389
395
|
dump file: #{fp}
|
390
396
|
|
@@ -884,11 +890,19 @@ Thank you for using FlyData!
|
|
884
890
|
case de['type']
|
885
891
|
when 'RedshiftMysqlDataEntry'
|
886
892
|
mp = de['mysql_data_entry_preference']
|
893
|
+
|
887
894
|
if mp['tables_append_only']
|
888
895
|
mp['tables'] = (mp['tables'].split(",") + mp['tables_append_only'].split(",")).uniq
|
889
896
|
else
|
890
897
|
mp['tables'] = mp['tables'].split(",").uniq
|
891
898
|
end
|
899
|
+
|
900
|
+
unless mp['ssl_ca_content'].to_s.strip.empty?
|
901
|
+
sync_fm = create_sync_file_manager(de)
|
902
|
+
sync_fm.save_ssl_ca(mp['ssl_ca_content'])
|
903
|
+
mp['ssl_ca'] = sync_fm.ssl_ca_path
|
904
|
+
mp['sslca'] = mp['ssl_ca']
|
905
|
+
end
|
892
906
|
else
|
893
907
|
raise SyncDataEntryError, "No supported data entry. Only mysql-redshift sync is supported."
|
894
908
|
end
|
@@ -78,13 +78,16 @@ module Flydata
|
|
78
78
|
|
79
79
|
SELECT_QUERY_TMPLT = "SELECT %s"
|
80
80
|
BINLOG_RETENTION_HOURS = 24
|
81
|
+
SELECT_TABLE_INFO_TMPLT = "SELECT table_name, table_type, engine FROM information_schema.tables WHERE table_schema = '%s' and table_name in(%s)"
|
81
82
|
|
82
83
|
#def initialize(de_hash, dump_dir=nil)
|
83
84
|
def initialize(dp_hash, de_hash, options={})
|
84
85
|
super
|
85
|
-
@db_opts = [:host, :port, :username, :password, :database].inject({}) {|h, sym| h[sym] = de_hash[sym.to_s]; h}
|
86
|
+
@db_opts = [:host, :port, :username, :password, :database, :ssl_ca].inject({}) {|h, sym| h[sym] = de_hash[sym.to_s]; h}
|
87
|
+
@db_opts[:sslca] = @db_opts[:ssl_ca] # for mysql2 gem
|
86
88
|
@dump_dir = options[:dump_dir] || nil
|
87
89
|
@backup_dir = options[:backup_dir] || nil
|
90
|
+
@tables = de_hash['tables']
|
88
91
|
end
|
89
92
|
|
90
93
|
def print_errors
|
@@ -202,6 +205,22 @@ module Flydata
|
|
202
205
|
end
|
203
206
|
end
|
204
207
|
|
208
|
+
# If table_type='VIEW' or engine='MEMORY', raise error.
|
209
|
+
def check_mysql_table_types
|
210
|
+
return if @tables.empty?
|
211
|
+
client = Mysql2::Client.new(@db_opts)
|
212
|
+
sel_query = SELECT_TABLE_INFO_TMPLT % [client.escape(@db_opts[:database]), @tables.collect{|t| "'#{client.escape(t)}'"}.join(", ")]
|
213
|
+
begin
|
214
|
+
invalid_tables = []
|
215
|
+
client.query(sel_query).each do |r|
|
216
|
+
invalid_tables.push(r['table_name']) if r['table_type'] == 'VIEW' || r['engine'] == 'MEMORY'
|
217
|
+
end
|
218
|
+
raise MysqlCompatibilityError, "FlyData does not support VIEW and MEMORY ENGINE table. Remove following tables from data entry: #{invalid_tables.join(", ")}" unless invalid_tables.empty?
|
219
|
+
ensure
|
220
|
+
client.close
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
205
224
|
def run_mysql_retention_check(mysql_client)
|
206
225
|
expire_logs_days_limit = BINLOG_RETENTION_HOURS / 24
|
207
226
|
sel_query = SELECT_QUERY_TMPLT % '@@expire_logs_days'
|
@@ -16,6 +16,7 @@ require 'flydata/fluent-plugins/mysql/binlog_record_dispatcher'
|
|
16
16
|
require 'flydata/fluent-plugins/mysql/context'
|
17
17
|
require 'flydata/fluent-plugins/idle_event_detector'
|
18
18
|
require 'flydata/fluent-plugins/mysql/table_meta'
|
19
|
+
require 'flydata-core/fluent/config_helper'
|
19
20
|
|
20
21
|
#Monkey-patch fluentd class (EngineClass) to support shutdown for input plugin.
|
21
22
|
#This will be called when USR1 signal is received
|
@@ -53,6 +54,7 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
53
54
|
config_param :initial_idle_interval, :integer, :default => 30
|
54
55
|
config_param :continuous_idle_interval, :integer, :default => 600
|
55
56
|
config_param :check_interval, :integer, :default => 5
|
57
|
+
config_param :ssl_ca_content, :string, :default => ''
|
56
58
|
|
57
59
|
def configure(conf)
|
58
60
|
super
|
@@ -65,9 +67,19 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
65
67
|
@sent_position_file_path = @sync_fm.sent_binlog_path(@position_file)
|
66
68
|
|
67
69
|
load_custom_conf
|
70
|
+
|
71
|
+
# SSL configuration
|
72
|
+
unless @ssl_ca_content.to_s.strip.empty?
|
73
|
+
@ssl_ca_path = @sync_fm.ssl_ca_path(@position_file)
|
74
|
+
@sync_fm.save_ssl_ca(FlydataCore::Fluent::ConfigHelper.unescape_conf(@ssl_ca_content), @ssl_ca_path)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Db access opts
|
78
|
+
db_opts = { host: @host, port: @port, username: @username, password: @password, database: @database, ssl_ca: @ssl_ca_path }
|
79
|
+
|
68
80
|
$log.info "mysql host:\"#{@host}\" port:\"#{@port}\" username:\"#{@username}\" database:\"#{@database}\" tables:\"#{@tables}\" tables_append_only:\"#{tables_append_only}\""
|
69
81
|
$log.info "mysql client version: #{`mysql -V`}"
|
70
|
-
server_version = `echo 'select version();' | #{Flydata::Util::MysqlUtil.generate_mysql_cmd(
|
82
|
+
server_version = `echo 'select version();' | #{Flydata::Util::MysqlUtil.generate_mysql_cmd(db_opts)} 2>/dev/null`
|
71
83
|
$log.info "mysql server version: #{server_version}"
|
72
84
|
|
73
85
|
@tables = @tables.split(/,\s*/)
|
@@ -77,19 +89,20 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
77
89
|
@omit_events[table] = [:delete, :truncate_table]
|
78
90
|
end
|
79
91
|
|
80
|
-
#Remove tables that do not have pos files
|
92
|
+
# Remove tables that do not have pos files
|
81
93
|
new_tables = @sync_fm.get_new_table_list(@tables, "pos")
|
82
94
|
@tables -= new_tables
|
83
95
|
$log.info "Not watching these tables: #{new_tables.join(", ")}"
|
84
96
|
|
85
|
-
table_meta = Mysql::TableMeta.new(
|
86
|
-
mysql_url: mysql_url, database: @database, tables: @tables)
|
97
|
+
table_meta = Mysql::TableMeta.new(db_opts.merge(tables: @tables))
|
87
98
|
|
88
99
|
table_revs = tables.inject({}) do |h, table_name|
|
89
100
|
h[table_name] = @sync_fm.table_rev(table_name)
|
90
101
|
h
|
91
102
|
end
|
92
103
|
|
104
|
+
|
105
|
+
# Set context
|
93
106
|
@context = Mysql::Context.new(
|
94
107
|
database: @database, tables: @tables,
|
95
108
|
tag: @tag, sync_fm: @sync_fm, omit_events: @omit_events,
|
@@ -134,6 +147,11 @@ EOS
|
|
134
147
|
@context.table_meta.update
|
135
148
|
start_kodama(mysql_url) do |c|
|
136
149
|
c.binlog_position_file = @position_file
|
150
|
+
if @ssl_ca_path.to_s != '' && c.respond_to?(:ssl_ca=)
|
151
|
+
$log.info "SSL is enabled. (ssl_ca: #{@ssl_ca_path})"
|
152
|
+
c.ssl_ca = @ssl_ca_path
|
153
|
+
end
|
154
|
+
|
137
155
|
if c.respond_to?(:sent_binlog_position_file=)
|
138
156
|
$log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
|
139
157
|
c.sent_binlog_position_file = @sent_position_file_path
|
@@ -3,9 +3,11 @@ require 'mysql2'
|
|
3
3
|
module Mysql
|
4
4
|
class TableMeta
|
5
5
|
MANDATORY_OPTS = [
|
6
|
-
:
|
6
|
+
:host, :port, :username, :password,
|
7
|
+
:database, :tables,
|
7
8
|
]
|
8
9
|
OPTIONAL_OPTS = [
|
10
|
+
:ssl_ca
|
9
11
|
]
|
10
12
|
|
11
13
|
GET_TABLE_META_SQL = <<EOT
|
@@ -24,14 +26,17 @@ EOT
|
|
24
26
|
def initialize(opts)
|
25
27
|
missing_opts = MANDATORY_OPTS - opts.keys
|
26
28
|
raise "Mandatory option(s) are missing: #{missing_opts.join(', ')}" unless (missing_opts.empty?)
|
27
|
-
|
29
|
+
|
30
|
+
@db_opts = [:host, :port, :username, :password, :database, :ssl_ca].inject({}) {|h, sym| h[sym] = opts[sym]; h}
|
31
|
+
@db_opts[:sslca] = @db_opts[:ssl_ca] # for mysql2 gem
|
32
|
+
|
28
33
|
@database = opts[:database]
|
29
34
|
@tables = opts[:tables]
|
30
35
|
@table_meta = Hash.new{|h, k| h[k] = {}}
|
31
36
|
end
|
32
37
|
|
33
38
|
def update
|
34
|
-
conn = Mysql2::Client.new(@
|
39
|
+
conn = Mysql2::Client.new(@db_opts)
|
35
40
|
sql = GET_TABLE_META_SQL % {
|
36
41
|
database: @database, tables: @tables.collect{|t| "'#{t}'"}.join(',') }
|
37
42
|
columns = conn.query(sql)
|
@@ -7,7 +7,7 @@ module Flydata
|
|
7
7
|
|
8
8
|
module MysqlAccessible
|
9
9
|
def mysql_conf(conf)
|
10
|
-
@mysql_conf = [:host, :port, :username, :password, :database].inject({}) {|h, sym| h[sym] = conf[sym.to_s]; h}
|
10
|
+
@mysql_conf = [:host, :port, :username, :password, :database, :ssl_ca, :sslca].inject({}) {|h, sym| h[sym] = conf[sym.to_s]; h}
|
11
11
|
end
|
12
12
|
|
13
13
|
def mysql_cli(conf = nil)
|
@@ -42,7 +42,7 @@ module Flydata
|
|
42
42
|
class MysqlDumpGenerator
|
43
43
|
def initialize(conf)
|
44
44
|
@conf = conf
|
45
|
-
@db_opts = [:host, :port, :username, :password, :database].inject({}) {|h, sym| h[sym] = conf[sym.to_s]; h}
|
45
|
+
@db_opts = [:host, :port, :username, :password, :database, :ssl_ca, :sslca].inject({}) {|h, sym| h[sym] = conf[sym.to_s]; h}
|
46
46
|
end
|
47
47
|
|
48
48
|
def dump(file_path)
|
@@ -1062,6 +1062,13 @@ grammar MysqlAlterTable
|
|
1062
1062
|
}
|
1063
1063
|
end
|
1064
1064
|
}
|
1065
|
+
/ auto_increment_opt opt_equal nsp ulong_num {
|
1066
|
+
def action
|
1067
|
+
{ action: :auto_increment,
|
1068
|
+
support_level: :nonbreaking
|
1069
|
+
}
|
1070
|
+
end
|
1071
|
+
}
|
1065
1072
|
#TODO - There are other rules which need to be implemented when required
|
1066
1073
|
end
|
1067
1074
|
|
@@ -105,6 +105,21 @@ module Flydata
|
|
105
105
|
"#{master_binlog_path[0..-5]}.sent.pos"
|
106
106
|
end
|
107
107
|
|
108
|
+
# ssl_ca file path
|
109
|
+
def ssl_ca_path(master_binlog_path = binlog_path)
|
110
|
+
unless master_binlog_path && master_binlog_path.end_with?('binlog.pos')
|
111
|
+
raise ArgumentError.new("Invalid binlog path. binlog path needs to end with 'binlog.pos'")
|
112
|
+
end
|
113
|
+
# <data-entry-name>.ssl_ca.pem
|
114
|
+
"#{master_binlog_path[0..-12]}.ssl_ca.pem"
|
115
|
+
end
|
116
|
+
|
117
|
+
def save_ssl_ca(ssl_ca_content, path = ssl_ca_path)
|
118
|
+
File.open(path, 'w') do |f|
|
119
|
+
f.write(ssl_ca_content)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
108
123
|
# table files
|
109
124
|
def reset_table_position_files(tables)
|
110
125
|
tables.each do |table_name|
|
@@ -12,6 +12,7 @@ module Flydata
|
|
12
12
|
# - password
|
13
13
|
# - database
|
14
14
|
# - tables # array
|
15
|
+
# - ssl_ca
|
15
16
|
# - custom_option # string
|
16
17
|
def self.generate_mysql_cmd(option)
|
17
18
|
raise ArgumentError.new("option must be hash.") unless option.kind_of?(Hash)
|
@@ -21,13 +22,18 @@ module Flydata
|
|
21
22
|
port = option[:port] ? "-P #{option[:port]}" : nil
|
22
23
|
username = option[:username] ? "-u#{option[:username]}" : nil
|
23
24
|
password = if !(option[:password].to_s.empty?)
|
24
|
-
"-p\"#{option[:password].gsub('`', '\\\`')}\""
|
25
|
+
"-p\"#{option[:password].gsub('$','\\$').gsub('"','\\"').gsub('`', '\\\`')}\""
|
25
26
|
else
|
26
27
|
nil
|
27
28
|
end
|
28
29
|
database = option[:database]
|
29
30
|
tables = option[:tables] ? option[:tables].join(' ') : nil
|
30
|
-
|
31
|
+
ssl_ca = option[:ssl_ca] ? option[:ssl_ca] : nil
|
32
|
+
|
33
|
+
default_option = option[:no_default_option] ? "" : DEFAULT_MYSQL_CMD_OPTION
|
34
|
+
default_option += " --ssl-ca=#{ssl_ca}" if ssl_ca
|
35
|
+
default_option = nil if default_option == ''
|
36
|
+
|
31
37
|
custom_option = option[:custom_option]
|
32
38
|
|
33
39
|
[command, host, port, username, password, default_option,
|
@@ -7,13 +7,15 @@ module Command
|
|
7
7
|
describe Base do
|
8
8
|
subject { described_class.new }
|
9
9
|
let(:data_entries) {
|
10
|
-
[{"id"=>4, "data_port_id"=>1, "name"=>"flydata_sync_mysql_2", "log_path"=>nil, "created_at"=>"2015-03-02T03:06:25.000Z", "updated_at"=>"2015-03-02T03:08:02.000Z", "log_deletion"=>nil, "display_name"=>"synctest", "heroku_resource_id"=>nil, "heroku_log_type"=>nil, "log_file_type"=>nil, "log_file_delimiter"=>nil, "enabled"=>true, "type"=>"RedshiftMysqlDataEntry", "tag_name"=>"flydata.c5c0eb3d_dp1.flydata_sync_mysql_2", "tag_name_dev"=>"flydata.c5c0eb3d_dp1.flydata_sync_mysql_2.dev", "data_port_key"=>"c5c0eb3d", "schema_name"=>"", "table_name"=>"", "redshift_schema_name"=>"", "redshift_table_name"=>"", "mysql_data_entry_preference"=>{"host"=>"ubertas.flydata.co", "port"=>3306, "username"=>"mak", "password"=>password, "database"=>"mak_development", "tables"=>"items,orders", "tables_append_only"=>""}}]
|
10
|
+
[{"id"=>4, "data_port_id"=>1, "name"=>"flydata_sync_mysql_2", "log_path"=>nil, "created_at"=>"2015-03-02T03:06:25.000Z", "updated_at"=>"2015-03-02T03:08:02.000Z", "log_deletion"=>nil, "display_name"=>"synctest", "heroku_resource_id"=>nil, "heroku_log_type"=>nil, "log_file_type"=>nil, "log_file_delimiter"=>nil, "enabled"=>true, "type"=>"RedshiftMysqlDataEntry", "tag_name"=>"flydata.c5c0eb3d_dp1.flydata_sync_mysql_2", "tag_name_dev"=>"flydata.c5c0eb3d_dp1.flydata_sync_mysql_2.dev", "data_port_key"=>"c5c0eb3d", "purpose_name" => "Test app", "schema_name"=>"", "table_name"=>"", "redshift_schema_name"=>"", "redshift_table_name"=>"", "mysql_data_entry_preference"=>{"host"=>"ubertas.flydata.co", "port"=>3306, "username"=>"mak", "password"=>password, "database"=>"mak_development", "tables"=>"items,orders", "tables_append_only"=>""}}]
|
11
11
|
}
|
12
12
|
let(:flydata) { double('flydata') }
|
13
13
|
let(:path) { '/data_entries' }
|
14
14
|
let(:response_body) { data_entries }
|
15
15
|
let(:response) { double('response') }
|
16
16
|
let(:response_code) { 200 }
|
17
|
+
let(:password) { '' }
|
18
|
+
|
17
19
|
before do
|
18
20
|
allow(response).to receive(:code).and_return(response_code)
|
19
21
|
allow(flydata).to receive(:get).with(path).and_return(response_body)
|
@@ -37,8 +39,13 @@ describe Base do
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
describe "#show_purpose_name" do
|
43
|
+
it "calls log_info_stdout with appropriate message" do
|
44
|
+
expect(subject).to receive(:log_info_stdout).with("Your current application name is 'Test app'")
|
45
|
+
subject.show_purpose_name
|
46
|
+
end
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
end
|
43
51
|
end
|
44
|
-
|
@@ -138,6 +138,49 @@ module Flydata
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
141
|
-
end
|
142
141
|
|
142
|
+
describe "#check_mysql_table_types" do
|
143
|
+
let(:test_data_entry) do
|
144
|
+
{ "host" => "test",
|
145
|
+
"port" => 1234,
|
146
|
+
"username" => "test",
|
147
|
+
"password" => "password",
|
148
|
+
"database" => "test_db",
|
149
|
+
"tables"=>["normal_table", "engine_table", "view_table"] }
|
150
|
+
end
|
151
|
+
let(:normal_table) { {"table_name"=>"normal_table", "table_type"=>"BASE TABLE", "engine"=>"InnoDB"} }
|
152
|
+
let(:engine_table) { {"table_name"=>"engine_table", "table_type"=>"BASE TABLE", "engine"=>"MEMORY"} }
|
153
|
+
let(:view) { {"table_name"=>"view_table", "table_type"=>"VIEW", "engine"=>nil} }
|
154
|
+
let(:client) { double('client') }
|
155
|
+
let(:subject_object) { MysqlCompatibilityCheck.new(:default_data_port,test_data_entry, {}) }
|
156
|
+
let(:error) { Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError }
|
157
|
+
let(:base_error_msg) { "FlyData does not support VIEW and MEMORY ENGINE table. Remove following tables from data entry: %s" }
|
158
|
+
subject { subject_object.check_mysql_table_types }
|
159
|
+
before do
|
160
|
+
allow(Mysql2::Client).to receive(:new).and_return(client)
|
161
|
+
allow(client).to receive(:query).and_return(table_list)
|
162
|
+
allow(client).to receive(:escape).and_return("aaa")
|
163
|
+
allow(client).to receive(:close)
|
164
|
+
end
|
165
|
+
context "where data entry has VIEW and MEMORY engine table" do
|
166
|
+
let(:error_msg) { base_error_msg % engine_table['table_name'] + ', ' + view['table_name'] }
|
167
|
+
let(:table_list) { [ engine_table, view ] }
|
168
|
+
it { expect{subject}.to raise_error(error, /#{error_msg}/) }
|
169
|
+
end
|
170
|
+
context "where data entry has MEMORY engine table" do
|
171
|
+
let(:error_msg) { base_error_msg % engine_table['table_name'] }
|
172
|
+
let(:table_list) { [ engine_table ] }
|
173
|
+
it { expect{subject}.to raise_error(error, /#{error_msg}/) }
|
174
|
+
end
|
175
|
+
context "where data entry has the VIEW" do
|
176
|
+
let(:error_msg) { base_error_msg % view['table_name'] }
|
177
|
+
let(:table_list) { [ view ] }
|
178
|
+
it { expect{subject}.to raise_error(error, /#{error_msg}/) }
|
179
|
+
end
|
180
|
+
context "where data entry does not have either VIEW and ENGINE table" do
|
181
|
+
let(:table_list) { [ normal_table ] }
|
182
|
+
it { expect{subject}.to_not raise_error }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
143
186
|
end
|
@@ -3,13 +3,12 @@ require 'flydata/fluent-plugins/mysql/table_meta'
|
|
3
3
|
|
4
4
|
module Mysql
|
5
5
|
describe TableMeta do
|
6
|
-
let(:
|
6
|
+
let(:db_opts) { { host: 'test-host', port: 3306, username: 'test-user', password: 'test-pswd', database: 'test-db' } }
|
7
7
|
let(:database) { 'test-db' }
|
8
8
|
let(:tables) { %w(a_table b_table c_table) }
|
9
9
|
|
10
10
|
let(:conn) { double('conn') }
|
11
|
-
let(:table_meta) { TableMeta.new(
|
12
|
-
mysql_url: mysql_url, database: database, tables: tables) }
|
11
|
+
let(:table_meta) { TableMeta.new(db_opts.merge(database: database, tables: tables)) }
|
13
12
|
|
14
13
|
before do
|
15
14
|
allow(conn).to receive(:close)
|
@@ -1365,6 +1365,17 @@ describe 'MysqlAlterTableParser' do
|
|
1365
1365
|
let(:alter_table_action) { "engine#{equal} #{storage_engine}"}
|
1366
1366
|
it_behaves_like "test optional equal", "test storage engines", "a parser parsing a nonbreaking query"
|
1367
1367
|
end
|
1368
|
+
context "set auto increment" do
|
1369
|
+
let(:action) { :auto_increment }
|
1370
|
+
context "single digit number" do
|
1371
|
+
let(:alter_table_action) { "auto_increment#{equal} 1"}
|
1372
|
+
it_behaves_like "test optional equal", "a parser parsing a nonbreaking query"
|
1373
|
+
end
|
1374
|
+
context "multi digit number" do
|
1375
|
+
let(:alter_table_action) { "AUTO_INCREMENT#{equal} 1234"}
|
1376
|
+
it_behaves_like "test optional equal", "a parser parsing a nonbreaking query"
|
1377
|
+
end
|
1378
|
+
end
|
1368
1379
|
end
|
1369
1380
|
context "force" do
|
1370
1381
|
let(:alter_table_action) { "force" }
|
@@ -194,6 +194,36 @@ module Flydata
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
+
describe '#ssl_ca_path' do
|
198
|
+
context 'with no args' do
|
199
|
+
subject { default_sfm.ssl_ca_path }
|
200
|
+
it { is_expected.to eq("#{FLYDATA_HOME}/flydata_sync_mysql.ssl_ca.pem") }
|
201
|
+
end
|
202
|
+
context 'with invalid args' do
|
203
|
+
subject { default_sfm.ssl_ca_path('/home/ec2-user/.flydata/flydata_sync.pos') }
|
204
|
+
it { expect{subject}.to raise_error(ArgumentError) }
|
205
|
+
end
|
206
|
+
context 'with valid args' do
|
207
|
+
subject { default_sfm.ssl_ca_path('/home/ec2-user/.flydata/flydata_sync.binlog.pos') }
|
208
|
+
it { is_expected.to eq('/home/ec2-user/.flydata/flydata_sync.ssl_ca.pem') }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe '#save_ssl_ca_path' do
|
213
|
+
let(:ssl_ca_path) { default_sfm.ssl_ca_path }
|
214
|
+
let(:ssl_ca_content) { 'aaaaabbbbbccccc' }
|
215
|
+
subject { default_sfm.save_ssl_ca(ssl_ca_content) }
|
216
|
+
|
217
|
+
after do
|
218
|
+
File.delete(ssl_ca_path)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'write a ssl_ca_content to ssl_ca_path' do
|
222
|
+
subject
|
223
|
+
expect(IO.read(ssl_ca_path)).to eq(ssl_ca_content)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
197
227
|
describe '#increment_and_save_table_position' do
|
198
228
|
let(:test_table) { 'test_table' }
|
199
229
|
before do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'flydata/util/mysql_util'
|
2
3
|
|
3
4
|
module Flydata
|
4
5
|
module Util
|
@@ -13,6 +14,7 @@ module Flydata
|
|
13
14
|
database: 'testdb',
|
14
15
|
} }
|
15
16
|
let(:option) { default_option }
|
17
|
+
let(:cmd_pswd_check) { 'mysqldump -h test-host -P 3306 -utestuser -p%s --default-character-set=utf8 --protocol=tcp testdb' }
|
16
18
|
|
17
19
|
describe '.generate_mysql_cmd' do
|
18
20
|
subject { described_class.generate_mysql_cmd(option) }
|
@@ -50,11 +52,29 @@ module Flydata
|
|
50
52
|
) }
|
51
53
|
end
|
52
54
|
|
53
|
-
context 'when password is empty' do
|
55
|
+
context 'when password is not empty' do
|
54
56
|
before { option[:password] = "abc`def" }
|
55
|
-
it { is_expected.to eq(
|
56
|
-
|
57
|
-
|
57
|
+
it { is_expected.to eq(cmd_pswd_check % '"abc\\`def"' ) }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when password includes double quate' do
|
61
|
+
before { option[:password] = "abc\"def" }
|
62
|
+
it { is_expected.to eq(cmd_pswd_check % '"abc\\"def"') }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when password includes dollars sign' do
|
66
|
+
before { option[:password] = "abc$def" }
|
67
|
+
it { is_expected.to eq(cmd_pswd_check % '"abc\\$def"' ) }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when password includes multiple special characters' do
|
71
|
+
before { option[:password] = "ab\"\"c$$def" }
|
72
|
+
it { is_expected.to eq(cmd_pswd_check % '"ab\\"\\"c\\$\\$def"' ) }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when password does not includes special characters' do
|
76
|
+
before { option[:password] = "abcdef" }
|
77
|
+
it { is_expected.to eq(cmd_pswd_check % '"abcdef"' ) }
|
58
78
|
end
|
59
79
|
|
60
80
|
context 'when tables are specified' do
|
@@ -64,6 +84,13 @@ module Flydata
|
|
64
84
|
) }
|
65
85
|
end
|
66
86
|
|
87
|
+
context 'when ssl_ca is specified' do
|
88
|
+
before { option[:ssl_ca] = 'mysql_sync.ssl_ca.pem' }
|
89
|
+
it { is_expected.to eq(
|
90
|
+
'mysqldump -h test-host -P 3306 -utestuser -p"testpassword" --default-character-set=utf8 --protocol=tcp --ssl-ca=mysql_sync.ssl_ca.pem testdb'
|
91
|
+
) }
|
92
|
+
end
|
93
|
+
|
67
94
|
context 'when no_default_option is turned on' do
|
68
95
|
before { option[:no_default_option] = true }
|
69
96
|
it { is_expected.to eq(
|
@@ -71,7 +98,6 @@ module Flydata
|
|
71
98
|
) }
|
72
99
|
end
|
73
100
|
|
74
|
-
|
75
101
|
context 'with options for mysql_protocol_tcp_compat' do
|
76
102
|
before {
|
77
103
|
option[:command] = 'mysql'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flydata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Fujikawa
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2015-04-
|
15
|
+
date: 2015-04-19 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rest-client
|
@@ -122,26 +122,6 @@ dependencies:
|
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 0.10.46
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: ruby-binlog
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - '>='
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: 1.0.2
|
132
|
-
- - ~>
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
version: '1.0'
|
135
|
-
type: :runtime
|
136
|
-
prerelease: false
|
137
|
-
version_requirements: !ruby/object:Gem::Requirement
|
138
|
-
requirements:
|
139
|
-
- - '>='
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: 1.0.2
|
142
|
-
- - ~>
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
version: '1.0'
|
145
125
|
- !ruby/object:Gem::Dependency
|
146
126
|
name: fluent-plugin-mysql-binlog
|
147
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,7 +148,7 @@ dependencies:
|
|
168
148
|
requirements:
|
169
149
|
- - '>='
|
170
150
|
- !ruby/object:Gem::Version
|
171
|
-
version: 0.3.
|
151
|
+
version: 0.3.17
|
172
152
|
- - ~>
|
173
153
|
- !ruby/object:Gem::Version
|
174
154
|
version: '0.3'
|
@@ -178,7 +158,7 @@ dependencies:
|
|
178
158
|
requirements:
|
179
159
|
- - '>='
|
180
160
|
- !ruby/object:Gem::Version
|
181
|
-
version: 0.3.
|
161
|
+
version: 0.3.17
|
182
162
|
- - ~>
|
183
163
|
- !ruby/object:Gem::Version
|
184
164
|
version: '0.3'
|
@@ -268,7 +248,7 @@ dependencies:
|
|
268
248
|
requirements:
|
269
249
|
- - '>='
|
270
250
|
- !ruby/object:Gem::Version
|
271
|
-
version: 0.1.
|
251
|
+
version: 0.1.3
|
272
252
|
- - ~>
|
273
253
|
- !ruby/object:Gem::Version
|
274
254
|
version: 0.1.2
|
@@ -278,7 +258,7 @@ dependencies:
|
|
278
258
|
requirements:
|
279
259
|
- - '>='
|
280
260
|
- !ruby/object:Gem::Version
|
281
|
-
version: 0.1.
|
261
|
+
version: 0.1.3
|
282
262
|
- - ~>
|
283
263
|
- !ruby/object:Gem::Version
|
284
264
|
version: 0.1.2
|
@@ -488,12 +468,14 @@ files:
|
|
488
468
|
- flydata-core/lib/flydata-core/core_ext/object/prepend.rb
|
489
469
|
- flydata-core/lib/flydata-core/errors.rb
|
490
470
|
- flydata-core/lib/flydata-core/fluent-plugins/multi_buffer.rb
|
471
|
+
- flydata-core/lib/flydata-core/fluent/config_helper.rb
|
491
472
|
- flydata-core/lib/flydata-core/logger.rb
|
492
473
|
- flydata-core/lib/flydata-core/table_def.rb
|
493
474
|
- flydata-core/lib/flydata-core/table_def/mysql_table_def.rb
|
494
475
|
- flydata-core/lib/flydata-core/table_def/redshift_table_def.rb
|
495
476
|
- flydata-core/lib/flydata-core/thread_context.rb
|
496
477
|
- flydata-core/spec/config/user_maintenance_spec.rb
|
478
|
+
- flydata-core/spec/fluent/config_helper_spec.rb
|
497
479
|
- flydata-core/spec/logger_spec.rb
|
498
480
|
- flydata-core/spec/spec_helper.rb
|
499
481
|
- flydata-core/spec/table_def/mysql_table_def_spec.rb
|
@@ -632,7 +614,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
632
614
|
version: '0'
|
633
615
|
requirements: []
|
634
616
|
rubyforge_project:
|
635
|
-
rubygems_version: 2.4.
|
617
|
+
rubygems_version: 2.4.6
|
636
618
|
signing_key:
|
637
619
|
specification_version: 4
|
638
620
|
summary: FlyData Agent
|