flydata 0.5.8 → 0.5.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c79a1c7705cdd2112d4fd3465f311bf31583471
4
- data.tar.gz: b5a6e9d153bbf84dca5d582de5bc5df460d01a96
3
+ metadata.gz: 66683f280e2cbf2c1c8ad081e4b9194dba9a928c
4
+ data.tar.gz: ff0e0497ec61502cbcb5a17d2860e3a98117cd54
5
5
  SHA512:
6
- metadata.gz: 30e4e6fee11a8ba1b76f0e7c14e05f5d723a90655fc0e4cc0e42724f6edcef4d73514cf5d970becf3178a224172a9aa33d4fbe1bbbf27e4a0c0b73419b15fe34
7
- data.tar.gz: 9ae07ffd9eb356a7947f5c8c1331f48181cc1ac8f76392f5c2d92122f4cfff38ef6f2d94e4ac001914bbb1d537423ff6ba060650d9776154b8b865285601cb77
6
+ metadata.gz: ed0e5930aa2494cc5ffb11d026c5edca78ba03fd97c72f42293864d5a835323f3a087133dec202245e6f143074fb8e8dbde3bf05d638f1bfdcd73d0725ae0bc8
7
+ data.tar.gz: c770737b2a978791723d46a9a8983c1677174c83f15a86ca03db552891a2d37529913ba62cbde987837bc931ac3d715d6cbd953e523126bd6cbc3742edeef09f
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.7'
16
+ gem "kodama", '~> 0.1', '>= 0.1.8'
17
17
  gem "serverengine", '~> 1.5'
18
18
 
19
19
  group :development do
data/Gemfile.lock CHANGED
@@ -61,7 +61,7 @@ GEM
61
61
  rdoc
62
62
  json (1.8.1)
63
63
  jwt (1.0.0)
64
- kodama (0.1.7)
64
+ kodama (0.1.8)
65
65
  ruby-binlog (~> 1.0, >= 1.0.6)
66
66
  method_source (0.8.2)
67
67
  mime-types (2.3)
@@ -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.7)
138
+ kodama (~> 0.1, >= 0.1.8)
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.8
1
+ 0.5.9
@@ -1,4 +1,5 @@
1
1
  require 'flydata-core/thread_context'
2
+ require 'flydata-core/string_utils'
2
3
 
3
4
  module FlydataCore
4
5
 
@@ -129,8 +130,11 @@ class FlydataError < StandardError
129
130
 
130
131
  def filter_content(error_content = @error_content)
131
132
  error_content.each do |k, value|
132
- if value.kind_of?(String) && value.length > MAX_CONTENT_SIZE
133
- error_content[k] = value[0..MAX_CONTENT_SIZE-1]
133
+ if value.kind_of?(String)
134
+ if value.length > MAX_CONTENT_SIZE
135
+ value = error_content[k] = value[0..MAX_CONTENT_SIZE-1]
136
+ end
137
+ error_content[k] = FlydataCore::StringUtils.replace_invalid_utf8_char(value)
134
138
  end
135
139
  end
136
140
  end
@@ -128,7 +128,7 @@ module FlydataCore
128
128
  # parameter => {"comparison sign"=>minimum value}
129
129
  'net_read_timeout'=>{'>='=>600},
130
130
  'net_write_timeout'=>{'>='=>600},
131
- 'wait_timeout'=>{'>='=>60},
131
+ #'wait_timeout'=>{'>='=>60},
132
132
  }
133
133
 
134
134
  SYS_VAR_TO_CHECK = BASE_SYS_VAR_TO_CHECK.merge(ADDITIONAL_SYS_VAR_TO_CHECK)
@@ -260,15 +260,16 @@ EOT
260
260
  class PrimaryKeyChecker < MysqlCompatibilityChecker
261
261
  PK_CHECK_QUERY_TMPLT = <<EOT
262
262
  SELECT
263
- c.table_name as table_name,
264
- SUM(IF(c.column_key = 'PRI', 1, 0)) as num_pk
263
+ t.table_name,
264
+ SUM(IF(tc.constraint_type='PRIMARY KEY', 1, 0)) as num_pk
265
265
  FROM
266
- information_schema.columns c
266
+ information_schema.tables t
267
+ LEFT OUTER JOIN information_schema.table_constraints tc USING (table_schema, table_name)
267
268
  WHERE
268
- c.table_schema='%{database}'
269
- AND c.table_name in (%{table_names})
269
+ t.table_schema = '%{database}'
270
+ AND t.table_name in (%{table_names})
270
271
  GROUP BY
271
- c.table_name
272
+ t.table_schema, t.table_name
272
273
  HAVING
273
274
  num_pk = 0;
274
275
  EOT
@@ -306,6 +307,22 @@ EOT
306
307
  end
307
308
  end
308
309
 
310
+ class RdsMasterStatusChecker < MysqlCompatibilityChecker
311
+ BINLOG_RETENTION_HOURS = NonRdsRetentionChecker::BINLOG_RETENTION_HOURS
312
+
313
+ def create_query(option = @option)
314
+ "show master status;"
315
+ end
316
+
317
+ # "show master status;" returns nothing if backup retention period is not set.
318
+ def check_result(result, option = @option)
319
+ if result.first.nil?
320
+ raise FlydataCore::MysqlCompatibilityError,
321
+ "Backup Retention Period must be set on your RDS console."
322
+ end
323
+ end
324
+ end
325
+
309
326
  class RdsRetentionChecker < MysqlCompatibilityChecker
310
327
  BINLOG_RETENTION_HOURS = NonRdsRetentionChecker::BINLOG_RETENTION_HOURS
311
328
 
@@ -0,0 +1,8 @@
1
+ module FlydataCore
2
+ module Mysql
3
+ module Ssl
4
+ # ssl cipher list not including DH algorithm
5
+ 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"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module FlydataCore
2
+ class StringUtils
3
+ def self.replace_invalid_utf8_char(str, replacement = '?')
4
+ str.encode("UTF-16BE",
5
+ invalid: :replace,
6
+ undef: :replace,
7
+ replace: replacement).encode("UTF-8")
8
+ end
9
+ end
10
+ end
@@ -346,6 +346,11 @@ EOS
346
346
  t = DateTime.strptime(value, "[%d/%b/%Y:%H:%M:%S %Z]")
347
347
  elsif time_match = TIME_REGEXP.match(value_str)
348
348
  t = convert_time_into_timestamp(time_match)
349
+ elsif /^(\d+)\.(\d+)$/ === value_str # epoch with fraction
350
+ epoch = $1
351
+ fraction = $2
352
+ t = DateTime.strptime(epoch, '%s')
353
+ t = DateTime.parse(t.strftime("%Y-%m-%dT%H:%M:%S.#{fraction}"))
349
354
  else
350
355
  t = DateTime.parse(convert_date(value_str))
351
356
  end
@@ -63,15 +63,16 @@ EOT
63
63
  subject { subject_object.create_query }
64
64
  it { is_expected.to eq <<EOT
65
65
  SELECT
66
- c.table_name as table_name,
67
- SUM(IF(c.column_key = 'PRI', 1, 0)) as num_pk
66
+ t.table_name,
67
+ SUM(IF(tc.constraint_type='PRIMARY KEY', 1, 0)) as num_pk
68
68
  FROM
69
- information_schema.columns c
69
+ information_schema.tables t
70
+ LEFT OUTER JOIN information_schema.table_constraints tc USING (table_schema, table_name)
70
71
  WHERE
71
- c.table_schema='test_db'
72
- AND c.table_name in ('table_1','table_2','table_3')
72
+ t.table_schema = 'test_db'
73
+ AND t.table_name in ('table_1','table_2','table_3')
73
74
  GROUP BY
74
- c.table_name
75
+ t.table_schema, t.table_name
75
76
  HAVING
76
77
  num_pk = 0;
77
78
  EOT
@@ -135,13 +136,12 @@ EOT
135
136
  {'Variable_name'=>'binlog_checksum','Value'=>'NONE'},
136
137
  {'Variable_name'=>'log_bin_use_v1_row_events','Value'=>'ON'},
137
138
  {'Variable_name'=>'log_slave_updates','Value'=>'ON'},
138
- {'Variable_name'=>'net_read_timeout','Value'=>600},
139
+ {'Variable_name'=>'net_read_timeout','Value'=>30},
139
140
  {'Variable_name'=>'net_write_timeout','Value'=>600},
140
- {'Variable_name'=>'wait_timeout','Value'=>30}
141
141
  ]
142
142
  end
143
143
  it do
144
- expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /binlog_format.*\n.*wait_timeout/)
144
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /binlog_format.*\n.*net_read_timeout/)
145
145
  end
146
146
  end
147
147
 
@@ -353,7 +353,45 @@ EOT
353
353
  ]
354
354
  end
355
355
  it { expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError,
356
- /^\[WARNING.*\n.*net_read_timeout.*\n.*wait_timeout/) }
356
+ /^\[WARNING.*\n.*net_read_timeout.*/) }
357
+ end
358
+ end
359
+ end
360
+
361
+ describe RdsMasterStatusChecker do
362
+ describe '#check_result' do
363
+ let(:subject_object) { described_class.new({}) }
364
+ let(:result) { [] }
365
+ subject { subject_object.check_result(result) }
366
+
367
+ context 'when result is empty' do
368
+ it do
369
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError)
370
+ end
371
+ end
372
+
373
+ context 'when result is not empty' do
374
+ =begin
375
+ mysql> show master status;
376
+ +----------------------------+----------+--------------+------------------+-------------------+
377
+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
378
+ +----------------------------+----------+--------------+------------------+-------------------+
379
+ | mysql-bin-changelog.026292 | 31300 | | | |
380
+ +----------------------------+----------+--------------+------------------+-------------------+
381
+ 1 row in set (0.00 sec)
382
+ =end
383
+ let(:result) do
384
+ {
385
+ 'File' => 'mysql-bin-changelog.026292',
386
+ 'Position' => '31300',
387
+ 'Binlog_Do_DB' => '',
388
+ 'Binlog_Ignore_DB' => '',
389
+ 'Executed_Gtid_Set' => '',
390
+ }
391
+ end
392
+ it do
393
+ expect{subject}.not_to raise_error
394
+ end
357
395
  end
358
396
  end
359
397
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'flydata-core/string_utils'
3
+
4
+ describe FlydataCore::StringUtils do
5
+ let(:str) { '' }
6
+ let(:expected_str) { str }
7
+
8
+ subject { described_class.replace_invalid_utf8_char(str) }
9
+
10
+ shared_examples 'return_expected_str' do
11
+ it { is_expected.to eq(expected_str) }
12
+ end
13
+
14
+ context 'with non-invalid char' do
15
+ context 'with ascii code str' do
16
+ let(:str) { 'abcdefg' }
17
+ it_behaves_like 'return_expected_str'
18
+ end
19
+
20
+ context 'with empty str' do
21
+ let(:str) { '' }
22
+ it_behaves_like 'return_expected_str'
23
+ end
24
+
25
+ context 'with UTF-8 char' do
26
+ let(:str) { 'あいうえお' }
27
+ it_behaves_like 'return_expected_str'
28
+ end
29
+ end
30
+
31
+ context 'with invalid char' do
32
+ context 'with ascii and invalid str' do
33
+ let(:str) { "abc\255def" }
34
+ let(:expected_str) { 'abc?def' }
35
+ it_behaves_like 'return_expected_str'
36
+ end
37
+
38
+ context 'with UTF-8 and invalid str' do
39
+ let(:str) { "あいう\255えお" }
40
+ let(:expected_str) { "あいう?えお" }
41
+ it_behaves_like 'return_expected_str'
42
+ end
43
+ end
44
+ end
@@ -654,6 +654,11 @@ EOS
654
654
  let(:value) { 1400705967 }
655
655
  it { is_expected.to eq('2014-05-21 20:59:27.000000') }
656
656
  end
657
+
658
+ context 'with millisec' do
659
+ let(:value) { 1400705967.283928 }
660
+ it { is_expected.to eq('2014-05-21 20:59:27.283928') }
661
+ end
657
662
  end
658
663
 
659
664
  context 'with all zero string' do
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.8 ruby lib
5
+ # stub: flydata 0.5.9 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "flydata"
9
- s.version = "0.5.8"
9
+ s.version = "0.5.9"
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-09-25"
14
+ s.date = "2015-10-02"
15
15
  s.description = "FlyData Agent"
16
16
  s.email = "sysadmin@flydata.com"
17
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -52,10 +52,12 @@ Gem::Specification.new do |s|
52
52
  "flydata-core/lib/flydata-core/mysql/command_generator.rb",
53
53
  "flydata-core/lib/flydata-core/mysql/compatibility_checker.rb",
54
54
  "flydata-core/lib/flydata-core/mysql/config.rb",
55
+ "flydata-core/lib/flydata-core/mysql/ssl.rb",
55
56
  "flydata-core/lib/flydata-core/option_validator.rb",
56
57
  "flydata-core/lib/flydata-core/query_job.rb",
57
58
  "flydata-core/lib/flydata-core/record/record.rb",
58
59
  "flydata-core/lib/flydata-core/redshift/string.rb",
60
+ "flydata-core/lib/flydata-core/string_utils.rb",
59
61
  "flydata-core/lib/flydata-core/table_def.rb",
60
62
  "flydata-core/lib/flydata-core/table_def/autoload_redshift_table_def.rb",
61
63
  "flydata-core/lib/flydata-core/table_def/mysql_table_def.rb",
@@ -72,6 +74,7 @@ Gem::Specification.new do |s|
72
74
  "flydata-core/spec/option_validator_spec.rb",
73
75
  "flydata-core/spec/redshift/string_spec.rb",
74
76
  "flydata-core/spec/spec_helper.rb",
77
+ "flydata-core/spec/string_utils_spec.rb",
75
78
  "flydata-core/spec/table_def/autoload_redshift_table_def_spec.rb",
76
79
  "flydata-core/spec/table_def/mysql_table_def_spec.rb",
77
80
  "flydata-core/spec/table_def/mysql_to_redshift_table_def_spec.rb",
@@ -250,7 +253,7 @@ Gem::Specification.new do |s|
250
253
  s.add_runtime_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
251
254
  s.add_runtime_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
252
255
  s.add_runtime_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
253
- s.add_runtime_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
256
+ s.add_runtime_dependency(%q<kodama>, [">= 0.1.8", "~> 0.1"])
254
257
  s.add_runtime_dependency(%q<serverengine>, ["~> 1.5"])
255
258
  s.add_development_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
256
259
  s.add_development_dependency(%q<rspec>, ["~> 3.0"])
@@ -274,7 +277,7 @@ Gem::Specification.new do |s|
274
277
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
275
278
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
276
279
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
277
- s.add_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
280
+ s.add_dependency(%q<kodama>, [">= 0.1.8", "~> 0.1"])
278
281
  s.add_dependency(%q<serverengine>, ["~> 1.5"])
279
282
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
280
283
  s.add_dependency(%q<rspec>, ["~> 3.0"])
@@ -299,7 +302,7 @@ Gem::Specification.new do |s|
299
302
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
300
303
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
301
304
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
302
- s.add_dependency(%q<kodama>, [">= 0.1.7", "~> 0.1.2"])
305
+ s.add_dependency(%q<kodama>, [">= 0.1.8", "~> 0.1"])
303
306
  s.add_dependency(%q<serverengine>, ["~> 1.5"])
304
307
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
305
308
  s.add_dependency(%q<rspec>, ["~> 3.0"])
data/lib/flydata.rb CHANGED
@@ -29,7 +29,7 @@ module Flydata
29
29
  FLYDATA_SERVERINFO = File.join(FLYDATA_GEM_BIN, 'serverinfo')
30
30
  FLYDATA_LOG = File.join(FLYDATA_HOME, 'flydata.log')
31
31
  FLYDATA_CONF = File.join(FLYDATA_HOME, 'flydata.conf')
32
- FLYDATA_LOCK = File.join(FLYDATA_HOME, 'flydata.lock')
32
+ FLYDATA_LOCK = File.join(FLYDATA_HOME, 'flydata_lock.pid')
33
33
  FLYDATA_HELPER_HOME = File.join(FLYDATA_HOME, 'helper')
34
34
 
35
35
  VERSION_PATH = File.join(FLYDATA_GEM_HOME, 'VERSION')
@@ -39,19 +39,19 @@ module Flydata
39
39
  create_helper_dirs
40
40
  end
41
41
 
42
- def start
42
+ def start(options = {})
43
43
  if running?
44
- log_info_stdout("Helper is already running.")
44
+ log_info_stdout("Helper is already running.", {}, options)
45
45
  else
46
46
  raw_start
47
47
  end
48
48
  end
49
49
 
50
- def stop
50
+ def stop(options = {})
51
51
  if running?
52
52
  run_command(stop_cmd)
53
53
  else
54
- log_info_stdout("Helper is not running.")
54
+ log_info_stdout("Helper is not running.", {}, options)
55
55
  end
56
56
  end
57
57
 
@@ -63,9 +63,9 @@ module Flydata
63
63
  end
64
64
  end
65
65
 
66
- def restart
66
+ def restart(options = {})
67
67
  if running?
68
- log_info_stdout("Restarting Helper.")
68
+ log_info_stdout("Restarting Helper.", {}, options)
69
69
  run_command(kill_hup_cmd)
70
70
  else
71
71
  raw_start
@@ -16,7 +16,7 @@ module Flydata
16
16
  sender.restart
17
17
  unless opts.skip_helper?
18
18
  helper = Flydata::Command::Helper.new
19
- helper.restart
19
+ helper.restart(quiet: true)
20
20
  end
21
21
  end
22
22
  run_exclusive :run
@@ -141,6 +141,16 @@ EOF
141
141
  File.exists?(FLYDATA_LOCK)
142
142
  end
143
143
 
144
+ def wait_until_server_ready(options = {})
145
+ retry_count = 60 # 60 x 30(sec) = 1800(sec) = 30(min)
146
+ 1.upto(retry_count) do |i|
147
+ return true if server_ready?
148
+ log_info_stdout("Waiting for the server side to become active... (#{i})") unless options[:quiet]
149
+ Kernel.sleep 30
150
+ end
151
+ false
152
+ end
153
+
144
154
  private
145
155
  # Return a list of fluentd parent processes run by the same user for the
146
156
  # same flydata.pid file but not the process managed by the file itself.
@@ -163,15 +173,6 @@ EOF
163
173
  orphan_pids
164
174
  end
165
175
 
166
- def wait_until_server_ready(options = {})
167
- retry_count = 10
168
- 1.upto(retry_count) do |i|
169
- return true if server_ready?
170
- log_info_stdout("Waiting for the server side to become active... (#{i}/#{retry_count})") unless options[:quiet]
171
- Kernel.sleep 30
172
- end
173
- false
174
- end
175
176
  def wait_until_client_ready(options = {})
176
177
  retry_count = 10
177
178
  1.upto(retry_count) do |i|
@@ -17,8 +17,8 @@ module Flydata
17
17
  helper_opts = Flydata::Command::Helper.slop_start
18
18
  helper_opts.parse!(args)
19
19
  helper = Flydata::Command::Helper.new(helper_opts)
20
- helper.stop # kill existing helper process (if any) and start
21
- helper.start
20
+ helper.stop(quiet: true) # kill existing helper process (if any) and start
21
+ helper.start(quiet: true)
22
22
  end
23
23
  end
24
24
  run_exclusive :run
@@ -15,7 +15,7 @@ module Flydata
15
15
  sender.stop
16
16
  if opts.full?
17
17
  helper = Flydata::Command::Helper.new
18
- helper.stop
18
+ helper.stop(quiet: true)
19
19
  end
20
20
  end
21
21
  run_exclusive :run
@@ -526,6 +526,10 @@ EOS
526
526
  # Initial sync
527
527
 
528
528
  def handle_mysql_sync(tables = nil, options = {})
529
+ unless Flydata::Command::Sender.new.wait_until_server_ready
530
+ raise Timeout::Error, "Timed out to wait for the server side to become active. Pleae try again later."
531
+ end
532
+
529
533
  de = data_entry
530
534
 
531
535
  # Setup instance variables
@@ -11,16 +11,16 @@ module Flydata
11
11
  $stderr.puts raw_msg if options[:stderr]
12
12
  end
13
13
 
14
- def log_info_stdout(message, log_params = {})
15
- log_info(message, log_params, {stdout: true})
14
+ def log_info_stdout(message, log_params = {}, options = {})
15
+ log_info(message, log_params, {stdout: !options[:quiet]})
16
16
  end
17
17
 
18
- def log_warn_stderr(message, log_params = {})
19
- log_warn(message, log_params, {stderr: true})
18
+ def log_warn_stderr(message, log_params = {}, options = {})
19
+ log_warn(message, log_params, {stderr: !options[:quiet]})
20
20
  end
21
21
 
22
- def log_error_stderr(message, log_params = {})
23
- log_error(message, log_params, {stderr: true})
22
+ def log_error_stderr(message, log_params = {}, options = {})
23
+ log_error(message, log_params, {stderr: !options[:quiet]})
24
24
  end
25
25
  end
26
26
  end
@@ -119,8 +119,14 @@ module Flydata
119
119
  FlydataCore::Mysql::RequiredBinlogParameterChecker.new(@db_opts).do_check
120
120
  end
121
121
 
122
+ def check_rds_master_status
123
+ if is_rds?
124
+ FlydataCore::Mysql::RdsMasterStatusChecker.new(@db_opts).do_check
125
+ end
126
+ end
127
+
122
128
  def check_mysql_binlog_retention
123
- if is_rds?(@db_opts[:host])
129
+ if is_rds?
124
130
  run_rds_retention_check
125
131
  else
126
132
  run_mysql_retention_check
@@ -171,7 +177,7 @@ module Flydata
171
177
  end
172
178
  end
173
179
 
174
- def is_rds?(hostname)
180
+ def is_rds?(hostname = @db_opts[:host])
175
181
  hostname.match(/rds.amazonaws.com$/) != nil
176
182
  end
177
183
  end
@@ -18,6 +18,7 @@ require 'flydata/fluent-plugins/idle_event_detector'
18
18
  require 'flydata/fluent-plugins/mysql/table_meta'
19
19
  require 'flydata/mysql/table_ddl'
20
20
  require 'flydata-core/fluent/config_helper'
21
+ require 'flydata-core/mysql/ssl'
21
22
 
22
23
  #Monkey-patch fluentd class (EngineClass) to support shutdown for input plugin.
23
24
  #This will be called when USR1 signal is received
@@ -72,8 +73,7 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
72
73
  # Supported ssl cipher list for mysql(openssl)
73
74
  # https://dev.mysql.com/doc/refman/5.6/en/ssl-options.html
74
75
 
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
76
+ config_param :secondary_ssl_cipher, :string, :default => FlydataCore::Mysql::Ssl::NON_DH_SSL_CIPHER
77
77
 
78
78
  def configure(conf)
79
79
  super
@@ -164,7 +164,6 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
164
164
  positions_path = @context.sync_fm.table_positions_dir_path
165
165
  Dir.mkdir positions_path unless File.exists? positions_path
166
166
 
167
- File.open(@lock_file, "w") {|f| f.write(Process.pid)}
168
167
  rescue Binlog::Error
169
168
  if (/basic_string::_M_replace_aux/ === $!.to_s)
170
169
  # TODO Fix the root cause in mysql-replication-listener
@@ -193,33 +192,41 @@ EOS
193
192
 
194
193
  current_ssl_cipher = @ssl_cipher
195
194
  retried = false
195
+ transaction_broken = false
196
+ File.open(@lock_file, "w") {|f| f.write(Process.pid)}
196
197
  begin
197
- start_kodama(mysql_url) do |c|
198
- c.binlog_position_file = @position_file
199
- if @ssl_ca_path.to_s != '' && c.respond_to?(:ssl_ca=)
200
- $log.info "SSL is enabled. (ssl_ca: #{@ssl_ca_path})"
201
- c.ssl_ca = @ssl_ca_path
202
- unless current_ssl_cipher.to_s.empty?
203
- $log.info "SSL cipher is set. (ssl_cipher: #{current_ssl_cipher})"
204
- c.ssl_cipher = current_ssl_cipher
198
+ begin
199
+ start_kodama(mysql_url) do |c|
200
+ c.binlog_position_file = @position_file
201
+ if @ssl_ca_path.to_s != '' && c.respond_to?(:ssl_ca=)
202
+ $log.info "SSL is enabled. (ssl_ca: #{@ssl_ca_path})"
203
+ c.ssl_ca = @ssl_ca_path
204
+ unless current_ssl_cipher.to_s.empty?
205
+ $log.info "SSL cipher is set. (ssl_cipher: #{current_ssl_cipher})"
206
+ c.ssl_cipher = current_ssl_cipher
207
+ end
205
208
  end
206
- end
207
209
 
208
- if c.respond_to?(:sent_binlog_position_file=)
209
- $log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
210
- c.sent_binlog_position_file = @sent_position_file_path
211
- end
210
+ if c.respond_to?(:sent_binlog_position_file=)
211
+ $log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
212
+ c.sent_binlog_position_file = @sent_position_file_path
213
+ end
212
214
 
213
- $log.info("Binlog position - resume_pos:'#{IO.read(@position_file) rescue IOError}' " +
214
- "sent_pos:'#{IO.read(@sent_position_file_path) rescue IOError}'")
215
+ $log.info("Binlog position - resume_pos:'#{IO.read(@position_file) rescue IOError}' " +
216
+ "sent_pos:'#{IO.read(@sent_position_file_path) rescue IOError}'")
215
217
 
216
- c.connection_retry_limit = @retry_limit
217
- c.connection_retry_wait = @retry_wait
218
- c.log_level = @log_level.to_sym
219
- @listen_events.each do |event_type|
220
- $log.trace { "registered binlog event listener '#{event_type}'" }
221
- c.send("on_#{event_type}", &method(:event_listener))
218
+ c.connection_retry_limit = @retry_limit
219
+ c.connection_retry_wait = @retry_wait
220
+ c.log_level = @log_level.to_sym
221
+ @listen_events.each do |event_type|
222
+ $log.trace { "registered binlog event listener '#{event_type}'" }
223
+ c.send("on_#{event_type}", &method(:event_listener))
224
+ end
222
225
  end
226
+ rescue Kodama::TransactionError
227
+ $log.debug "TransactionError"
228
+ transaction_broken = true
229
+ raise
223
230
  end
224
231
  rescue Binlog::Error => e
225
232
  if /dh key too small/.match(e.to_s) && !retried && !@secondary_ssl_cipher.to_s.empty?
@@ -230,6 +237,12 @@ EOS
230
237
  else
231
238
  raise e
232
239
  end
240
+ ensure
241
+ if !transaction_broken && # leave the lock file when a transaction is broken
242
+ File.exists?(@lock_file) &&
243
+ Process.pid == File.open(@lock_file, "r") {|f| f.read}.to_i
244
+ File.delete(@lock_file)
245
+ end
233
246
  end
234
247
 
235
248
  rescue => e
@@ -259,18 +272,12 @@ EOS
259
272
  rescue Exception => e
260
273
  position = @binlog_position_file.read
261
274
  $log.error "error occured while processing #{event.event_type} event at #{position}\n#{e.message}\n#{$!.backtrace.join("\n")}"
262
- # Not reraising a StandardError because the underlying code can't handle an error well.
263
- raise unless e.kind_of?(StandardError)
275
+ raise
264
276
  end
265
277
 
266
278
  def shutdown
267
279
  return if instance_variable_defined? :@abort
268
280
 
269
- if File.exists?(@lock_file) &&
270
- Process.pid == File.open(@lock_file, "r") {|f| f.read}.to_i
271
- File.delete(@lock_file)
272
- end
273
-
274
281
  @idle_event_detector.stop
275
282
  if @thread and @thread.alive?
276
283
  $log.info "Requesting stop Kodama"
@@ -123,17 +123,13 @@ module Flydata
123
123
  end
124
124
 
125
125
  def sent_binlog_path(master_binlog_path = binlog_path)
126
- unless master_binlog_path && master_binlog_path.end_with?('binlog.pos')
127
- raise ArgumentError.new("Invalid binlog path. binlog path needs to end with 'binlog.pos'")
128
- end
126
+ validate_master_binlog_path(master_binlog_path)
129
127
  "#{master_binlog_path[0..-5]}.sent.pos"
130
128
  end
131
129
 
132
130
  # ssl_ca file path
133
131
  def ssl_ca_path(master_binlog_path = binlog_path)
134
- unless master_binlog_path && master_binlog_path.end_with?('binlog.pos')
135
- raise ArgumentError.new("Invalid binlog path. binlog path needs to end with 'binlog.pos'")
136
- end
132
+ validate_master_binlog_path(master_binlog_path)
137
133
  # <data-entry-name>.ssl_ca.pem
138
134
  "#{master_binlog_path[0..-12]}.ssl_ca.pem"
139
135
  end
@@ -144,6 +140,19 @@ module Flydata
144
140
  end
145
141
  end
146
142
 
143
+ # ssl_cipher file path
144
+ def ssl_cipher_path(master_binlog_path = binlog_path)
145
+ validate_master_binlog_path(master_binlog_path)
146
+ # <data-entry-name>.ssl_cipher
147
+ "#{master_binlog_path[0..-12]}.ssl_cipher"
148
+ end
149
+
150
+ def save_ssl_cipher(ssl_cipher_content, path = ssl_cipher_path)
151
+ File.open(path, 'w') do |f|
152
+ f.write(ssl_cipher_content)
153
+ end
154
+ end
155
+
147
156
  # table files
148
157
  def reset_table_position_files(tables)
149
158
  tables.each do |table_name|
@@ -340,7 +349,9 @@ module Flydata
340
349
  FileUtils.mkdir_p(backup_dir) unless Dir.exists?(backup_dir)
341
350
  dest_dir = File.join(backup_dir, Time.now.strftime("%Y%m%d%H%M%S"))
342
351
  FileUtils.mkdir(dest_dir)
343
- FileUtils.mv(Dir.glob("#{dump_dir}/*"), dest_dir)
352
+ %w(info pos stats mysql_table).each do |ext|
353
+ FileUtils.mv(Dir.glob("#{dump_dir}/*.#{ext}"), dest_dir)
354
+ end
344
355
  end
345
356
 
346
357
  def backup_dir
@@ -405,5 +416,11 @@ module Flydata
405
416
  FileUtils.mkdir_p(dump_dir) unless Dir.exists?(dump_dir)
406
417
  dump_dir
407
418
  end
419
+
420
+ def validate_master_binlog_path(master_binlog_path)
421
+ unless master_binlog_path && master_binlog_path.end_with?('binlog.pos')
422
+ raise ArgumentError.new("Invalid binlog path. binlog path needs to end with 'binlog.pos'")
423
+ end
424
+ end
408
425
  end
409
426
  end
@@ -272,5 +272,42 @@ module Flydata
272
272
  it { expect{subject}.to_not raise_error }
273
273
  end
274
274
  end
275
+
276
+ describe "#check_rds_master_status" do
277
+ let(:client) { double('client') }
278
+ let(:subject_object) { MysqlCompatibilityCheck.new(default_data_port, default_mysql_cred) }
279
+ subject { subject_object.check_rds_master_status }
280
+ let(:master_status) { [] }
281
+
282
+ before do
283
+ allow(Mysql2::Client).to receive(:new).and_return(client)
284
+ allow(client).to receive(:query).and_return(master_status)
285
+ allow(client).to receive(:close)
286
+ end
287
+
288
+ context 'when host is rds' do
289
+ before do
290
+ default_mysql_cred['host'] = 'rdrss.xxyyzz.rds.amazonaws.com'
291
+ end
292
+
293
+ context "where backup retention period is not set" do
294
+ let(:master_status) { [] }
295
+ it { expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /Backup Retention Period/) }
296
+ end
297
+
298
+ context "where backup retention period is set" do
299
+ let(:master_status) do
300
+ [{
301
+ 'File' => 'mysql-bin-changelog.026292',
302
+ 'Position' => '31300',
303
+ 'Binlog_Do_DB' => '',
304
+ 'Binlog_Ignore_DB' => '',
305
+ 'Executed_Gtid_Set' => '',
306
+ }]
307
+ end
308
+ it { expect{subject}.not_to raise_error }
309
+ end
310
+ end
311
+ end
275
312
  end
276
313
  end
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.8
4
+ version: 0.5.9
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-09-25 00:00:00.000000000 Z
15
+ date: 2015-10-02 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -248,20 +248,20 @@ dependencies:
248
248
  requirements:
249
249
  - - '>='
250
250
  - !ruby/object:Gem::Version
251
- version: 0.1.7
251
+ version: 0.1.8
252
252
  - - ~>
253
253
  - !ruby/object:Gem::Version
254
- version: 0.1.2
254
+ version: '0.1'
255
255
  type: :runtime
256
256
  prerelease: false
257
257
  version_requirements: !ruby/object:Gem::Requirement
258
258
  requirements:
259
259
  - - '>='
260
260
  - !ruby/object:Gem::Version
261
- version: 0.1.7
261
+ version: 0.1.8
262
262
  - - ~>
263
263
  - !ruby/object:Gem::Version
264
- version: 0.1.2
264
+ version: '0.1'
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: serverengine
267
267
  requirement: !ruby/object:Gem::Requirement
@@ -489,10 +489,12 @@ files:
489
489
  - flydata-core/lib/flydata-core/mysql/command_generator.rb
490
490
  - flydata-core/lib/flydata-core/mysql/compatibility_checker.rb
491
491
  - flydata-core/lib/flydata-core/mysql/config.rb
492
+ - flydata-core/lib/flydata-core/mysql/ssl.rb
492
493
  - flydata-core/lib/flydata-core/option_validator.rb
493
494
  - flydata-core/lib/flydata-core/query_job.rb
494
495
  - flydata-core/lib/flydata-core/record/record.rb
495
496
  - flydata-core/lib/flydata-core/redshift/string.rb
497
+ - flydata-core/lib/flydata-core/string_utils.rb
496
498
  - flydata-core/lib/flydata-core/table_def.rb
497
499
  - flydata-core/lib/flydata-core/table_def/autoload_redshift_table_def.rb
498
500
  - flydata-core/lib/flydata-core/table_def/mysql_table_def.rb
@@ -509,6 +511,7 @@ files:
509
511
  - flydata-core/spec/option_validator_spec.rb
510
512
  - flydata-core/spec/redshift/string_spec.rb
511
513
  - flydata-core/spec/spec_helper.rb
514
+ - flydata-core/spec/string_utils_spec.rb
512
515
  - flydata-core/spec/table_def/autoload_redshift_table_def_spec.rb
513
516
  - flydata-core/spec/table_def/mysql_table_def_spec.rb
514
517
  - flydata-core/spec/table_def/mysql_to_redshift_table_def_spec.rb