flydata 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/serverinfo +53 -0
- data/flydata.gemspec +5 -4
- data/lib/flydata/cli.rb +1 -0
- data/lib/flydata/command/sender.rb +2 -1
- data/lib/flydata/command/sync.rb +20 -18
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +8 -2
- data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +5 -1
- data/lib/flydata/fluent-plugins/mysql/context.rb +2 -2
- data/lib/flydata/fluent-plugins/preference.rb +1 -0
- data/spec/flydata/cli_spec.rb +3 -3
- data/spec/flydata/command/sender_spec.rb +6 -0
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +69 -0
- data/spec/spec_helper.rb +38 -0
- data/tmpl/redshift_mysql_data_entry.conf.tmpl +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a3fbdc5a0e42708b1dd6f173c366810e4f58892
|
4
|
+
data.tar.gz: 85a647490961e9b85baea5524b9c0f4f395a9d64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 200c29e2a64610cd4561ae127365f934b9cef0ef9dad264fed54d191bc3ec779eb22fe507d4d55c6373928a560c807dafa0cc0883243b0865723a62649349d40
|
7
|
+
data.tar.gz: 2a5b4a1e246b448e6fffe76c6fff8416298d22c4e46719109d6d9c2fca99c3f2ddb1cc3e70cb5b5bf9afbac388c3048b1b840c05952bcc0ab9e14a53c89b901f
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/bin/serverinfo
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
detect_system() {
|
3
|
+
# refer to https://github.com/wayneeseguin/rvm/blob/master/scripts/functions/utility_system
|
4
|
+
unset _system_info _system_lib_type
|
5
|
+
export _system_info _system_lib_type
|
6
|
+
_system_info="$(command uname -a)"
|
7
|
+
_system_lib_type="unknown"
|
8
|
+
case "$(command uname)" in
|
9
|
+
(Linux|GNU*)
|
10
|
+
if [[ -f /etc/lsb-release ]]; then
|
11
|
+
_system_lib_type="debian"
|
12
|
+
elif [[ -f /etc/debian_version ]]; then
|
13
|
+
_system_lib_type="debian"
|
14
|
+
elif [[ -f /etc/os-release ]]; then
|
15
|
+
_system_lib_type="debian"
|
16
|
+
elif [[ -f /etc/system-release ]]; then
|
17
|
+
_system_lib_type="centos"
|
18
|
+
elif [[ -f /etc/centos-release ]]; then
|
19
|
+
_system_lib_type="centos"
|
20
|
+
elif [[ -f /etc/redhat-release ]]; then
|
21
|
+
_system_lib_type="centos"
|
22
|
+
fi
|
23
|
+
;;
|
24
|
+
#(Darwin)
|
25
|
+
# _system_lib_type="osx"
|
26
|
+
# ;;
|
27
|
+
(*)
|
28
|
+
;;
|
29
|
+
esac
|
30
|
+
}
|
31
|
+
|
32
|
+
log_server_details()
|
33
|
+
{
|
34
|
+
echo "Logging ip address"
|
35
|
+
ip addr show
|
36
|
+
|
37
|
+
echo "Logging ulimit and uname"
|
38
|
+
ulimit -a
|
39
|
+
uname -a
|
40
|
+
|
41
|
+
echo "Logging repo details"
|
42
|
+
detect_system
|
43
|
+
if [ "${_system_lib_type}" = "debian" ]; then
|
44
|
+
grep -RoPish --include="*.list" "(?<=^deb\s).*?(?=#|$)" /etc/apt
|
45
|
+
else
|
46
|
+
yum repolist all
|
47
|
+
fi
|
48
|
+
|
49
|
+
echo "Logging release details"
|
50
|
+
cat /etc/*-release
|
51
|
+
}
|
52
|
+
|
53
|
+
log_server_details
|
data/flydata.gemspec
CHANGED
@@ -2,19 +2,19 @@
|
|
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.2.
|
5
|
+
# stub: flydata 0.2.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "flydata"
|
9
|
-
s.version = "0.2.
|
9
|
+
s.version = "0.2.2"
|
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"]
|
14
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-09-12"
|
15
15
|
s.description = "FlyData Command Line Interface"
|
16
16
|
s.email = "sysadmin@flydata.co"
|
17
|
-
s.executables = ["fdmysqldump", "flydata"]
|
17
|
+
s.executables = ["fdmysqldump", "flydata", "serverinfo"]
|
18
18
|
s.files = [
|
19
19
|
".gitignore",
|
20
20
|
".rspec",
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"VERSION",
|
25
25
|
"bin/fdmysqldump",
|
26
26
|
"bin/flydata",
|
27
|
+
"bin/serverinfo",
|
27
28
|
"flydata.gemspec",
|
28
29
|
"lib/fly_data_model.rb",
|
29
30
|
"lib/flydata.rb",
|
data/lib/flydata/cli.rb
CHANGED
@@ -6,7 +6,7 @@ module Flydata
|
|
6
6
|
on 'n', 'no-daemon', 'Start FlyData agent as a regular program'
|
7
7
|
end
|
8
8
|
end
|
9
|
-
def start(options_or_show_final_message = {show_final_message: true}) # For backward compatibility. Use only as options going forward
|
9
|
+
def start(options_or_show_final_message = {show_final_message: true}) # For backward compatibility. Use only as options going forward
|
10
10
|
if options_or_show_final_message.kind_of? Hash
|
11
11
|
options = options_or_show_final_message
|
12
12
|
else
|
@@ -23,6 +23,7 @@ module Flydata
|
|
23
23
|
# Start sender(fluentd) process
|
24
24
|
say('Starting sender process.') unless options[:quiet]
|
25
25
|
Dir.chdir(FLYDATA_HOME){
|
26
|
+
Kernel.system("bash #{File.dirname(__FILE__)}/../../../bin/serverinfo", :out => ["#{FLYDATA_HOME}/flydata.log",'a'], :err => ["#{FLYDATA_HOME}/flydata.log",'a'])
|
26
27
|
daemon_option = opts.no_daemon? ? "" : "-d #{FLYDATA_HOME}/flydata.pid"
|
27
28
|
Kernel.system("fluentd #{daemon_option} -l #{FLYDATA_HOME}/flydata.log -c #{FLYDATA_HOME}/flydata.conf -p #{File.dirname(__FILE__)}/../fluent-plugins")
|
28
29
|
}
|
data/lib/flydata/command/sync.rb
CHANGED
@@ -35,16 +35,10 @@ module Flydata
|
|
35
35
|
end
|
36
36
|
exit 1
|
37
37
|
end
|
38
|
-
de =
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
de = load_sync_info(override_tables(de, tables))
|
43
|
-
flush_buffer_and_stop unless de['mysql_data_entry_preference']['initial_sync']
|
44
|
-
sync_mysql_to_redshift(de)
|
45
|
-
else
|
46
|
-
raise "No supported data entry. Only mysql-redshift sync is supported."
|
47
|
-
end
|
38
|
+
de = retrieve_data_entry
|
39
|
+
de = load_sync_info(override_tables(de, tables))
|
40
|
+
flush_buffer_and_stop unless de['mysql_data_entry_preference']['initial_sync']
|
41
|
+
sync_mysql_to_redshift(de)
|
48
42
|
end
|
49
43
|
|
50
44
|
def flush
|
@@ -65,7 +59,7 @@ module Flydata
|
|
65
59
|
sender.flush_client_buffer # TODO We should rather delete buffer files
|
66
60
|
sender.stop
|
67
61
|
|
68
|
-
de =
|
62
|
+
de = retrieve_data_entry
|
69
63
|
wait_for_server_buffer
|
70
64
|
cleanup_sync_server(de, tables) unless opts.client?
|
71
65
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
|
@@ -114,7 +108,7 @@ module Flydata
|
|
114
108
|
end
|
115
109
|
|
116
110
|
def check
|
117
|
-
de =
|
111
|
+
de = retrieve_data_entry
|
118
112
|
retry_on(RestClient::Exception) do
|
119
113
|
status = do_check(de)
|
120
114
|
if status['complete']
|
@@ -127,7 +121,7 @@ module Flydata
|
|
127
121
|
|
128
122
|
# skip initial sync
|
129
123
|
def skip
|
130
|
-
de =
|
124
|
+
de = retrieve_data_entry
|
131
125
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
|
132
126
|
binlog_path = sync_fm.binlog_path
|
133
127
|
`touch #{binlog_path}`
|
@@ -137,20 +131,28 @@ module Flydata
|
|
137
131
|
end
|
138
132
|
|
139
133
|
def generate_table_ddl(*tables)
|
140
|
-
de =
|
134
|
+
de = retrieve_data_entry
|
141
135
|
Flydata::Mysql::CompatibilityCheck.new(de['mysql_data_entry_preference']).check
|
136
|
+
do_generate_table_ddl(override_tables(de, tables))
|
137
|
+
end
|
142
138
|
|
139
|
+
private
|
140
|
+
|
141
|
+
def retrieve_data_entry
|
142
|
+
de = retrieve_data_entries.first
|
143
143
|
raise "There are no data entry." unless de
|
144
144
|
case de['type']
|
145
145
|
when 'RedshiftMysqlDataEntry'
|
146
|
-
|
146
|
+
mp = de['mysql_data_entry_preference']
|
147
|
+
if mp['tables_append_only']
|
148
|
+
mp['tables'] = (mp['tables'].split(",") + mp['tables_append_only'].split(",")).uniq.join(",")
|
149
|
+
end
|
147
150
|
else
|
148
151
|
raise "No supported data entry. Only mysql-redshift sync is supported."
|
149
152
|
end
|
153
|
+
de
|
150
154
|
end
|
151
155
|
|
152
|
-
private
|
153
|
-
|
154
156
|
def cleanup_sync_server(de, tables = [])
|
155
157
|
puts "Cleaning the server"
|
156
158
|
flydata.data_entry.cleanup_sync(de['id'], tables)
|
@@ -412,7 +414,7 @@ What's next?
|
|
412
414
|
Thank you for using FlyData!
|
413
415
|
EOM
|
414
416
|
def complete
|
415
|
-
de = load_sync_info(
|
417
|
+
de = load_sync_info(retrieve_data_entry)
|
416
418
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
|
417
419
|
info = sync_fm.load_dump_pos
|
418
420
|
if info[:status] == STATUS_COMPLETE
|
@@ -47,6 +47,7 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
47
47
|
|
48
48
|
config_param :database, :string
|
49
49
|
config_param :tables, :string
|
50
|
+
config_param :tables_append_only, :string
|
50
51
|
|
51
52
|
def configure(conf)
|
52
53
|
super
|
@@ -55,13 +56,18 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
55
56
|
raise "No position file(#{@position_file}). Initial synchronization is required before starting."
|
56
57
|
end
|
57
58
|
load_custom_conf
|
58
|
-
$log.info "mysql host:\"#{@host}\" username:\"#{@username}\" database:\"#{@database}\" tables:\"#{@tables}\""
|
59
|
+
$log.info "mysql host:\"#{@host}\" username:\"#{@username}\" database:\"#{@database}\" tables:\"#{@tables}\" tables_append_only:\"#{tables_append_only}\""
|
59
60
|
@tables = @tables.split(/,\s*/)
|
61
|
+
@omit_events = Hash.new
|
62
|
+
@tables_append_only.split(/,\s*/).each do |table|
|
63
|
+
@tables << table unless @tables.include?(table)
|
64
|
+
@omit_events[table] = [:delete]
|
65
|
+
end
|
60
66
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(nil) # Passing nil for data_entry as this class does not use methods which require data_entry
|
61
67
|
|
62
68
|
@context = Mysql::Context.new(
|
63
69
|
database: @database, tables: @tables,
|
64
|
-
tag: @tag, sync_fm: sync_fm
|
70
|
+
tag: @tag, sync_fm: sync_fm, omit_events: @omit_events
|
65
71
|
)
|
66
72
|
@record_dispatcher = Mysql::FlydataBinlogRecordDispatcher.new(@context)
|
67
73
|
end
|
@@ -50,6 +50,10 @@ module Mysql
|
|
50
50
|
acceptable
|
51
51
|
end
|
52
52
|
|
53
|
+
def acceptable_event?(type, table)
|
54
|
+
@context.omit_events[table].nil? || !@context.omit_events[table].include?(type)
|
55
|
+
end
|
56
|
+
|
53
57
|
def emit_record(type, record, opt = {})
|
54
58
|
return unless acceptable_db?(record)
|
55
59
|
return unless record["table_name"].nil? or acceptable_table?(record, record["table_name"])
|
@@ -62,7 +66,7 @@ module Mysql
|
|
62
66
|
|
63
67
|
table = records.first[TABLE_NAME] || record['table_name']
|
64
68
|
raise "Missing table name. #{record}" if table.to_s.empty?
|
65
|
-
return unless acceptable_table?(record, table)
|
69
|
+
return unless acceptable_table?(record, table) && acceptable_event?(type, table)
|
66
70
|
|
67
71
|
table_rev = @context.sync_fm.table_rev(table)
|
68
72
|
position = record['next_position'] - record['event_length']
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Mysql
|
2
2
|
class Context
|
3
3
|
MANDATORY_OPTS = [
|
4
|
-
:database, :tables, :tag, :sync_fm,
|
4
|
+
:database, :tables, :tag, :sync_fm, :omit_events
|
5
5
|
]
|
6
6
|
OPTIONAL_OPTS = [
|
7
|
-
:current_binlog_file
|
7
|
+
:current_binlog_file
|
8
8
|
]
|
9
9
|
|
10
10
|
(MANDATORY_OPTS + OPTIONAL_OPTS).each do |opt|
|
data/spec/flydata/cli_spec.rb
CHANGED
@@ -20,7 +20,7 @@ module Flydata
|
|
20
20
|
expect(a.to_hash).to be_empty
|
21
21
|
}.and_return(command_obj)
|
22
22
|
expect(command_obj).to receive(:run)
|
23
|
-
|
23
|
+
|
24
24
|
subject.run
|
25
25
|
end
|
26
26
|
end
|
@@ -30,7 +30,7 @@ module Flydata
|
|
30
30
|
expect(subject).to receive(:puts).with('! Unknown options -a, --host-name').once
|
31
31
|
allow(subject).to receive(:puts)
|
32
32
|
|
33
|
-
subject.run
|
33
|
+
expect{ subject.run }.to terminate.with_code(1)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
context 'with arguments' do
|
@@ -65,7 +65,7 @@ module Flydata
|
|
65
65
|
expect(subject).to receive(:puts).with('! Unknown options -a, --host-name').once
|
66
66
|
allow(subject).to receive(:puts)
|
67
67
|
|
68
|
-
subject.run
|
68
|
+
expect{ subject.run }.to terminate.with_code(1)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -21,6 +21,8 @@ module Flydata
|
|
21
21
|
let(:args) { [] }
|
22
22
|
it "starts fluend with daemon option" do
|
23
23
|
expect(Kernel).to receive(:system).with( Regexp.new(
|
24
|
+
"bash .+/../../../bin/serverinfo"), :out => [Regexp.new(".+/flydata.log"),'a'], :err => [Regexp.new(".+/flydata.log"),'a'])
|
25
|
+
expect(Kernel).to receive(:system).with( Regexp.new(
|
24
26
|
"fluentd -d .+/flydata.pid -l .+/flydata.log -c .+/flydata.conf -p .+/\.\./fluent-plugins"))
|
25
27
|
subject.start(false)
|
26
28
|
end
|
@@ -28,6 +30,8 @@ module Flydata
|
|
28
30
|
context "as regular process" do
|
29
31
|
let(:args) { ["-n"] }
|
30
32
|
it "starts fluentd with no daemon option" do
|
33
|
+
expect(Kernel).to receive(:system).with( Regexp.new(
|
34
|
+
"bash .+/../../../bin/serverinfo"), :out => [Regexp.new(".+/flydata.log"),'a'], :err => [Regexp.new(".+/flydata.log"),'a'])
|
31
35
|
expect(Kernel).to receive(:system).with(Regexp.new(
|
32
36
|
"fluentd -l .+/flydata.log -c .+/flydata.conf -p .+/\.\./fluent-plugins"))
|
33
37
|
subject.start(false)
|
@@ -36,6 +40,8 @@ module Flydata
|
|
36
40
|
context "as regular process with long option" do
|
37
41
|
let(:args) { ["--no-daemon"] }
|
38
42
|
it "starts fluentd with no daemon option" do
|
43
|
+
expect(Kernel).to receive(:system).with( Regexp.new(
|
44
|
+
"bash .+/../../../bin/serverinfo"), :out => [Regexp.new(".+/flydata.log"),'a'], :err => [Regexp.new(".+/flydata.log"),'a'])
|
39
45
|
expect(Kernel).to receive(:system).with(Regexp.new(
|
40
46
|
"fluentd -l .+/flydata.log -c .+/flydata.conf -p .+/\.\./fluent-plugins"))
|
41
47
|
subject.start(false)
|
@@ -18,10 +18,27 @@ module Fluent
|
|
18
18
|
TEST_POSITION_FILE = "test_position.log"
|
19
19
|
TEST_REVISION_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.rev")
|
20
20
|
TEST_TIMESTAMP = 1389214083
|
21
|
+
TEST_TABLE_APPEND_ONLY = "test_table_4"
|
22
|
+
TEST_SEQUENCE_FILE_1 = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE_APPEND_ONLY}.pos")
|
21
23
|
TEST_CONFIG = <<EOT
|
22
24
|
tag #{TEST_TAG}
|
23
25
|
database #{TEST_DB}
|
24
26
|
tables #{TEST_TABLES}
|
27
|
+
tables_append_only
|
28
|
+
position_file #{TEST_POSITION_FILE}
|
29
|
+
EOT
|
30
|
+
TEST_TABLES_APPEND_ONLY_CONFIG = <<EOT
|
31
|
+
tag #{TEST_TAG}
|
32
|
+
database #{TEST_DB}
|
33
|
+
tables #{TEST_TABLES}
|
34
|
+
tables_append_only #{TEST_TABLE_APPEND_ONLY}
|
35
|
+
position_file #{TEST_POSITION_FILE}
|
36
|
+
EOT
|
37
|
+
TEST_TABLES_DUPLICATE_CONFIG = <<EOT
|
38
|
+
tag #{TEST_TAG}
|
39
|
+
database #{TEST_DB}
|
40
|
+
tables #{TEST_TABLES},#{TEST_TABLE_APPEND_ONLY}
|
41
|
+
tables_append_only #{TEST_TABLE_APPEND_ONLY}
|
25
42
|
position_file #{TEST_POSITION_FILE}
|
26
43
|
EOT
|
27
44
|
|
@@ -189,11 +206,13 @@ EOT
|
|
189
206
|
def setup_initial_flydata_files
|
190
207
|
%w(positions dump conf).each{|f| FileUtils.mkdir_p(File.join(FLYDATA_HOME, f))}
|
191
208
|
create_file(TEST_SEQUENCE_FILE, TEST_SEQUENCE_NUM.to_s)
|
209
|
+
create_file(TEST_SEQUENCE_FILE_1, TEST_SEQUENCE_NUM.to_s)
|
192
210
|
end
|
193
211
|
|
194
212
|
def cleanup_flydata_files
|
195
213
|
%w(positions dump conf).each{|f| FileUtils.rm_rf(File.join(FLYDATA_HOME, f))}
|
196
214
|
delete_file(TEST_SEQUENCE_FILE)
|
215
|
+
delete_file(TEST_SEQUENCE_FILE_1)
|
197
216
|
end
|
198
217
|
|
199
218
|
before do
|
@@ -409,6 +428,56 @@ EOT
|
|
409
428
|
expect_no_emitted_record(event)
|
410
429
|
end
|
411
430
|
end
|
431
|
+
|
432
|
+
context 'for append only' do
|
433
|
+
shared_examples 'emits records correctly' do
|
434
|
+
it 'emits records when it receives an insert event for append only table' do
|
435
|
+
event = insert_event
|
436
|
+
event['table_name'] = TEST_TABLE_APPEND_ONLY
|
437
|
+
expect_emitted_records_with_rows(event, :insert, TEST_TABLE_APPEND_ONLY, 628, "mysql-bin.000048",
|
438
|
+
[{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
|
439
|
+
end
|
440
|
+
|
441
|
+
it 'does not emit a record when it receives a delete event for append only table' do
|
442
|
+
event = delete_event
|
443
|
+
event['table_name'] = TEST_TABLE_APPEND_ONLY
|
444
|
+
expect_no_emitted_record(event)
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'emits records when it receives an update event for append only table' do
|
448
|
+
event = update_event
|
449
|
+
event['table_name'] = TEST_TABLE_APPEND_ONLY
|
450
|
+
expect_emitted_records_with_rows(event, :update, TEST_TABLE_APPEND_ONLY, 2528, "mysql-bin.000048",
|
451
|
+
[{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
|
452
|
+
end
|
453
|
+
|
454
|
+
it 'emits a record when it receives a delete event for non-append only table' do
|
455
|
+
expect_emitted_records_with_rows(delete_event, :delete, TEST_TABLE, 5324, "mysql-bin.000048",
|
456
|
+
[{"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
|
457
|
+
end
|
458
|
+
|
459
|
+
it 'emits records when it receives an insert event for non-append only table' do
|
460
|
+
expect_emitted_records_with_rows(insert_event, :insert, TEST_TABLE, 628, "mysql-bin.000048",
|
461
|
+
[{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
context 'no duplicate entries in tables and tables_append_only' do
|
466
|
+
before do
|
467
|
+
Test.configure_plugin(plugin, TEST_TABLES_APPEND_ONLY_CONFIG)
|
468
|
+
plugin.event_listener(rotate_event)
|
469
|
+
end
|
470
|
+
include_examples 'emits records correctly'
|
471
|
+
end
|
472
|
+
|
473
|
+
context 'duplicate entries in tables and tables_append_only' do
|
474
|
+
before do
|
475
|
+
Test.configure_plugin(plugin, TEST_TABLES_DUPLICATE_CONFIG)
|
476
|
+
plugin.event_listener(rotate_event)
|
477
|
+
end
|
478
|
+
include_examples 'emits records correctly'
|
479
|
+
end
|
480
|
+
end
|
412
481
|
end
|
413
482
|
end
|
414
483
|
|
data/spec/spec_helper.rb
CHANGED
@@ -33,5 +33,43 @@ RSpec.configure do |config|
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# https://gist.github.com/stevenharman/2355172
|
39
|
+
RSpec::Matchers.define :terminate do |code|
|
40
|
+
actual = nil
|
41
|
+
|
42
|
+
def supports_block_expectations?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
match do |block|
|
47
|
+
begin
|
48
|
+
block.call
|
49
|
+
rescue SystemExit => e
|
50
|
+
actual = e.status
|
51
|
+
end
|
52
|
+
actual and actual == status_code
|
53
|
+
end
|
54
|
+
|
55
|
+
chain :with_code do |status_code|
|
56
|
+
@status_code = status_code
|
57
|
+
end
|
58
|
+
|
59
|
+
failure_message_for_should do |block|
|
60
|
+
"expected block to call exit(#{status_code}) but exit" +
|
61
|
+
(actual.nil? ? " not called" : "(#{actual}) was called")
|
62
|
+
end
|
63
|
+
|
64
|
+
failure_message_for_should_not do |block|
|
65
|
+
"expected block not to call exit(#{status_code})"
|
66
|
+
end
|
67
|
+
|
68
|
+
description do
|
69
|
+
"expect block to call exit(#{status_code})"
|
70
|
+
end
|
36
71
|
|
72
|
+
def status_code
|
73
|
+
@status_code ||= 0
|
74
|
+
end
|
37
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flydata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Fujikawa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -377,6 +377,7 @@ email: sysadmin@flydata.co
|
|
377
377
|
executables:
|
378
378
|
- fdmysqldump
|
379
379
|
- flydata
|
380
|
+
- serverinfo
|
380
381
|
extensions: []
|
381
382
|
extra_rdoc_files: []
|
382
383
|
files:
|
@@ -388,6 +389,7 @@ files:
|
|
388
389
|
- VERSION
|
389
390
|
- bin/fdmysqldump
|
390
391
|
- bin/flydata
|
392
|
+
- bin/serverinfo
|
391
393
|
- flydata.gemspec
|
392
394
|
- lib/fly_data_model.rb
|
393
395
|
- lib/flydata.rb
|