mysql-slaver 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|