mysql-slaver 0.1.13 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4e9d24a3c9ff946cc64f58907bde35066b175e77
4
- data.tar.gz: 8d4d3066bef6770d7a3d7f4b58a5230bbb2d7c88
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzdhZjFhOTkyMGFhMjk3NGNjMWRkZDRlOWZjNmZhZmQzNTA4MTVkMQ==
5
+ data.tar.gz: !binary |-
6
+ N2IzYTBhODAwYzU2MjBmZGYwZDUxY2MwODg3YWVjNTk4MGYwM2E5Nw==
5
7
  SHA512:
6
- metadata.gz: a08b60d264c9b12ea14586fc5df10b45058a536f5b8e5ca7802ae790cea4e92face82a4d6022a467b86862dcca69dbc3dabc0ac43d16d74cb09e8792e81d585f
7
- data.tar.gz: 6e713f19740a10ab24d237b234a8e89f6d49b719c109d9d90512a517991e74eaece1895ecb1f9b49b7b8bffbc10f175e41394d2015c22b39269292763fb4179e
8
+ metadata.gz: !binary |-
9
+ OWY0MjgyODk1ODk5YTc1ZmE4OTUxNTAwN2MwNGEwNDFiNjY4NTQ5NDhhZDY5
10
+ OGRkNGRhMGM4OGQ1NjIzODc0YzMwMjI1NmIyNWEwZDM3MmMxNjJiMTI2NjNk
11
+ MDdiNTI1NmQwODA2MzkyODM5ZWY3NjU5NzcyMTc3NDRlZDdhZmU=
12
+ data.tar.gz: !binary |-
13
+ MzQ3OWZmOWVmMTdjMmM5NzhhZTM4NDA3MWFjZmRjOWYzYTJlN2Y0YmJmNWMx
14
+ ODZlYTQ0MTFkMGY4ZTI1MjFiNDI3NDBhZjg2MDEzYWIwODlkODUyODAyMDQx
15
+ NDQ3NDMyMDhiMzM0ZWFmYzgxMDU1ZTJlYTFlZGQxODY3YmY0OTk=
data/Gemfile CHANGED
@@ -9,5 +9,5 @@ group :development, :test do
9
9
  gem "gem-this"
10
10
  gem "gemcutter"
11
11
  gem "rspec"
12
- # gem "ruby-debug"
12
+ gem "debugger"
13
13
  end
data/Gemfile.lock CHANGED
@@ -1,34 +1,42 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ columnize (0.9.0)
5
+ debugger (1.6.8)
6
+ columnize (>= 0.3.1)
7
+ debugger-linecache (~> 1.2.0)
8
+ debugger-ruby_core_source (~> 1.3.5)
9
+ debugger-linecache (1.2.0)
10
+ debugger-ruby_core_source (1.3.8)
4
11
  diff-lcs (1.2.5)
5
12
  gem-this (0.3.7)
6
13
  gemcutter (0.7.1)
7
- json (1.8.1)
14
+ json (1.8.3)
8
15
  rake (10.4.2)
9
16
  rdoc (4.2.0)
10
17
  json (~> 1.4)
11
18
  rdoc-data (4.0.1)
12
19
  rdoc (~> 4.0)
13
- rspec (3.2.0)
14
- rspec-core (~> 3.2.0)
15
- rspec-expectations (~> 3.2.0)
16
- rspec-mocks (~> 3.2.0)
17
- rspec-core (3.2.0)
18
- rspec-support (~> 3.2.0)
19
- rspec-expectations (3.2.0)
20
+ rspec (3.3.0)
21
+ rspec-core (~> 3.3.0)
22
+ rspec-expectations (~> 3.3.0)
23
+ rspec-mocks (~> 3.3.0)
24
+ rspec-core (3.3.2)
25
+ rspec-support (~> 3.3.0)
26
+ rspec-expectations (3.3.1)
20
27
  diff-lcs (>= 1.2.0, < 2.0)
21
- rspec-support (~> 3.2.0)
22
- rspec-mocks (3.2.0)
28
+ rspec-support (~> 3.3.0)
29
+ rspec-mocks (3.3.2)
23
30
  diff-lcs (>= 1.2.0, < 2.0)
24
- rspec-support (~> 3.2.0)
25
- rspec-support (3.2.1)
31
+ rspec-support (~> 3.3.0)
32
+ rspec-support (3.3.0)
26
33
  thor (0.19.1)
27
34
 
28
35
  PLATFORMS
29
36
  ruby
30
37
 
31
38
  DEPENDENCIES
39
+ debugger
32
40
  gem-this
33
41
  gemcutter
34
42
  rake
@@ -36,3 +44,6 @@ DEPENDENCIES
36
44
  rdoc-data
37
45
  rspec
38
46
  thor
47
+
48
+ BUNDLED WITH
49
+ 1.10.6
data/README.md CHANGED
@@ -16,6 +16,7 @@ BLOGPOST
16
16
 
17
17
  ASSUMPTIONS/PRE-REQUISITES
18
18
 
19
+ * ruby 1.9.3 or greater
19
20
  * localhost is configured as a mysql replication slave
20
21
  * the current localhost user can ssh to the db master
21
22
  * any ssh config settings, other than a port number, required to access the master from localhost are set in a ~/.ssh/config file
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ RSpec::Core::RakeTask.new do |t|
9
9
  end
10
10
 
11
11
 
12
- task :default => ["spec"]
12
+ task default: ["spec"]
13
13
 
14
14
  # This builds the actual gem. For details of what all these options
15
15
  # mean, and other ones you can add, check the documentation here:
@@ -20,7 +20,7 @@ spec = Gem::Specification.new do |s|
20
20
 
21
21
  # Change these as appropriate
22
22
  s.name = "mysql-slaver"
23
- s.version = "0.1.13"
23
+ s.version = "0.2.0"
24
24
  s.summary = "Setup mysql replication"
25
25
  s.author = "David Salgado"
26
26
  s.email = "david@digitalronin.com"
@@ -67,7 +67,7 @@ end
67
67
  # - using bundler with a git source
68
68
  # - building the gem without rake (i.e. gem build blah.gemspec)
69
69
  # - maybe others?
70
- task :package => :gemspec
70
+ task package: :gemspec
71
71
 
72
72
  # Generate documentation
73
73
  RDoc::Task.new do |rd|
@@ -77,6 +77,6 @@ RDoc::Task.new do |rd|
77
77
  end
78
78
 
79
79
  desc 'Clear out RDoc and generated packages'
80
- task :clean => [:clobber_rdoc, :clobber_package] do
80
+ task clean: [:clobber_rdoc, :clobber_package] do
81
81
  rm "#{spec.name}.gemspec"
82
82
  end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require './lib/mysql_slaver'
5
+
6
+ MysqlSlaver::CLI.start(ARGV)
@@ -2,27 +2,31 @@ module MysqlSlaver
2
2
  class CLI < ::Thor
3
3
  desc "enslave", "Start MySQL replication to this host from a master"
4
4
 
5
- option :master_host, :required => true, :desc => "The server which will be the replication master, for this slave"
6
- option :database, :required => true, :desc => "The database to copy from the master"
7
- option :replication_user, :required => true, :desc => "DB user (on the master host), with replication permissions"
8
- option :replication_password, :required => true, :desc => "DB password for the replication user"
9
- option :root_password, :desc => "Password for the mysql root user (on both master and slave)"
10
- option :port, :default => 3306, :desc => "Mysql port"
11
- option :ssh_port, :default => 22, :desc => "SSH port"
12
- option :sock, :desc => "Mysql socket file (if any)"
13
- option :no_copy, :type => :boolean, :desc => "Do not copy data - just change master status"
5
+ option :master_host, required: true, desc: "The server which will be the replication master, for this slave"
6
+ option :database, required: true, desc: "The database to copy from the master"
7
+ option :replication_user, required: true, desc: "DB user (on the master host), with replication permissions"
8
+ option :replication_password, required: true, desc: "DB password for the replication user"
9
+ option :root_password, desc: "Password for the mysql root user (on both master and slave)"
10
+ option :port, default: 3306, desc: "Mysql port"
11
+ option :ssh_port, default: 22, desc: "SSH port"
12
+ option :sock, desc: "Mysql socket file (if any)"
13
+ option :no_copy, type: :boolean, desc: "Do not copy data - just change master status"
14
+ option :tables, desc: "Space-separated list of tables to copy (defaults to entire database)"
15
+ option :dry_run, type: :boolean, desc: "Display commands without executing"
14
16
 
15
17
  def enslave
16
18
  MysqlSlaver::Slaver.new(
17
- :master_host => options[:master_host],
18
- :port => options[:port],
19
- :ssh_port => options[:ssh_port],
20
- :socket_file => options[:sock],
21
- :no_copy => options[:no_copy],
22
- :mysql_root_password => options[:root_password],
23
- :database => options[:database],
24
- :replication_user => options[:replication_user],
25
- :replication_password => options[:replication_password]
19
+ master_host: options[:master_host],
20
+ port: options[:port],
21
+ ssh_port: options[:ssh_port],
22
+ socket_file: options[:sock],
23
+ no_copy: options[:no_copy],
24
+ mysql_root_password: options[:root_password],
25
+ database: options[:database],
26
+ replication_user: options[:replication_user],
27
+ replication_password: options[:replication_password],
28
+ tables: options[:tables],
29
+ dry_run: options[:dry_run]
26
30
  ).enslave!
27
31
  end
28
32
  end
@@ -2,7 +2,7 @@ module MysqlSlaver
2
2
  class DbCopier
3
3
  include MysqlCommand
4
4
 
5
- attr_accessor :master_host, :mysql_root_password, :database, :executor, :port, :socket_file
5
+ attr_accessor :master_host, :mysql_root_password, :database, :executor, :port, :socket_file, :tables
6
6
 
7
7
  def initialize(params)
8
8
  @master_host = params.fetch(:master_host)
@@ -10,7 +10,8 @@ module MysqlSlaver
10
10
  @database = params.fetch(:database)
11
11
  @port = params.fetch(:port, nil)
12
12
  @socket_file = params.fetch(:socket_file, nil)
13
- @executor = params.fetch(:executor) { Executor.new(:ssh_port => params[:ssh_port]) }
13
+ @executor = params.fetch(:executor) { Executor.new(ssh_port: params[:ssh_port]) }
14
+ @tables = params.fetch(:tables, nil)
14
15
  end
15
16
 
16
17
  def copy!
@@ -26,8 +27,8 @@ module MysqlSlaver
26
27
 
27
28
  def mysql_params
28
29
  {
29
- :root_password => mysql_root_password,
30
- :socket_file => socket_file
30
+ root_password: mysql_root_password,
31
+ socket_file: socket_file
31
32
  }
32
33
  end
33
34
 
@@ -36,6 +37,7 @@ module MysqlSlaver
36
37
  rtn = %[mysqldump]
37
38
  rtn << %[ -P #{port}] if port
38
39
  rtn << %[ #{creds} -h #{master_host} --master-data --single-transaction --quick --skip-add-locks --skip-lock-tables --default-character-set=utf8 --compress #{database}]
40
+ rtn << %[ #{tables}] unless tables.to_s.empty?
39
41
  rtn
40
42
  end
41
43
  end
@@ -1,11 +1,12 @@
1
1
  module MysqlSlaver
2
2
  class Executor
3
- attr_reader :ssh_port
3
+ attr_reader :ssh_port, :dry_run
4
4
 
5
5
  include Logger
6
6
 
7
7
  def initialize(params = {})
8
8
  @ssh_port = params[:ssh_port]
9
+ @dry_run = params.fetch(:dry_run, false)
9
10
  end
10
11
 
11
12
  def ssh_command(cmd, host)
@@ -19,8 +20,18 @@ module MysqlSlaver
19
20
  def execute(cmd)
20
21
  string = cmd.is_a?(Array) ? cmd.join('; ') : cmd
21
22
  log "CMD: #{string}"
22
- result = `#{string}`
23
- $?.success? ? result : nil
23
+ if dry_run
24
+ "[DUMMY RESULT]"
25
+ else
26
+ result = `#{string}`
27
+ success? ? result : nil
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def success?
34
+ $?.success?
24
35
  end
25
36
  end
26
37
  end
@@ -28,8 +28,8 @@ module MysqlSlaver
28
28
 
29
29
  def mysql_params
30
30
  {
31
- :root_password => mysql_root_password,
32
- :socket_file => socket_file
31
+ root_password: mysql_root_password,
32
+ socket_file: socket_file
33
33
  }
34
34
  end
35
35
 
@@ -8,43 +8,51 @@ module MysqlSlaver
8
8
  class Slaver
9
9
  include Logger
10
10
 
11
- attr_reader :status_fetcher, :data_copier, :master_changer, :no_copy
11
+ attr_reader :status_fetcher, :data_copier, :master_changer, :no_copy, :tables
12
12
 
13
13
  def initialize(params)
14
14
  mysql_root_password = params.fetch(:mysql_root_password, '')
15
15
  port = params.fetch(:port, 3306)
16
16
  ssh_port = params.fetch(:ssh_port, 22)
17
17
  socket_file = params.fetch(:socket_file, nil)
18
+ tables = params.fetch(:tables, nil)
18
19
  @no_copy = params.fetch(:no_copy, false)
19
20
 
21
+ dry_run = params.fetch(:dry_run, false)
22
+ executor = Executor.new(ssh_port: params[:ssh_port], dry_run: dry_run)
23
+
20
24
  @status_fetcher = params.fetch(:status_fetcher) {
21
25
  StatusFetcher.new(
22
- :master_host => params.fetch(:master_host),
23
- :mysql_root_password => mysql_root_password,
24
- :socket_file => socket_file,
25
- :ssh_port => ssh_port
26
+ master_host: params.fetch(:master_host),
27
+ mysql_root_password: mysql_root_password,
28
+ socket_file: socket_file,
29
+ ssh_port: ssh_port,
30
+ executor: executor
26
31
  )
27
32
  }
28
33
 
29
34
  @data_copier = params.fetch(:data_copier) {
30
35
  DbCopier.new(
31
- :master_host => params.fetch(:master_host),
32
- :mysql_root_password => mysql_root_password,
33
- :database => params.fetch(:database),
34
- :port => port,
35
- :socket_file => socket_file,
36
- :ssh_port => ssh_port
36
+ master_host: params.fetch(:master_host),
37
+ mysql_root_password: mysql_root_password,
38
+ database: params.fetch(:database),
39
+ port: port,
40
+ socket_file: socket_file,
41
+ tables: tables,
42
+ ssh_port: ssh_port,
43
+ executor: executor
37
44
  )
38
45
  }
39
46
 
40
47
  @master_changer = params.fetch(:master_changer) {
41
48
  MasterChanger.new(
42
- :master_host => params.fetch(:master_host),
43
- :mysql_root_password => mysql_root_password,
44
- :replication_user => params.fetch(:replication_user),
45
- :replication_password => params.fetch(:replication_password),
46
- :port => port,
47
- :socket_file => socket_file
49
+ master_host: params.fetch(:master_host),
50
+ mysql_root_password: mysql_root_password,
51
+ replication_user: params.fetch(:replication_user),
52
+ replication_password: params.fetch(:replication_password),
53
+ port: port,
54
+ socket_file: socket_file,
55
+ executor: executor
48
56
  )
49
57
  }
50
58
  end
@@ -9,11 +9,11 @@ module MysqlSlaver
9
9
  @master_host = params.fetch(:master_host)
10
10
  @socket_file = params.fetch(:socket_file, nil)
11
11
  @mysql_root_password = params.fetch(:mysql_root_password, '')
12
- @executor = params.fetch(:executor) { Executor.new(:ssh_port => params[:ssh_port]) }
12
+ @executor = params.fetch(:executor) { Executor.new(ssh_port: params[:ssh_port]) }
13
13
  end
14
14
 
15
15
  def status
16
- params = {:root_password => mysql_root_password, :socket_file => socket_file}
16
+ params = {root_password: mysql_root_password, socket_file: socket_file}
17
17
  cmd = mysql_command("show master status\\G", params)
18
18
  if data = executor.execute(executor.ssh_command(cmd, master_host))
19
19
  rtn = parse data
@@ -37,7 +37,7 @@ module MysqlSlaver
37
37
  position = $1
38
38
  end
39
39
  end
40
- {:file => file, :position => position}
40
+ {file: file, position: position}
41
41
  end
42
42
 
43
43
  end
@@ -1,15 +1,15 @@
1
- require 'spec/spec_helper'
1
+ require './spec/spec_helper'
2
2
 
3
3
  module MysqlSlaver
4
4
  describe DbCopier do
5
- let(:executor) { double(Executor, :execute => true, :ssh_command => "dummy-ssh-command") }
5
+ let(:executor) { double(Executor, execute: true, ssh_command: "dummy-ssh-command") }
6
6
 
7
7
  let(:params) {
8
8
  {
9
- :master_host => 'my.db.host',
10
- :mysql_root_password => 'supersekrit',
11
- :database => 'myappdb',
12
- :executor => executor
9
+ master_host: 'my.db.host',
10
+ mysql_root_password: 'supersekrit',
11
+ database: 'myappdb',
12
+ executor: executor
13
13
  }
14
14
  }
15
15
  subject(:copier) { described_class.new(params) }
@@ -37,7 +37,7 @@ module MysqlSlaver
37
37
  end
38
38
 
39
39
  context "with a non-standard mysql port" do
40
- let(:params) { super().merge(:port => 3307) }
40
+ let(:params) { super().merge(port: 3307) }
41
41
 
42
42
  it "issues mysqldump over ssh" do
43
43
  dump = "mysqldump -P 3307 -u root -p supersekrit -h my.db.host --master-data --single-transaction --quick --skip-add-locks --skip-lock-tables --default-character-set=utf8 --compress myappdb"
@@ -47,7 +47,7 @@ module MysqlSlaver
47
47
  end
48
48
 
49
49
  context "with a socket file" do
50
- let(:params) { super().merge(:socket_file => "/tmp/mysql.sock") }
50
+ let(:params) { super().merge(socket_file: "/tmp/mysql.sock") }
51
51
 
52
52
  it "issues mysqldump over ssh" do
53
53
  dump = "mysqldump -S /tmp/mysql.sock -u root -p supersekrit -h my.db.host --master-data --single-transaction --quick --skip-add-locks --skip-lock-tables --default-character-set=utf8 --compress myappdb"
@@ -62,5 +62,15 @@ module MysqlSlaver
62
62
  end
63
63
 
64
64
  end
65
+
66
+ context "with a list of tables" do
67
+ let(:params) { super().merge(tables: 'foo bar baz') }
68
+
69
+ it "lists tables in mysqldump command" do
70
+ dump = "mysqldump -u root -p supersekrit -h my.db.host --master-data --single-transaction --quick --skip-add-locks --skip-lock-tables --default-character-set=utf8 --compress myappdb foo bar baz"
71
+ expect(executor).to receive(:ssh_command).with(dump, 'my.db.host')
72
+ copier.copy!
73
+ end
74
+ end
65
75
  end
66
76
  end
@@ -1,12 +1,16 @@
1
- require 'spec/spec_helper'
1
+ require './spec/spec_helper'
2
2
 
3
3
  module MysqlSlaver
4
4
  describe Executor do
5
5
  let(:ssh_port) { nil }
6
- let(:params) { {:ssh_port => ssh_port} }
6
+ let(:params) { {ssh_port: ssh_port} }
7
7
 
8
8
  subject(:executor) { described_class.new(params) }
9
9
 
10
+ before do
11
+ allow(executor).to receive(:log)
12
+ end
13
+
10
14
  describe "#ssh_command" do
11
15
  it "formats command" do
12
16
  expect(executor.ssh_command("foo", "myhost")).to eq("ssh myhost 'foo'")
@@ -20,5 +24,57 @@ module MysqlSlaver
20
24
  end
21
25
  end
22
26
  end
27
+
28
+ describe "#execute" do
29
+ let(:succeeded) { true }
30
+
31
+ before do
32
+ allow(executor).to receive(:success?).and_return(succeeded)
33
+ end
34
+
35
+ context "when command succeeds" do
36
+ let(:succeeded) { true }
37
+
38
+ it "runs command in backticks" do
39
+ expect(executor).to receive(:`).with('ls')
40
+ executor.execute('ls')
41
+ end
42
+
43
+ it "returns the command output" do
44
+ expect(executor).to receive(:`).with('ls').and_return("foo\nbar\nbaz")
45
+ expect(executor.execute('ls')).to eq("foo\nbar\nbaz")
46
+ end
47
+ end
48
+
49
+ context "when command fails" do
50
+ let(:succeeded) { false }
51
+
52
+ before do
53
+ allow(executor).to receive(:`)
54
+ end
55
+
56
+ it "runs command in backticks" do
57
+ expect(executor).to receive(:`).with('ls')
58
+ executor.execute('ls')
59
+ end
60
+
61
+ it "returns nil" do
62
+ expect(executor.execute('ls')).to be_nil
63
+ end
64
+ end
65
+
66
+ context "dry-run" do
67
+ let(:params) { super().merge(dry_run: true) }
68
+
69
+ it "doesn't run the command" do
70
+ expect(executor).to_not receive(:`)
71
+ executor.execute('ls')
72
+ end
73
+
74
+ it "returns dummy result" do
75
+ expect(executor.execute('ls')).to eq("[DUMMY RESULT]")
76
+ end
77
+ end
78
+ end
23
79
  end
24
80
  end
@@ -1,18 +1,18 @@
1
- require 'spec/spec_helper'
1
+ require './spec/spec_helper'
2
2
 
3
3
  module MysqlSlaver
4
4
  describe MasterChanger do
5
- let(:executor) { double(Executor, :execute => true) }
5
+ let(:executor) { double(Executor, execute: true) }
6
6
 
7
- let(:status) { {:file => 'mysql-bin.001555', :position => 18426246} }
7
+ let(:status) { {file: 'mysql-bin.001555', position: 18426246} }
8
8
  let(:params) {
9
9
  {
10
- :master_host => 'my.db.host',
11
- :port => 3306,
12
- :mysql_root_password => 'supersekrit',
13
- :replication_user => 'repluser',
14
- :replication_password => 'replpassword',
15
- :executor => executor
10
+ master_host: 'my.db.host',
11
+ port: 3306,
12
+ mysql_root_password: 'supersekrit',
13
+ replication_user: 'repluser',
14
+ replication_password: 'replpassword',
15
+ executor: executor
16
16
  }
17
17
  }
18
18
  subject(:changer) { described_class.new(params) }
@@ -26,7 +26,7 @@ module MysqlSlaver
26
26
  end
27
27
 
28
28
  context "with a non-standard mysql port" do
29
- let(:params) { super().merge(:port => 3307) }
29
+ let(:params) { super().merge(port: 3307) }
30
30
 
31
31
  it "executes multi-part mysql command" do
32
32
  change_cmd = %[mysql -u root -p supersekrit -e "stop slave; CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.001555', MASTER_LOG_POS=18426246, MASTER_HOST='my.db.host', MASTER_PORT=3307, MASTER_USER='repluser', MASTER_PASSWORD='replpassword'; start slave"]
@@ -36,7 +36,7 @@ module MysqlSlaver
36
36
  end
37
37
 
38
38
  context "with a mysql socket file" do
39
- let(:params) { super().merge(:socket_file => "/tmp/mysql.sock") }
39
+ let(:params) { super().merge(socket_file: "/tmp/mysql.sock") }
40
40
 
41
41
  it "executes multi-part mysql command" do
42
42
  change_cmd = %[mysql -S /tmp/mysql.sock -u root -p supersekrit -e "stop slave; CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.001555', MASTER_LOG_POS=18426246, MASTER_HOST='my.db.host', MASTER_PORT=3306, MASTER_USER='repluser', MASTER_PASSWORD='replpassword'; start slave"]
@@ -1,19 +1,19 @@
1
- require 'spec/spec_helper'
1
+ require './spec/spec_helper'
2
2
 
3
3
  module MysqlSlaver
4
4
  describe Slaver do
5
5
  subject(:slaver) { described_class.new(params) }
6
6
 
7
7
  describe "#enslave!" do
8
- let(:status_fetcher) { double(StatusFetcher, :status => ()) }
9
- let(:data_copier) { double(DbCopier, :copy! => true) }
10
- let(:master_changer) { double(MasterChanger, :change! => true) }
8
+ let(:status_fetcher) { double(StatusFetcher, status: ()) }
9
+ let(:data_copier) { double(DbCopier, copy!: true) }
10
+ let(:master_changer) { double(MasterChanger, change!: true) }
11
11
 
12
12
  let(:params) {
13
13
  {
14
- :status_fetcher => status_fetcher,
15
- :data_copier => data_copier,
16
- :master_changer => master_changer
14
+ status_fetcher: status_fetcher,
15
+ data_copier: data_copier,
16
+ master_changer: master_changer
17
17
  }
18
18
  }
19
19
 
@@ -53,7 +53,7 @@ module MysqlSlaver
53
53
  end
54
54
 
55
55
  context "no-copy" do
56
- let(:params) { super().merge(:no_copy => true) }
56
+ let(:params) { super().merge(no_copy: true) }
57
57
 
58
58
  it "fetches master status" do
59
59
  slaver.enslave!
@@ -75,11 +75,11 @@ module MysqlSlaver
75
75
  context "instantiating collaborators" do
76
76
  let(:params) {
77
77
  {
78
- :master_host => 'my.db.host',
79
- :mysql_root_password => 'supersekrit',
80
- :database => 'myappdb',
81
- :replication_user => 'repluser',
82
- :replication_password => 'replpassword'
78
+ master_host: 'my.db.host',
79
+ mysql_root_password: 'supersekrit',
80
+ database: 'myappdb',
81
+ replication_user: 'repluser',
82
+ replication_password: 'replpassword'
83
83
  }
84
84
  }
85
85
 
@@ -106,7 +106,7 @@ module MysqlSlaver
106
106
  end
107
107
 
108
108
  context "with non-standard mysql port" do
109
- let(:params) { super().merge(:port => 3307) }
109
+ let(:params) { super().merge(port: 3307) }
110
110
 
111
111
  it "instantiates a master changer" do
112
112
  changer = slaver.master_changer
@@ -115,7 +115,7 @@ module MysqlSlaver
115
115
  end
116
116
 
117
117
  context "with non-standard ssh port" do
118
- let(:params) { super().merge(:ssh_port => 64389) }
118
+ let(:params) { super().merge(ssh_port: 64389) }
119
119
 
120
120
  it "instantiates a status fetcher" do
121
121
  fetcher = slaver.status_fetcher
@@ -129,7 +129,7 @@ module MysqlSlaver
129
129
  end
130
130
 
131
131
  context "with mysql socket" do
132
- let(:params) { super().merge(:socket_file => "/tmp/mysql.sock") }
132
+ let(:params) { super().merge(socket_file: "/tmp/mysql.sock") }
133
133
 
134
134
  it "instantiates a status fetcher" do
135
135
  fetcher = slaver.status_fetcher
@@ -146,6 +146,34 @@ module MysqlSlaver
146
146
  expect(copier.socket_file).to eq("/tmp/mysql.sock")
147
147
  end
148
148
  end
149
+
150
+ context "with a list of tables" do
151
+ let(:params) { super().merge(tables: 'foo bar baz') }
152
+
153
+ it "instantiates a data copier" do
154
+ copier = slaver.data_copier
155
+ expect(copier.tables).to eq('foo bar baz')
156
+ end
157
+ end
158
+
159
+ context "dry-run" do
160
+ let(:params) { super().merge(dry_run: true) }
161
+
162
+ it "instantiates a status fetcher" do
163
+ fetcher = slaver.status_fetcher
164
+ expect(fetcher.executor.dry_run).to be_truthy
165
+ end
166
+
167
+ it "instantiates a master changer" do
168
+ changer = slaver.master_changer
169
+ expect(changer.executor.dry_run).to be_truthy
170
+ end
171
+
172
+ it "instantiates a data copier" do
173
+ copier = slaver.data_copier
174
+ expect(copier.executor.dry_run).to be_truthy
175
+ end
176
+ end
149
177
  end
150
178
  end
151
179
  end
@@ -1,14 +1,14 @@
1
- require 'spec/spec_helper'
1
+ require './spec/spec_helper'
2
2
 
3
3
  module MysqlSlaver
4
4
  describe StatusFetcher do
5
- let(:executor) { double(Executor, :execute => "", :ssh_command => "dummy-ssh-command") }
5
+ let(:executor) { double(Executor, execute: "", ssh_command: "dummy-ssh-command") }
6
6
 
7
7
  let(:params) {
8
8
  {
9
- :master_host => 'my.db.host',
10
- :mysql_root_password => 'supersekrit',
11
- :executor => executor
9
+ master_host: 'my.db.host',
10
+ mysql_root_password: 'supersekrit',
11
+ executor: executor
12
12
  }
13
13
  }
14
14
  subject(:fetcher) { described_class.new(params) }
@@ -52,13 +52,13 @@ EOF
52
52
  end
53
53
 
54
54
  it "parses show master output" do
55
- expect(fetcher.status).to eq({:file => 'mysql-bin.003219', :position => '37065270'})
55
+ expect(fetcher.status).to eq({file: 'mysql-bin.003219', position: '37065270'})
56
56
  end
57
57
  end
58
58
  end
59
59
 
60
60
  context "using a socket filename" do
61
- let(:params) { super().merge(:socket_file => "/var/run/mysqld/mysqld.master.sock") }
61
+ let(:params) { super().merge(socket_file: "/var/run/mysqld/mysqld.master.sock") }
62
62
 
63
63
  it "executes show master command over ssh" do
64
64
  show_master = %[mysql -S /var/run/mysqld/mysqld.master.sock -u root -p supersekrit -e "show master status\\G"]
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'ruby-debug'
1
+ require 'debugger'
2
2
  Debugger.start
3
3
 
4
- require 'lib/mysql_slaver'
4
+ require './lib/mysql_slaver'
metadata CHANGED
@@ -1,33 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql-slaver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Salgado
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: Make a mysql server into a slave of another, optionally copying data
28
28
  email: david@digitalronin.com
29
29
  executables:
30
30
  - mysql_slaver
31
+ - mysql_slaver-dev
31
32
  extensions: []
32
33
  extra_rdoc_files:
33
34
  - README.md
@@ -37,6 +38,7 @@ files:
37
38
  - README.md
38
39
  - Rakefile
39
40
  - bin/mysql_slaver
41
+ - bin/mysql_slaver-dev
40
42
  - lib/mysql_slaver.rb
41
43
  - lib/mysql_slaver/cli.rb
42
44
  - lib/mysql_slaver/db_copier.rb
@@ -55,27 +57,27 @@ files:
55
57
  - spec/spec_helper.rb
56
58
  homepage: https://digitalronin.github.io/2014/04/16/mysql-slaver-gem-setup-mysql-replication/
57
59
  licenses:
58
- - "[MIT]"
60
+ - ! '[MIT]'
59
61
  metadata: {}
60
62
  post_install_message:
61
63
  rdoc_options:
62
- - "--main"
64
+ - --main
63
65
  - README.md
64
66
  require_paths:
65
67
  - lib
66
68
  required_ruby_version: !ruby/object:Gem::Requirement
67
69
  requirements:
68
- - - ">="
70
+ - - ! '>='
69
71
  - !ruby/object:Gem::Version
70
72
  version: '0'
71
73
  required_rubygems_version: !ruby/object:Gem::Requirement
72
74
  requirements:
73
- - - ">="
75
+ - - ! '>='
74
76
  - !ruby/object:Gem::Version
75
77
  version: '0'
76
78
  requirements: []
77
79
  rubyforge_project:
78
- rubygems_version: 2.4.5
80
+ rubygems_version: 2.4.6
79
81
  signing_key:
80
82
  specification_version: 4
81
83
  summary: Setup mysql replication