flydata 0.3.13 → 0.3.14
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 +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
|