flydata 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0bbdc5f5871df8b3fec4c8c92abd1fdb6b6b24f6
4
- data.tar.gz: 0be09c4771db44cac9c3229251598f6f5c3c23fd
3
+ metadata.gz: 3363c696e28b167255482e1d6b7352d5e3989786
4
+ data.tar.gz: 57d1039674d07396d58b2cf32d25c5c38db703ca
5
5
  SHA512:
6
- metadata.gz: 3bdacc04e29100c441e7e1eb1660eb9763e2566f0ac05846a7cc85ac2067e4f0171c41d95e4a12ae5fa7b9c3720b5583040191a68b669b392e360fa58be79abb
7
- data.tar.gz: 932a0de391228f576f389c731f312108931be9473875fe8265cc982d58771a6ea20671a762eeaf7b30a5aefbdfa0d60bb4572f409635f757e2bd900fad65e966
6
+ metadata.gz: 24e8879e214ec3b0cfa21d7b725e05bca66b4c668f59d3bfc5869285e70d1a92f97971002566f9d7e65332d91897561a20ffab26916ee7ce35c163e25066546a
7
+ data.tar.gz: 6303e50004f8d927867892a94e309d8e578cee1ed633f2768bae4470aca808cd9945ff2694ac220a07d4e20bea35df2df194963475ee971417910c22bdc6914b
data/Gemfile CHANGED
@@ -13,7 +13,7 @@ gem "slop", '~> 3.4', '>= 3.4.6'
13
13
  gem "treetop", '~> 1.5', '>= 1.5.3'
14
14
  gem "sys-filesystem", '~> 1.1', '>= 1.1.3'
15
15
  gem "io-console", '~> 0.4.2', '>= 0.4.2'
16
- gem "kodama", '~> 0.1.2', '>= 0.1.6'
16
+ gem "kodama", '~> 0.1.2', '>= 0.1.7'
17
17
  gem "serverengine", '~> 1.5'
18
18
 
19
19
  group :development do
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.6)
65
- ruby-binlog (~> 1.0, >= 1.0.4)
64
+ kodama (0.1.7)
65
+ ruby-binlog (~> 1.0, >= 1.0.6)
66
66
  method_source (0.8.2)
67
67
  mime-types (2.3)
68
68
  minitest (4.7.5)
@@ -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.4)
108
+ ruby-binlog (1.0.6)
109
109
  ruby-prof (0.15.1)
110
110
  serverengine (1.5.10)
111
111
  sigdump (~> 0.2.2)
@@ -135,7 +135,7 @@ DEPENDENCIES
135
135
  io-console (~> 0.4.2, >= 0.4.2)
136
136
  jeweler (~> 1.8, >= 1.8.8)
137
137
  json (~> 1.8, >= 1.8.0)
138
- kodama (~> 0.1.2, >= 0.1.6)
138
+ kodama (~> 0.1.2, >= 0.1.7)
139
139
  mysql2 (~> 0.3, >= 0.3.17)
140
140
  protected_attributes (~> 1.0, >= 1.0.8)
141
141
  pry
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.5.1
@@ -14,3 +14,4 @@ spec/reports
14
14
  test/tmp
15
15
  test/version_tmp
16
16
  tmp
17
+ /vendor/
data/flydata-core/Gemfile CHANGED
@@ -1,11 +1,14 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+
3
4
  # for dependencies
5
+ gem 'aws-sdk', "1.18.0"
6
+
4
7
  group :development, :test do
5
8
  gem 'timecop'
6
9
  gem 'ruby-prof'
7
10
  gem 'rubocop'
11
+ gem 'mysql2'
8
12
  gem 'rspec', '~> 3.1'
9
13
  gem 'simplecov', :require => false
10
14
  end
11
-
@@ -4,9 +4,16 @@ GEM
4
4
  ast (2.0.0)
5
5
  astrolabe (1.3.0)
6
6
  parser (>= 2.2.0.pre.3, < 3.0)
7
+ aws-sdk (1.18.0)
8
+ json (~> 1.4)
9
+ nokogiri (< 1.6.0)
10
+ uuidtools (~> 2.1)
7
11
  diff-lcs (1.2.5)
8
12
  docile (1.1.5)
13
+ json (1.8.2)
9
14
  multi_json (1.10.1)
15
+ mysql2 (0.3.18)
16
+ nokogiri (1.5.11)
10
17
  parser (2.2.0.pre.8)
11
18
  ast (>= 1.1, < 3.0)
12
19
  slop (~> 3.4, >= 3.4.5)
@@ -39,11 +46,14 @@ GEM
39
46
  simplecov-html (0.8.0)
40
47
  slop (3.6.0)
41
48
  timecop (0.7.1)
49
+ uuidtools (2.1.5)
42
50
 
43
51
  PLATFORMS
44
52
  ruby
45
53
 
46
54
  DEPENDENCIES
55
+ aws-sdk (= 1.18.0)
56
+ mysql2
47
57
  rspec (~> 3.1)
48
58
  rubocop
49
59
  ruby-prof
@@ -118,34 +118,57 @@ module FlydataCore
118
118
  'binlog_format'=>'ROW',
119
119
  'binlog_checksum'=>'NONE',
120
120
  'log_bin_use_v1_row_events'=>'ON',
121
- 'log_slave_updates'=>'ON'
121
+ 'log_slave_updates'=>'ON',
122
+ # parameter => {"comparison sign"=>minimum value}
123
+ # TODO: Handled the error message of following items as warning
124
+ #'net_read_timeout'=>{'>'=>600},
125
+ #'net_write_timeout'=>{'>'=>600},
126
+ #'wait_timeout'=>{'>'=>60}
122
127
  }
128
+ OPTIONAL_SYS_VAR = %w(binlog_checksum log_bin_use_v1_row_events)
123
129
 
124
130
  def check_result(result, option = @option)
125
131
  errors = {}
126
132
  param_hash = convert_result_to_hash(result)
127
133
 
128
- SYS_VAR_TO_CHECK.each_key do |sys_var|
129
- if param_hash.has_key?(sys_var)
130
- actual_val = param_hash[sys_var]
131
- expected_val = SYS_VAR_TO_CHECK[sys_var]
132
- unless actual_val == expected_val
133
- errors[sys_var] = actual_val
134
- end
135
- elsif not %w(binlog_checksum log_bin_use_v1_row_events).include?(sys_var)
136
- # Mark variables that do not exist as error
137
- errors[sys_var] = false
138
- end
139
- end
134
+ compare_sys_var_values(param_hash, SYS_VAR_TO_CHECK, errors, OPTIONAL_SYS_VAR)
140
135
 
141
136
  unless errors.empty?
142
137
  error_explanation = ""
143
138
  errors.each_key do |err_key|
144
- error_explanation << "\n * #{err_key} is #{errors[err_key]} but should be #{SYS_VAR_TO_CHECK[err_key]}"
139
+ if SYS_VAR_TO_CHECK[err_key].is_a?(Hash)
140
+ error_explanation << "\n * #{err_key} is #{errors[err_key]} but should be at least #{SYS_VAR_TO_CHECK[err_key].values.first}"
141
+ else
142
+ error_explanation << "\n * #{err_key} is #{errors[err_key]} but should be #{SYS_VAR_TO_CHECK[err_key]}"
143
+ end
145
144
  end
146
145
  raise FlydataCore::MysqlCompatibilityError,
147
146
  "These system variable(s) are not the correct value: #{error_explanation}\n" +
148
- " Please change these system variables for FlyData Sync to run correctly"
147
+ " Please change these system variables for FlyData Sync to run"
148
+ end
149
+ end
150
+
151
+ private
152
+ def compare_sys_var_values(input_value_hash, expected_value_hash, errors, exception_arr)
153
+ expected_value_hash.each_key do |exp_val|
154
+ if input_value_hash.has_key?(exp_val)
155
+ actual_val = input_value_hash[exp_val]
156
+ compare_sym = expected_value_hash[exp_val].is_a?(Hash) ? expected_value_hash[exp_val].keys.first : "="
157
+ case compare_sym
158
+ when "="
159
+ expected_val = expected_value_hash[exp_val]
160
+ unless actual_val == expected_val
161
+ errors[exp_val] = actual_val
162
+ end
163
+ when ">"
164
+ expected_val = expected_value_hash[exp_val].values.first
165
+ unless actual_val.to_i >= expected_val.to_i
166
+ errors[exp_val] = actual_val
167
+ end
168
+ end
169
+ elsif not exception_arr.include?(exp_val)
170
+ errors[exp_val] = false
171
+ end
149
172
  end
150
173
  end
151
174
  end
@@ -181,6 +204,34 @@ module FlydataCore
181
204
  end
182
205
  end
183
206
 
207
+ class PrimaryKeyChecker < MysqlCompatibilityChecker
208
+ PK_CHECK_QUERY_TMPLT = <<EOT
209
+ SELECT k.table_name as table_name
210
+ FROM information_schema.table_constraints t
211
+ JOIN information_schema.key_column_usage k
212
+ USING(constraint_name,table_schema,table_name)
213
+ WHERE t.constraint_type='PRIMARY KEY'
214
+ AND t.table_schema='%{database}'
215
+ AND t.table_name in (%{table_names})
216
+ GROUP BY k.table_name;
217
+ EOT
218
+ def create_query(option = @option)
219
+ PK_CHECK_QUERY_TMPLT % {database: option[:database], table_names: option[:tables].collect{|tn| "'#{tn}'"}.join(',')}
220
+ end
221
+
222
+ def check_result(result, option = @option)
223
+ pk_tables = []
224
+ result.each {|r| pk_tables << r['table_name']}
225
+ missing_pk_tables = option[:tables] - pk_tables
226
+
227
+ unless missing_pk_tables.empty?
228
+ raise FlydataCore::MysqlCompatibilityError,
229
+ "Primary key is required for tables to sync. " +
230
+ "Add primary key or remove following tables from data entry: #{missing_pk_tables.join(", ")}"
231
+ end
232
+ end
233
+ end
234
+
184
235
  class NonRdsRetentionChecker < MysqlCompatibilityChecker
185
236
  include MysqlVariablesHandling
186
237
 
@@ -87,6 +87,19 @@ EOS
87
87
  schema_name.to_s.empty? ? "\"#{table_name}\"" : "\"#{schema_name}\".\"#{table_name}\""
88
88
  end
89
89
 
90
+ def self.fq_table_name(table_name, schema_name)
91
+ idx = table_name.rindex('.')
92
+ if (idx)
93
+ # table name has schame qualifier. Remove it.
94
+ table_name = table_name[idx+1..-1]
95
+ end
96
+
97
+ result =
98
+ schema_name.to_s.empty? ? table_name : "#{schema_name}.#{table_name}"
99
+
100
+ convert_to_valid_table_name(result)
101
+ end
102
+
90
103
  def self.flydata_ctl_table_for_ddl(schema_name, ctl_table_type = :columns)
91
104
  table_name = case ctl_table_type
92
105
  when :columns; FLYDATA_CTL_COLUMNS_TABLE
@@ -0,0 +1,28 @@
1
+ module FlydataCore
2
+
3
+ module WrapperSingleForwardable
4
+ # Delegates a method call `delegator` to the given `accessor` like the
5
+ # original `def_single_delegator` does. In addition, it wraps the returned
6
+ # object (or each object in an array) with the caller's own instance.
7
+ def def_wrapper_single_delegator(accessor, delegator)
8
+ self.define_singleton_method(delegator) do |*args|
9
+ result = accessor.send(delegator, *args)
10
+ case result
11
+ when Array
12
+ result.collect{|res| self.new(res)}
13
+ when NilClass
14
+ nil
15
+ else
16
+ self.new(result)
17
+ end
18
+ end
19
+ end
20
+
21
+ def def_wrapper_single_delegators(accessor, *delegators)
22
+ delegators.each do |delegator|
23
+ def_wrapper_single_delegator(accessor, delegator)
24
+ end
25
+ end
26
+ end
27
+
28
+ end
@@ -1,9 +1,186 @@
1
1
  require 'spec_helper'
2
+ require 'flydata-core/mysql/compatibility_checker'
2
3
 
3
4
  module FlydataCore
4
5
  module Mysql
5
- describe SyncPermissionChecker do
6
+ describe CompatibilityChecker do
7
+ let(:database) { 'test_db' }
8
+ let(:tables) { %w(table_1 table_2 table_3) }
9
+ let(:option) do
10
+ { database: database, tables: tables }
11
+ end
6
12
 
13
+ describe PrimaryKeyChecker do
14
+ let(:subject_object) { described_class.new(option) }
15
+
16
+ describe '#create_query' do
17
+ subject { subject_object.create_query }
18
+ it { is_expected.to eq <<EOT
19
+ SELECT k.table_name as table_name
20
+ FROM information_schema.table_constraints t
21
+ JOIN information_schema.key_column_usage k
22
+ USING(constraint_name,table_schema,table_name)
23
+ WHERE t.constraint_type='PRIMARY KEY'
24
+ AND t.table_schema='test_db'
25
+ AND t.table_name in ('table_1','table_2','table_3')
26
+ GROUP BY k.table_name;
27
+ EOT
28
+ }
29
+ end
30
+
31
+ describe '#check_reesult' do
32
+ let(:result) { [] }
33
+ subject { subject_object.check_result(result) }
34
+
35
+ context 'when all tables have pk' do
36
+ let(:result) do
37
+ [ {"table_name" => "table_1"},
38
+ {"table_name" => "table_2"},
39
+ {"table_name" => "table_3"}, ]
40
+ end
41
+ it { expect{subject}.not_to raise_error }
42
+ end
43
+
44
+ context 'when some tables does not have pk' do
45
+ let(:result) { [{"table_name" => "table_2"} ] }
46
+ it do
47
+ expect{subject}.to raise_error {|e|
48
+ expect(e).to be_kind_of(FlydataCore::MysqlCompatibilityError)
49
+ expect(e.to_s.include?("table_1")).to be_truthy
50
+ expect(e.to_s.include?("table_2")).to be_falsey
51
+ expect(e.to_s.include?("table_3")).to be_truthy
52
+ }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe BinlogParameterChecker do
60
+ let(:subject_object) { BinlogParameterChecker.new({}) }
61
+
62
+ describe "#check_result" do
63
+ let(:sys_var) do
64
+ [
65
+ {'Variable_name'=>'binlog_format','Value'=>'ROW'},
66
+ {'Variable_name'=>'binlog_checksum','Value'=>'NONE'},
67
+ {'Variable_name'=>'log_bin_use_v1_row_events','Value'=>'ON'},
68
+ {'Variable_name'=>'log_slave_updates','Value'=>'ON'},
69
+ {'Variable_name'=>'net_read_timeout','Value'=>600},
70
+ {'Variable_name'=>'net_write_timeout','Value'=>600},
71
+ {'Variable_name'=>'wait_timeout','Value'=>60}
72
+ ]
73
+ end
74
+ subject { subject_object.check_result(sys_var, {}) }
75
+
76
+ context "where parameters are valid" do
77
+ it do
78
+ expect{subject}.to_not raise_error
79
+ end
80
+ end
81
+ context "where parameters are invalid" do
82
+ let(:sys_var) do
83
+ [
84
+ {'Variable_name'=>'binlog_format','Value'=>'MIXED'},
85
+ {'Variable_name'=>'binlog_checksum','Value'=>'NONE'},
86
+ {'Variable_name'=>'log_bin_use_v1_row_events','Value'=>'ON'},
87
+ {'Variable_name'=>'log_slave_updates','Value'=>'ON'},
88
+ {'Variable_name'=>'net_read_timeout','Value'=>600},
89
+ {'Variable_name'=>'net_write_timeout','Value'=>600},
90
+ {'Variable_name'=>'wait_timeout','Value'=>30}
91
+ ]
92
+ end
93
+ it do
94
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /binlog_format.*\n.*wait_timeout/)
95
+ end
96
+ end
97
+ end
98
+ describe "#compare_sys_var_values" do
99
+ let(:expected_val) do
100
+ {
101
+ :value_1 => 'foo',
102
+ :value_2 => 50,
103
+ :value_3 => {">"=>100}
104
+ }
105
+ end
106
+ let(:errors) { {} }
107
+ let(:exception_arr) { [] }
108
+ subject { subject_object.send(:compare_sys_var_values, input_val, expected_val, errors, exception_arr) }
109
+
110
+ shared_examples "expect correct errors from values" do
111
+ it do
112
+ subject
113
+ expect(errors).to eq( expecting_errors )
114
+ end
115
+ end
116
+
117
+ context "when getting valid parameters" do
118
+ let(:input_val) do
119
+ {
120
+ :value_1 => 'foo',
121
+ :value_2 => 50,
122
+ :value_3 => 200
123
+ }
124
+ end
125
+ let(:expecting_errors) { {} }
126
+ it_behaves_like "expect correct errors from values"
127
+ end
128
+ context "when getting one invalid exact parameters for int" do
129
+ let(:input_val) do
130
+ {
131
+ :value_1 => 'foo',
132
+ :value_2 => 20,
133
+ :value_3 => 100
134
+ }
135
+ end
136
+ let(:expecting_errors) { {value_2:20} }
137
+ it_behaves_like "expect correct errors from values"
138
+ end
139
+ context "when getting one invalid exact parameter for string" do
140
+ let(:input_val) do
141
+ {
142
+ :value_1 => 'fo',
143
+ :value_2 => 50,
144
+ :value_3 => 100
145
+ }
146
+ end
147
+ let(:expecting_errors) { {value_1:'fo'} }
148
+ it_behaves_like "expect correct errors from values"
149
+ end
150
+ context "when getting one invalid comparitive parameter that's lower than required" do
151
+ let(:input_val) do
152
+ {
153
+ :value_1 => 'foo',
154
+ :value_2 => 50,
155
+ :value_3 => 1
156
+ }
157
+ end
158
+ let(:expecting_errors) { {value_3:1} }
159
+ it_behaves_like "expect correct errors from values"
160
+ end
161
+ context "when getting a valid comparitive parameter that's higher than required" do
162
+ let(:input_val) do
163
+ {
164
+ :value_1 => 'foo',
165
+ :value_2 => 50,
166
+ :value_3 => 101
167
+ }
168
+ end
169
+ let(:expecting_errors) { {} }
170
+ it_behaves_like "expect correct errors from values"
171
+ end
172
+ context "when getting muliple invalid parameters" do
173
+ let(:input_val) do
174
+ {
175
+ :value_1 => 'fo',
176
+ :value_2 => 50,
177
+ :value_3 => 15
178
+ }
179
+ end
180
+ let(:expecting_errors) { {value_1:'fo', value_3:15} }
181
+ it_behaves_like "expect correct errors from values"
182
+ end
183
+ end
7
184
  end
8
185
  end
9
186
  end
@@ -896,6 +896,43 @@ EOS
896
896
 
897
897
  it_behaves_like "expecting no underscore in front of numbers"
898
898
  end
899
+
900
+ describe ".fq_table_name" do
901
+ subject { subject_object.fq_table_name(table_name, schema_name) }
902
+ context "with no schema name" do
903
+ let(:schema_name) { nil }
904
+ context "with a table name with no schema prefix" do
905
+ let(:table_name) { "test_table" }
906
+ it { is_expected.to eq "test_table" }
907
+ end
908
+ context "with a table name with a schema prefix" do
909
+ let(:table_name) { "some_schema.test_table" }
910
+ it { is_expected.to eq "test_table" }
911
+ end
912
+ context "with a mixed-case table name" do
913
+ let(:table_name) { "Test_Table" }
914
+ it { is_expected.to eq "test_table" }
915
+ end
916
+ end
917
+ context "with a schema name" do
918
+ let(:schema_name) { "test_schema" }
919
+ context "with a table name with no schema prefix" do
920
+ let(:table_name) { "test_table" }
921
+ it { is_expected.to eq "test_schema.test_table" }
922
+ end
923
+ context "with a table name with a schema prefix" do
924
+ let(:table_name) { "some_schema.test_table" }
925
+ it { is_expected.to eq "test_schema.test_table" }
926
+ end
927
+ end
928
+ context "with a mixed-case schema name" do
929
+ let(:schema_name) { "Test_Schema" }
930
+ context "with a table name with no schema prefix" do
931
+ let(:table_name) { "test_table" }
932
+ it { is_expected.to eq "test_schema.test_table" }
933
+ end
934
+ end
935
+ end
899
936
  end
900
937
 
901
938
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'flydata-core/wrapper_forwardable'
3
+
4
+ module FlydataCore
5
+
6
+ describe WrapperSingleForwardable do
7
+ class Target
8
+ def self.foo(a, b)
9
+ target_foo_result
10
+ end
11
+ end
12
+
13
+ class Test
14
+ extend WrapperSingleForwardable
15
+
16
+ def_wrapper_single_delegator Target, :foo
17
+
18
+ def initialize(item)
19
+ @item = item
20
+ end
21
+
22
+ def ==(other)
23
+ @item == other.item
24
+ end
25
+
26
+ attr_reader :item
27
+ end
28
+ let(:subject_object) { Test }
29
+ let(:args) { [ 'arg1', 'arg2' ] }
30
+
31
+ describe '.def_wrapper_single_delegator' do
32
+ it 'defines a class method of the given name to the subject class' do
33
+ expect(subject_object.respond_to?(:foo)).to eq true
34
+ end
35
+
36
+ describe 'the method defined by it' do
37
+ subject { subject_object.foo(*args) }
38
+ before do
39
+ expect(Target).to receive(:foo).with(*args).
40
+ and_return(target_foo_result)
41
+ end
42
+
43
+ context 'when the target method returns an object' do
44
+ let(:target_foo_result) { double('single_object') }
45
+
46
+ it 'returns an object of the subject class containing the target result' do
47
+ is_expected.to eq subject_object.new(target_foo_result)
48
+ end
49
+ end
50
+ context 'when the target method returns nil' do
51
+ let(:target_foo_result) { nil }
52
+
53
+ it 'returns nil' do
54
+ is_expected.to eq nil
55
+ end
56
+ end
57
+ context 'when the target method returns an array' do
58
+ let(:target_foo_result) { [ double('object1'), double('object2') ] }
59
+ it 'returns an array of instances of the subject class. Each instance contains an object returned from the target' do
60
+ is_expected.to eq target_foo_result.collect{|item| subject_object.new(item) }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ end
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.5.0 ruby lib
5
+ # stub: flydata 0.5.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "flydata"
9
- s.version = "0.5.0"
9
+ s.version = "0.5.1"
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-07-24"
14
+ s.date = "2015-08-04"
15
15
  s.description = "FlyData Agent"
16
16
  s.email = "sysadmin@flydata.com"
17
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -51,8 +51,6 @@ Gem::Specification.new do |s|
51
51
  "flydata-core/lib/flydata-core/mysql/compatibility_checker.rb",
52
52
  "flydata-core/lib/flydata-core/option_validator.rb",
53
53
  "flydata-core/lib/flydata-core/query_job.rb",
54
- "flydata-core/lib/flydata-core/query_job/redshift.rb",
55
- "flydata-core/lib/flydata-core/query_job/table_status.rb",
56
54
  "flydata-core/lib/flydata-core/record/record.rb",
57
55
  "flydata-core/lib/flydata-core/redshift/string.rb",
58
56
  "flydata-core/lib/flydata-core/table_def.rb",
@@ -61,13 +59,13 @@ Gem::Specification.new do |s|
61
59
  "flydata-core/lib/flydata-core/table_def/redshift_table_def.rb",
62
60
  "flydata-core/lib/flydata-core/table_def/sync_redshift_table_def.rb",
63
61
  "flydata-core/lib/flydata-core/thread_context.rb",
62
+ "flydata-core/lib/flydata-core/wrapper_forwardable.rb",
64
63
  "flydata-core/spec/config/user_maintenance_spec.rb",
65
64
  "flydata-core/spec/fluent/config_helper_spec.rb",
66
65
  "flydata-core/spec/logger_spec.rb",
67
66
  "flydata-core/spec/mysql/command_generator_spec.rb",
68
67
  "flydata-core/spec/mysql/compatibility_checker.rb",
69
68
  "flydata-core/spec/option_validator_spec.rb",
70
- "flydata-core/spec/query_job/redshift_spec.rb",
71
69
  "flydata-core/spec/redshift/string_spec.rb",
72
70
  "flydata-core/spec/spec_helper.rb",
73
71
  "flydata-core/spec/table_def/autoload_redshift_table_def_spec.rb",
@@ -88,6 +86,7 @@ Gem::Specification.new do |s|
88
86
  "flydata-core/spec/table_def/mysqldump_test_unsigned.dump",
89
87
  "flydata-core/spec/table_def/redshift_table_def_spec.rb",
90
88
  "flydata-core/spec/table_def/sync_redshift_table_def_spec.rb",
89
+ "flydata-core/spec/wrapper_forwardable_spec.rb",
91
90
  "flydata.gemspec",
92
91
  "lib/fly_data_model.rb",
93
92
  "lib/flydata.rb",
@@ -243,7 +242,7 @@ Gem::Specification.new do |s|
243
242
  s.add_runtime_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
244
243
  s.add_runtime_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
245
244
  s.add_runtime_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
246
- s.add_runtime_dependency(%q<kodama>, [">= 0.1.6", "~> 0.1.2"])
245
+ s.add_runtime_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
247
246
  s.add_runtime_dependency(%q<serverengine>, ["~> 1.5"])
248
247
  s.add_development_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
249
248
  s.add_development_dependency(%q<rspec>, ["~> 3.0"])
@@ -267,7 +266,7 @@ Gem::Specification.new do |s|
267
266
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
268
267
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
269
268
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
270
- s.add_dependency(%q<kodama>, [">= 0.1.6", "~> 0.1.2"])
269
+ s.add_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
271
270
  s.add_dependency(%q<serverengine>, ["~> 1.5"])
272
271
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
273
272
  s.add_dependency(%q<rspec>, ["~> 3.0"])
@@ -292,7 +291,7 @@ Gem::Specification.new do |s|
292
291
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
293
292
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
294
293
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
295
- s.add_dependency(%q<kodama>, [">= 0.1.6", "~> 0.1.2"])
294
+ s.add_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
296
295
  s.add_dependency(%q<serverengine>, ["~> 1.5"])
297
296
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
298
297
  s.add_dependency(%q<rspec>, ["~> 3.0"])
@@ -37,7 +37,7 @@ module Flydata
37
37
  # Start sender(fluentd) process
38
38
  log_info_stdout("Starting FlyData Agent sender process.") unless options[:quiet]
39
39
  raw_start(options)
40
-
40
+
41
41
  wait_until_client_ready(options)
42
42
  #wait_until_logs_uploaded
43
43
  fluentd_started = true
@@ -117,7 +117,7 @@ EOF
117
117
  `[ -f #{pid_file} ] && pgrep -P \`cat #{pid_file}\``.to_i > 0
118
118
  end
119
119
  def kill_all(options = {})
120
- if Kernel.system("ps ax | grep 'flydata' | grep -v grep | awk '{print \"kill \" $1}' | sh")
120
+ if Kernel.system("ps ax | grep 'flydata' | grep -v grep | grep fluentd | awk '{print \"kill \" $1}' | sh")
121
121
  log_info_stdout("Done.") unless options[:quiet]
122
122
  return true
123
123
  else
@@ -172,7 +172,7 @@ EOF
172
172
  raise "Somthing has gone wrong... Please try setup command again."
173
173
  end
174
174
  def wait_until_client_stop(options = {})
175
- retry_count = 5
175
+ retry_count = 10
176
176
  1.upto(retry_count) do |i|
177
177
  return true unless process_exist?
178
178
  log_info_stdout("Waiting for the client to stop... (#{i}/#{retry_count})") unless options[:quiet]
@@ -57,6 +57,23 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
57
57
  config_param :idle_timeout, :time, :default => 1800 # 30 min
58
58
  config_param :check_interval, :integer, :default => 5 # 5 sec
59
59
  config_param :ssl_ca_content, :string, :default => ''
60
+ config_param :ssl_cipher, :string, :default => nil
61
+
62
+ # Secondary ssl cipher is for a workaround to handle 'dh key too small' error
63
+ # If mysql-server is v5.6.25 or older, and client openssl is
64
+ # 1.0.1f-1ubuntu-2.15(for ubuntu) or later, client will get the above error because.
65
+ # the key length returned from mysql-server is only 512 bits.
66
+ #
67
+ # In case of dh key error, we retry with non-DH cipher.
68
+ #
69
+ # * SECURITY IMPROVEMENT: reject dh keys smaller than 768 bits
70
+ # https://launchpad.net/ubuntu/+source/openssl/1.0.1f-1ubuntu2.15
71
+ #
72
+ # Supported ssl cipher list for mysql(openssl)
73
+ # https://dev.mysql.com/doc/refman/5.6/en/ssl-options.html
74
+
75
+ NON_DH_SSL_CIPHER = "AES256-GCM-SHA384:AES256-SHA:AES256-SHA256:CAMELLIA256-SHA:DES-CBC3-SHA:PSK-3DES-EDE-CBC-SHA:PSK-AES256-CBC-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:SRP-RSA-AES-128-CBC-S:SRP-RSA-AES-256-CBC-SHA"
76
+ config_param :secondary_ssl_cipher, :string, :default => NON_DH_SSL_CIPHER
60
77
 
61
78
  def configure(conf)
62
79
  super
@@ -110,7 +127,6 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
110
127
  h
111
128
  end
112
129
 
113
-
114
130
  # Set context
115
131
  @context = Mysql::Context.new(
116
132
  database: @database, tables: @tables,
@@ -162,29 +178,48 @@ EOS
162
178
  @context) do |event|
163
179
  @record_dispatcher.dispatch(event)
164
180
  end
165
- start_kodama(mysql_url) do |c|
166
- c.binlog_position_file = @position_file
167
- if @ssl_ca_path.to_s != '' && c.respond_to?(:ssl_ca=)
168
- $log.info "SSL is enabled. (ssl_ca: #{@ssl_ca_path})"
169
- c.ssl_ca = @ssl_ca_path
170
- end
171
181
 
172
- if c.respond_to?(:sent_binlog_position_file=)
173
- $log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
174
- c.sent_binlog_position_file = @sent_position_file_path
175
- end
182
+ current_ssl_cipher = @ssl_cipher
183
+ retried = false
184
+ begin
185
+ start_kodama(mysql_url) do |c|
186
+ c.binlog_position_file = @position_file
187
+ if @ssl_ca_path.to_s != '' && c.respond_to?(:ssl_ca=)
188
+ $log.info "SSL is enabled. (ssl_ca: #{@ssl_ca_path})"
189
+ c.ssl_ca = @ssl_ca_path
190
+ unless current_ssl_cipher.to_s.empty?
191
+ $log.info "SSL cipher is set. (ssl_cipher: #{current_ssl_cipher})"
192
+ c.ssl_cipher = current_ssl_cipher
193
+ end
194
+ end
176
195
 
177
- $log.info("Binlog position - resume_pos:'#{IO.read(@position_file) rescue IOError}' " +
178
- "sent_pos:'#{IO.read(@sent_position_file_path) rescue IOError}'")
196
+ if c.respond_to?(:sent_binlog_position_file=)
197
+ $log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
198
+ c.sent_binlog_position_file = @sent_position_file_path
199
+ end
179
200
 
180
- c.connection_retry_limit = @retry_limit
181
- c.connection_retry_wait = @retry_wait
182
- c.log_level = @log_level.to_sym
183
- @listen_events.each do |event_type|
184
- $log.trace { "registered binlog event listener '#{event_type}'" }
185
- c.send("on_#{event_type}", &method(:event_listener))
201
+ $log.info("Binlog position - resume_pos:'#{IO.read(@position_file) rescue IOError}' " +
202
+ "sent_pos:'#{IO.read(@sent_position_file_path) rescue IOError}'")
203
+
204
+ c.connection_retry_limit = @retry_limit
205
+ c.connection_retry_wait = @retry_wait
206
+ c.log_level = @log_level.to_sym
207
+ @listen_events.each do |event_type|
208
+ $log.trace { "registered binlog event listener '#{event_type}'" }
209
+ c.send("on_#{event_type}", &method(:event_listener))
210
+ end
211
+ end
212
+ rescue Binlog::Error => e
213
+ if /dh key too small/.match(e.to_s) && !retried && !@secondary_ssl_cipher.to_s.empty?
214
+ retried = true
215
+ current_ssl_cipher = @secondary_ssl_cipher
216
+ $log.warn("Retry with secondary ssl cipher list due to '#{e}' - secondary_ssl_cipher: '#{@secondary_ssl_cipher}'")
217
+ retry
218
+ else
219
+ raise e
186
220
  end
187
221
  end
222
+
188
223
  rescue => e
189
224
  # HACK: mysql-replication-listener has a network connection leak bug which doesn't release a connection
190
225
  # to MySQL. Rather than fixing the bug, restarting the fluentd process for now.
@@ -894,7 +894,7 @@ grammar MysqlAlterTable
894
894
  }
895
895
  end
896
896
  rule character_set_opt
897
- 'character set'i sp value {
897
+ charset sp value {
898
898
  def character_set_opt_option
899
899
  { cs: FlydataCore::TableDef::MysqlTableDef.flydata_charset(value.raw_value) }
900
900
  end
@@ -185,19 +185,50 @@ describe 'MysqlAlterTableParser' do
185
185
  end
186
186
 
187
187
  context 'with after option' do
188
- let(:query) { "alter table test_table add column value varchar(26) after id" }
189
- it do
190
- expect(subject).to eq({
191
- type: :alter_table,
192
- table_name: "test_table",
193
- actions: [{
194
- action: :add_column,
195
- column: "value",
196
- type: "varchar(78)",
197
- after: 'id',
198
- query: "add column value varchar(26) after id"
199
- }]
200
- })
188
+ context 'without charset' do
189
+ let(:query) { "alter table test_table add column value varchar(26) after id" }
190
+ it do
191
+ expect(subject).to eq({
192
+ type: :alter_table,
193
+ table_name: "test_table",
194
+ actions: [{
195
+ action: :add_column,
196
+ column: "value",
197
+ type: "varchar(78)",
198
+ after: 'id',
199
+ query: "add column value varchar(26) after id"
200
+ }]
201
+ })
202
+ end
203
+ end
204
+ context 'with charset and collate' do
205
+ shared_examples "parse character set correctly" do
206
+ let(:query) { "alter table `kiikplan`.`plan` add column `email_header` varchar(1024) #{charset} utf8 COLLATE utf8_general_ci NULL after `color`" }
207
+ it do
208
+ expect(subject).to eq({
209
+ type: :alter_table,
210
+ table_name: "plan",
211
+ actions: [{
212
+ action: :add_column,
213
+ column: "email_header",
214
+ type: "varchar(3072)",
215
+ cs: "UTF_8",
216
+ after: 'color',
217
+ query: "add column `email_header` varchar(1024) #{charset} utf8 COLLATE utf8_general_ci NULL after `color`"
218
+ }],
219
+ schema_name: "kiikplan"
220
+ })
221
+ end
222
+ end
223
+ context "with character set" do
224
+ let(:charset) { "character set" }
225
+ include_examples "parse character set correctly"
226
+ end
227
+
228
+ context "with charset" do
229
+ let(:charset) { "CHARSET" }
230
+ include_examples "parse character set correctly"
231
+ end
201
232
  end
202
233
  end
203
234
  shared_examples "generating a flydata record for the given query" do
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.5.0
4
+ version: 0.5.1
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-07-24 00:00:00.000000000 Z
15
+ date: 2015-08-04 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -248,7 +248,7 @@ dependencies:
248
248
  requirements:
249
249
  - - '>='
250
250
  - !ruby/object:Gem::Version
251
- version: 0.1.6
251
+ version: 0.1.7
252
252
  - - ~>
253
253
  - !ruby/object:Gem::Version
254
254
  version: 0.1.2
@@ -258,7 +258,7 @@ dependencies:
258
258
  requirements:
259
259
  - - '>='
260
260
  - !ruby/object:Gem::Version
261
- version: 0.1.6
261
+ version: 0.1.7
262
262
  - - ~>
263
263
  - !ruby/object:Gem::Version
264
264
  version: 0.1.2
@@ -488,8 +488,6 @@ files:
488
488
  - flydata-core/lib/flydata-core/mysql/compatibility_checker.rb
489
489
  - flydata-core/lib/flydata-core/option_validator.rb
490
490
  - flydata-core/lib/flydata-core/query_job.rb
491
- - flydata-core/lib/flydata-core/query_job/redshift.rb
492
- - flydata-core/lib/flydata-core/query_job/table_status.rb
493
491
  - flydata-core/lib/flydata-core/record/record.rb
494
492
  - flydata-core/lib/flydata-core/redshift/string.rb
495
493
  - flydata-core/lib/flydata-core/table_def.rb
@@ -498,13 +496,13 @@ files:
498
496
  - flydata-core/lib/flydata-core/table_def/redshift_table_def.rb
499
497
  - flydata-core/lib/flydata-core/table_def/sync_redshift_table_def.rb
500
498
  - flydata-core/lib/flydata-core/thread_context.rb
499
+ - flydata-core/lib/flydata-core/wrapper_forwardable.rb
501
500
  - flydata-core/spec/config/user_maintenance_spec.rb
502
501
  - flydata-core/spec/fluent/config_helper_spec.rb
503
502
  - flydata-core/spec/logger_spec.rb
504
503
  - flydata-core/spec/mysql/command_generator_spec.rb
505
504
  - flydata-core/spec/mysql/compatibility_checker.rb
506
505
  - flydata-core/spec/option_validator_spec.rb
507
- - flydata-core/spec/query_job/redshift_spec.rb
508
506
  - flydata-core/spec/redshift/string_spec.rb
509
507
  - flydata-core/spec/spec_helper.rb
510
508
  - flydata-core/spec/table_def/autoload_redshift_table_def_spec.rb
@@ -525,6 +523,7 @@ files:
525
523
  - flydata-core/spec/table_def/mysqldump_test_unsigned.dump
526
524
  - flydata-core/spec/table_def/redshift_table_def_spec.rb
527
525
  - flydata-core/spec/table_def/sync_redshift_table_def_spec.rb
526
+ - flydata-core/spec/wrapper_forwardable_spec.rb
528
527
  - flydata.gemspec
529
528
  - lib/fly_data_model.rb
530
529
  - lib/flydata.rb
@@ -1,27 +0,0 @@
1
- require 'flydata-core/table_def/redshift_table_def'
2
-
3
- module FlydataCore
4
- module QueryJob
5
-
6
- class Redshift
7
- # returns a list of table names used in the Query Job system.
8
- def self.target_table_names(flydata_table_names)
9
- flydata_table_names = [ flydata_table_names ] unless flydata_table_names.kind_of?(Array)
10
-
11
- flydata_table_names.collect {|flydata_table_name|
12
- redshift_table_name = TableDef::RedshiftTableDef.convert_to_valid_table_name(flydata_table_name)
13
- table_names = [ redshift_table_name ]
14
- if redshift_table_name != flydata_table_name
15
- # for backward compatibility
16
- # Old implementation used FlyData table names. To support it, the
17
- # method adds the flydata_table_name as well.
18
- table_names << flydata_table_name
19
- end
20
-
21
- table_names
22
- }.flatten
23
- end
24
- end
25
-
26
- end
27
- end
@@ -1,44 +0,0 @@
1
- require 'flydata-core/query_job/redshift'
2
- require 'flydata-core/table_def/redshift_table_def'
3
-
4
- module FlydataCore
5
- module QueryJob
6
-
7
- class TableStatus
8
- @@domain = 'flydata_redshift_table_status'
9
-
10
- def self.domain=(domain)
11
- @@domain = domain
12
- end
13
-
14
- def self.sdb=(sdb)
15
- @@sdb = sdb
16
- end
17
-
18
- def self.where(*args)
19
- table_status_items = {}
20
- @@sdb.domains[@@domain].items.where(*args).each(select: :all) do |item|
21
- class << item
22
- # returns the corect (Redshift) table name
23
- def table_name
24
- FlydataCore::TableDef::RedshiftTableDef.convert_to_valid_table_name(attributes['table_name'].first)
25
- end
26
-
27
- def target_table_names
28
- FlydataCore::QueryJob::Redshift.target_table_names(attributes['table_name'].first)
29
- end
30
- end
31
- tn = item.attributes['table_name'].first
32
- redshift_table_name = FlydataCore::TableDef::RedshiftTableDef.convert_to_valid_table_name(tn)
33
- if redshift_table_name == tn
34
- table_status_items[redshift_table_name] ||= item
35
- else
36
- table_status_items[redshift_table_name] = item
37
- end
38
- end
39
- table_status_items.values
40
- end
41
- end
42
-
43
- end
44
- end
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
- require 'flydata-core/query_job/redshift'
3
-
4
- module FlydataCore::QueryJob
5
-
6
- describe Redshift do
7
- describe '.target_table_names' do
8
- subject { described_class.target_table_names(flydata_table_names) }
9
-
10
- context 'with a single table name' do
11
- let(:flydata_table_names) { "my_table" }
12
-
13
- it { is_expected.to eq [ flydata_table_names ] }
14
- end
15
-
16
- context 'with multiples table names' do
17
- let(:flydata_table_names) { %w(my_table1 my_table2) }
18
-
19
- it { is_expected.to eq flydata_table_names }
20
- end
21
- context 'with a mixed case table name' do
22
- let(:flydata_table_names) { "MyTable" }
23
-
24
- it { is_expected.to eq [ flydata_table_names.downcase, flydata_table_names ] }
25
- end
26
- context 'with table names including mixed case one' do
27
- let(:flydata_table_names) { %w(MyTable my_table2) }
28
-
29
- it { is_expected.to eq %w(mytable MyTable my_table2) }
30
- end
31
- end
32
- end
33
-
34
- end