flydata 0.3.13 → 0.3.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 317626ac900b0a0adf96c84648e554f6d2e7436a
4
- data.tar.gz: e54dcf2b46068be7c27e3d6ce63c338d111e0c20
3
+ metadata.gz: de14c5ba0b4b0b3c1b98e93f9e41c59a32db18fd
4
+ data.tar.gz: 685e70c882291fe387d7aaf14657a879b8c1d73e
5
5
  SHA512:
6
- metadata.gz: 935c6cc893c91fba078e92306b88a06697195c3a21b5241f0d08936a9cfb8acdff7c9eb32febbdc5c77a04b5dbe9627c757cf123ceee0420ae29784e4e10e1b4
7
- data.tar.gz: 593a4ade45a37713981a11c5d98456eaaa04a592870cab4b2aff48a162e17d36c4780a138df5c38636d07bc9c3879d3ddde02e6331c94be916c62cc9b1d2f58a
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'
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.2'
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.2)
65
- ruby-binlog (>= 0.1.9)
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.16)
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.2)
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.2)
137
- mysql2 (~> 0.3, >= 0.3.11)
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.13
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.13 ruby lib
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.13"
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-09"
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.3"
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.11", "~> 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.2", "~> 0.1.2"])
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.11", "~> 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.2", "~> 0.1.2"])
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.11", "~> 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.2", "~> 0.1.2"])
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"])
@@ -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']}
@@ -5,6 +5,7 @@ module Flydata
5
5
  module Command
6
6
  class Status < Base
7
7
  def run
8
+ show_purpose_name
8
9
  sender = Flydata::Command::Sender.new
9
10
  sender.status
10
11
  end
@@ -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(host: @host, port: @port, username: @username, password: @password)} 2>/dev/null`
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
- :mysql_url, :database, :tables
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
- @mysql_url = opts[:mysql_url]
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(@mysql_url)
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)
@@ -76,6 +76,7 @@ module Fluent
76
76
  host: {},
77
77
  username: {},
78
78
  password: {encrypted: true},
79
+ ssl_ca_content: {},
79
80
  },
80
81
  }
81
82
 
@@ -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
- default_option = option[:no_default_option] ? nil : DEFAULT_MYSQL_CMD_OPTION
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
-
@@ -8,6 +8,7 @@ module Flydata
8
8
  let(:sender) { double("sender") }
9
9
 
10
10
  it do
11
+ expect(subject).to receive(:show_purpose_name)
11
12
  expect(Flydata::Command::Sender).to receive(:new).and_return(sender)
12
13
  expect(sender).to receive(:status)
13
14
  subject.run
@@ -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(:mysql_url) { double('mysql_url') }
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
- 'mysqldump -h test-host -P 3306 -utestuser -p"abc\\`def" --default-character-set=utf8 --protocol=tcp testdb'
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.13
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-09 00:00:00.000000000 Z
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.11
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.11
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.2
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.2
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.3
617
+ rubygems_version: 2.4.6
636
618
  signing_key:
637
619
  specification_version: 4
638
620
  summary: FlyData Agent