mysql-slaver 0.1.9 → 0.1.10
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.
- data/README.md +3 -4
- data/lib/mysql_slaver/cli.rb +6 -3
- data/lib/mysql_slaver/db_copier.rb +1 -1
- data/lib/mysql_slaver/executor.rb +11 -1
- data/lib/mysql_slaver/slaver.rb +8 -4
- data/lib/mysql_slaver/status_fetcher.rb +1 -1
- data/spec/mysql_slaver/executor_spec.rb +12 -1
- data/spec/mysql_slaver/slaver_spec.rb +32 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -14,7 +14,7 @@ ASSUMPTIONS/PRE-REQUISITES
|
|
14
14
|
|
15
15
|
* localhost is configured as a mysql replication slave
|
16
16
|
* the current localhost user can ssh to the db master
|
17
|
-
* any ssh config settings required to access the master from localhost are set in a ~/.ssh/config file
|
17
|
+
* any ssh config settings, other than a port number, required to access the master from localhost are set in a ~/.ssh/config file
|
18
18
|
* ssh is on the current user's path
|
19
19
|
* your mysql administrator user is called 'root', locally and on the db master
|
20
20
|
* mysql is on the local user's path
|
@@ -30,11 +30,10 @@ CAVEATS
|
|
30
30
|
|
31
31
|
TODO
|
32
32
|
|
33
|
-
*
|
33
|
+
* output better help (include optional params, format better (shorter lines))
|
34
34
|
* add a "dry-run" mode
|
35
|
-
* check ssh connection
|
35
|
+
* check ssh connection
|
36
36
|
* check replication permissions
|
37
37
|
* check slave is setup as a replication slave (i.e. it has a mysql server id)
|
38
38
|
* allow a mysql admin username other than 'root'
|
39
39
|
* allow different root user passwords on slave and master
|
40
|
-
* allow ssh options
|
data/lib/mysql_slaver/cli.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
module MysqlSlaver
|
2
2
|
class CLI < ::Thor
|
3
|
+
desc "enslave", "Start MySQL replication to this host from a master"
|
4
|
+
|
3
5
|
option :master_host, :required => true, :desc => "The server which will be the replication master, for this slave"
|
4
6
|
option :database, :required => true, :desc => "The database to copy from the master"
|
5
7
|
option :replication_user, :required => true, :desc => "DB user (on the master host), with replication permissions"
|
6
8
|
option :replication_password, :required => true, :desc => "DB password for the replication user"
|
7
|
-
|
8
9
|
option :root_password, :desc => "Password for the mysql root user (on both master and slave)"
|
9
10
|
option :port, :desc => "Mysql port (if not 3306)"
|
11
|
+
option :ssh_port, :desc => "SSH port (if not 22)"
|
10
12
|
option :sock, :desc => "Mysql socket file (if any)"
|
11
|
-
|
12
|
-
desc "enslave", "start mysql replication to this host from a master"
|
13
|
+
option :no_copy, :type => :boolean, :desc => "Do not copy data - just change master status"
|
13
14
|
|
14
15
|
def enslave
|
15
16
|
MysqlSlaver::Slaver.new(
|
16
17
|
:master_host => options[:master_host],
|
17
18
|
:port => options[:port],
|
19
|
+
:ssh_port => options[:ssh_port],
|
18
20
|
:socket_file => options[:sock],
|
21
|
+
:no_copy => options[:no_copy],
|
19
22
|
:mysql_root_password => options[:root_password],
|
20
23
|
:database => options[:database],
|
21
24
|
:replication_user => options[:replication_user],
|
@@ -10,7 +10,7 @@ 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 }
|
13
|
+
@executor = params.fetch(:executor) { Executor.new(:ssh_port => params[:ssh_port]) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def copy!
|
@@ -1,9 +1,19 @@
|
|
1
1
|
module MysqlSlaver
|
2
2
|
class Executor
|
3
|
+
attr_reader :ssh_port
|
4
|
+
|
3
5
|
include Logger
|
4
6
|
|
7
|
+
def initialize(params = {})
|
8
|
+
@ssh_port = params[:ssh_port]
|
9
|
+
end
|
10
|
+
|
5
11
|
def ssh_command(cmd, host)
|
6
|
-
|
12
|
+
if ssh_port
|
13
|
+
"ssh -p #{ssh_port} #{host} '#{cmd}'"
|
14
|
+
else
|
15
|
+
"ssh #{host} '#{cmd}'"
|
16
|
+
end
|
7
17
|
end
|
8
18
|
|
9
19
|
def execute(cmd)
|
data/lib/mysql_slaver/slaver.rb
CHANGED
@@ -6,18 +6,21 @@
|
|
6
6
|
# connection)
|
7
7
|
module MysqlSlaver
|
8
8
|
class Slaver
|
9
|
-
attr_reader :status_fetcher, :data_copier, :master_changer
|
9
|
+
attr_reader :status_fetcher, :data_copier, :master_changer, :no_copy
|
10
10
|
|
11
11
|
def initialize(params)
|
12
12
|
mysql_root_password = params.fetch(:mysql_root_password, '')
|
13
13
|
port = params.fetch(:port, 3306)
|
14
|
+
ssh_port = params.fetch(:ssh_port, 22)
|
14
15
|
socket_file = params.fetch(:socket_file, nil)
|
16
|
+
@no_copy = params.fetch(:no_copy, false)
|
15
17
|
|
16
18
|
@status_fetcher = params.fetch(:status_fetcher) {
|
17
19
|
StatusFetcher.new(
|
18
20
|
:master_host => params.fetch(:master_host),
|
19
21
|
:mysql_root_password => mysql_root_password,
|
20
|
-
:socket_file => socket_file
|
22
|
+
:socket_file => socket_file,
|
23
|
+
:ssh_port => ssh_port
|
21
24
|
)
|
22
25
|
}
|
23
26
|
|
@@ -27,7 +30,8 @@ module MysqlSlaver
|
|
27
30
|
:mysql_root_password => mysql_root_password,
|
28
31
|
:database => params.fetch(:database),
|
29
32
|
:port => port,
|
30
|
-
:socket_file => socket_file
|
33
|
+
:socket_file => socket_file,
|
34
|
+
:ssh_port => ssh_port
|
31
35
|
)
|
32
36
|
}
|
33
37
|
|
@@ -45,7 +49,7 @@ module MysqlSlaver
|
|
45
49
|
|
46
50
|
def enslave!
|
47
51
|
master_status = status_fetcher.status
|
48
|
-
data_copier.copy!
|
52
|
+
data_copier.copy! unless no_copy
|
49
53
|
master_changer.change!(master_status)
|
50
54
|
end
|
51
55
|
end
|
@@ -9,7 +9,7 @@ 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 }
|
12
|
+
@executor = params.fetch(:executor) { Executor.new(:ssh_port => params[:ssh_port]) }
|
13
13
|
end
|
14
14
|
|
15
15
|
def status
|
@@ -2,12 +2,23 @@ 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} }
|
7
|
+
|
8
|
+
subject(:executor) { described_class.new(params) }
|
6
9
|
|
7
10
|
describe "#ssh_command" do
|
8
11
|
it "formats command" do
|
9
12
|
expect(executor.ssh_command("foo", "myhost")).to eq("ssh myhost 'foo'")
|
10
13
|
end
|
14
|
+
|
15
|
+
context "with non-standard ssh port" do
|
16
|
+
let(:ssh_port) { 64389 }
|
17
|
+
|
18
|
+
it "formats command" do
|
19
|
+
expect(executor.ssh_command("foo", "myhost")).to eq("ssh -p 64389 myhost 'foo'")
|
20
|
+
end
|
21
|
+
end
|
11
22
|
end
|
12
23
|
end
|
13
24
|
end
|
@@ -32,6 +32,24 @@ module MysqlSlaver
|
|
32
32
|
expect(master_changer).to have_received(:change!)
|
33
33
|
end
|
34
34
|
|
35
|
+
context "no-copy" do
|
36
|
+
let(:params) { super().merge(:no_copy => true) }
|
37
|
+
|
38
|
+
it "fetches master status" do
|
39
|
+
slaver.enslave!
|
40
|
+
expect(status_fetcher).to have_received(:status)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "doesn't copy data" do
|
44
|
+
slaver.enslave!
|
45
|
+
expect(data_copier).to_not have_received(:copy!)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "changes master status" do
|
49
|
+
slaver.enslave!
|
50
|
+
expect(master_changer).to have_received(:change!)
|
51
|
+
end
|
52
|
+
end
|
35
53
|
end
|
36
54
|
|
37
55
|
context "instantiating collaborators" do
|
@@ -76,6 +94,20 @@ module MysqlSlaver
|
|
76
94
|
end
|
77
95
|
end
|
78
96
|
|
97
|
+
context "with non-standard ssh port" do
|
98
|
+
let(:params) { super().merge(:ssh_port => 64389) }
|
99
|
+
|
100
|
+
it "instantiates a status fetcher" do
|
101
|
+
fetcher = slaver.status_fetcher
|
102
|
+
expect(fetcher.executor.ssh_port).to eq(64389)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "instantiates a data copier" do
|
106
|
+
copier = slaver.data_copier
|
107
|
+
expect(copier.executor.ssh_port).to eq(64389)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
79
111
|
context "with mysql socket" do
|
80
112
|
let(:params) { super().merge(:socket_file => "/tmp/mysql.sock") }
|
81
113
|
|
@@ -93,7 +125,6 @@ module MysqlSlaver
|
|
93
125
|
copier = slaver.data_copier
|
94
126
|
expect(copier.socket_file).to eq("/tmp/mysql.sock")
|
95
127
|
end
|
96
|
-
|
97
128
|
end
|
98
129
|
end
|
99
130
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql-slaver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 10
|
10
|
+
version: 0.1.10
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Salgado
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2014-04-
|
18
|
+
date: 2014-04-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|