dk-dumpdb 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +0 -2
- data/README.md +275 -2
- data/dk-dumpdb.gemspec +3 -3
- data/lib/dk-dumpdb.rb +9 -1
- data/lib/dk-dumpdb/config.rb +122 -0
- data/lib/dk-dumpdb/db.rb +69 -0
- data/lib/dk-dumpdb/script.rb +83 -0
- data/lib/dk-dumpdb/task.rb +58 -0
- data/lib/dk-dumpdb/task/copy_dump.rb +16 -0
- data/lib/dk-dumpdb/task/dump.rb +16 -0
- data/lib/dk-dumpdb/task/internal_task.rb +44 -0
- data/lib/dk-dumpdb/task/restore.rb +16 -0
- data/lib/dk-dumpdb/task/setup.rb +17 -0
- data/lib/dk-dumpdb/task/teardown.rb +17 -0
- data/lib/dk-dumpdb/version.rb +1 -1
- data/test/support/factory.rb +12 -0
- data/test/support/task/internal_task.rb +27 -0
- data/test/unit/config_tests.rb +259 -0
- data/test/unit/db_tests.rb +103 -0
- data/test/unit/dk-dumpdb_tests.rb +16 -0
- data/test/unit/script_tests.rb +165 -0
- data/test/unit/task/copy_dump_tests.rb +57 -0
- data/test/unit/task/dump_tests.rb +58 -0
- data/test/unit/task/internal_task_tests.rb +106 -0
- data/test/unit/task/restore_tests.rb +58 -0
- data/test/unit/task/setup_tests.rb +60 -0
- data/test/unit/task/teardown_tests.rb +60 -0
- data/test/unit/task_tests.rb +113 -0
- metadata +46 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
SHA512:
|
3
|
-
data.tar.gz: 35cfd71c0691092fafe514197bf7d916ac7609f76323cea08321aec494e1bc8c0341e182a5db6da12659c0821ebfe2415d8270fb92c8b45a3263bd96c0bbc2ae
|
4
|
-
metadata.gz: c246440dccc0f8c88ed6aeca8713030ad0fc89b208d9fab078664b15c012ecf3a4edf39cea35534f99b8c2eee98fdc622dfe0393f6311df08d82055fc234edfd
|
5
2
|
SHA1:
|
6
|
-
data.tar.gz:
|
7
|
-
metadata.gz:
|
3
|
+
data.tar.gz: e11cb2727d58c1e8d0d41f80ff897667bb498d57
|
4
|
+
metadata.gz: c473885515e00293605ba387a45b8fade137e21f
|
5
|
+
SHA512:
|
6
|
+
data.tar.gz: 2aeecfd06e98c3366edace947408fba6025f253c1ad8436b74f68b6ffbd6eb270048b3ec0cecb75a35e0c17a6fb3c62db4c257290b2c369d5278c65c61d814f4
|
7
|
+
metadata.gz: e40f4afbe89db4a169559fbc059345da69d72690932d051caa1f2879232a08b6eef268c1b10f0f3683aef28de846ae1677e23a4d46dd7e578f5608a9409421d4
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,284 @@
|
|
2
2
|
|
3
3
|
Build Dk tasks to dump and restore your databases.
|
4
4
|
|
5
|
-
Note: this is a port of the [Dumpdb gem](https://github.com/redding/dumpdb) to work with [Dk](https://github.com/redding/dk) tasks. The overall API/DSL is similar - you
|
5
|
+
Note: this is a port of the [Dumpdb gem](https://github.com/redding/dumpdb) to work with [Dk](https://github.com/redding/dk) tasks. The overall API/DSL is similar - you still define restore scripts but they are run using Dk tasks.
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
|
9
|
+
```ruby
|
10
|
+
require 'dk-dumpdb'
|
11
|
+
|
12
|
+
class MysqlFullRestoreScript
|
13
|
+
include Dk::Dumpdb::Script
|
14
|
+
|
15
|
+
config do
|
16
|
+
source do
|
17
|
+
{ :host => 'production.example.com',
|
18
|
+
:port => 1234,
|
19
|
+
:user => 'admin',
|
20
|
+
:pw => 'secret',
|
21
|
+
:db => 'myapp_db',
|
22
|
+
:output_root => '/some/source/dir'
|
23
|
+
}
|
24
|
+
end
|
25
|
+
target do
|
26
|
+
{ :host => 'localhost',
|
27
|
+
:user => 'admin',
|
28
|
+
:db => 'myapp_db',
|
29
|
+
:output_root => '/some/target/dir'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
dump{ "mysqldump -u :user -p\":pw\" :db | bzip2 > :dump_file" }
|
34
|
+
|
35
|
+
dump_file{ "dump.bz2" }
|
36
|
+
|
37
|
+
restore{ "mysqladmin -u :user -p\":pw\" -f -b DROP :db; true" }
|
38
|
+
restore{ "mysqladmin -u :user -p\":pw\" -f CREATE :db" }
|
39
|
+
restore{ "bunzip2 -c :dump_file | mysql -u :user -p\":pw\" :db" }
|
40
|
+
end
|
41
|
+
|
42
|
+
task_desc "restore mysql data"
|
43
|
+
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
Dk::Dumpdb provides a framework for defining scripts that backup and restore databases. You configure your source and target db settings. You define the set of commands needed for your task to dump the (local or remote) source database and optionally restore the dump to the (local) target database.
|
48
|
+
|
49
|
+
### Running
|
50
|
+
|
51
|
+
Each script automatically defines its own Dk task (`<ScriptClass>::Task`) that you can configure/use directly or that you can run from your own restore task.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# configure the dumpdb script task and use directly
|
55
|
+
|
56
|
+
require 'dk'
|
57
|
+
|
58
|
+
Dk.configure do
|
59
|
+
task 'restore-mysql', MysqlFullRestoreScript::Task
|
60
|
+
end
|
61
|
+
|
62
|
+
# OR use your own dk task to run the dumpdb script task
|
63
|
+
|
64
|
+
class MysqlFullRestoreTask
|
65
|
+
include Dk::Task
|
66
|
+
|
67
|
+
def run!
|
68
|
+
# custom logic before the script run...
|
69
|
+
|
70
|
+
run_task MysqlFullRestoreScript::Task
|
71
|
+
|
72
|
+
# custom logic after the script run...
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
Dk.configure do
|
78
|
+
task 'restore-mysql', MysqlFullRestoreTask
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
Either way, to run use Dk's CLI:
|
83
|
+
|
84
|
+
```
|
85
|
+
$ dk restore-mysql
|
86
|
+
```
|
87
|
+
|
88
|
+
Dk runs the task which runs the dump commands using source settings and runs the restore commands using target settings. By default, Dk::Dumpdb assumes both the dump and restore commands are to be run on the local system.
|
89
|
+
|
90
|
+
### Remote dumps
|
91
|
+
|
92
|
+
To run your dump commands on a remote server, specify the optional `ssh` setting.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
class MysqlFullRestoreScript
|
96
|
+
include Dk::Dumpdb::Script
|
97
|
+
|
98
|
+
config do
|
99
|
+
ssh { 'user@host' }
|
100
|
+
# ...
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
This tells Dk::Dumpdb to run the dump commands using ssh on a remote host and to download the dump file using sftp.
|
107
|
+
|
108
|
+
**Note**: you can configure SSH args using [Dk's config DSL](https://github.com/redding/dk#ssh_hosts-ssh_args-host_ssh_args). These will be used by the ssh dump commands.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Dk.configure do
|
112
|
+
# these custom args will be on all SSH dump cmds
|
113
|
+
ssh_args "-o ForwardAgent=yes "\
|
114
|
+
"-o ControlMaster=auto "\
|
115
|
+
"-o ControlPersist=60s "\
|
116
|
+
"-o UserKnownHostsFile=/dev/null "\
|
117
|
+
"-o StrictHostKeyChecking=no "\
|
118
|
+
"-o ConnectTimeout=10 "\
|
119
|
+
"-o LogLevel=quiet " \
|
120
|
+
"-tt "
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
Dk::Dumpdb uses `scp` to tranfer remote dump files to the local system. You can configure any custom scp args by setting a param:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
Dk.configure do
|
128
|
+
scp_args = "-o ForwardAgent=yes "\
|
129
|
+
"-o ControlMaster=auto "\
|
130
|
+
"-o ControlPersist=60s "\
|
131
|
+
"-o UserKnownHostsFile=/dev/null "\
|
132
|
+
"-o StrictHostKeyChecking=no "\
|
133
|
+
"-o ConnectTimeout=10 "\
|
134
|
+
"-o LogLevel=quiet "
|
135
|
+
dk_config.set_param(Dk::Dumpdb::SCP_ARGS_PARAM_NAME, scp_args)
|
136
|
+
|
137
|
+
task 'restore-mysql', MysqlFullRestoreScript::Task
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
141
|
+
**Protip**: since scp and ssh cmds share ssh options, set those to a variable and reuse on both the ssh cmds and the scp dump file cmd:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
Dk.configure do
|
145
|
+
# reuse thise on both the ssh and scp cmds
|
146
|
+
ssh_opts = "-o ForwardAgent=yes "\
|
147
|
+
"-o ControlMaster=auto "\
|
148
|
+
"-o ControlPersist=60s "\
|
149
|
+
"-o UserKnownHostsFile=/dev/null "\
|
150
|
+
"-o StrictHostKeyChecking=no "\
|
151
|
+
"-o ConnectTimeout=10 "\
|
152
|
+
"-o LogLevel=quiet "
|
153
|
+
|
154
|
+
ssh_args "#{ssh_opts} -tt"
|
155
|
+
dk_config.set_param(Dk::Dumpdb::SCP_ARGS_PARAM_NAME, ssh_opts)
|
156
|
+
|
157
|
+
task 'restore-mysql', MysqlFullRestoreScript::Task
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
## Define your script
|
162
|
+
|
163
|
+
Every Dk::Dumpdb script assumes there are two types of commands involved: dump commands that run using source settings and restore commands that run using target settings. The dump commands should produce a single "dump file" (typically a compressed file or tar). The restore commands restore the local db from the dump file.
|
164
|
+
|
165
|
+
### The Dump File
|
166
|
+
|
167
|
+
You specify the name of the dump file using the `dump_file` setting
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# ...
|
171
|
+
dump_file { "dump.bz2" }
|
172
|
+
#...
|
173
|
+
```
|
174
|
+
|
175
|
+
This tells Dk::Dumpdb what file is being generated by the dump and will be used in the restore. The dump commands should produce it. The restore commands should use it.
|
176
|
+
|
177
|
+
### Dump commands
|
178
|
+
|
179
|
+
Dump commands are system commands that should produce the dump file.
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
# ...
|
183
|
+
dump { "mysqldump -u :user -p :pw :db | bzip2 > :dump_file" }
|
184
|
+
#...
|
185
|
+
```
|
186
|
+
|
187
|
+
### Restore commands
|
188
|
+
|
189
|
+
Restore commands are system commands that should restore the local db from the dump file.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# ...
|
193
|
+
restore { "mysqladmin -u :user :pw -f -b DROP :db; true" } # drop the local db, whether it exists or not
|
194
|
+
restore { "mysqladmin -u :user :pw -f CREATE :db" } # recreate the local db
|
195
|
+
restore { "bunzip2 -c :dump_file | mysql -u :user :pw :db" } # unzip the dump file and apply it to the db
|
196
|
+
#...
|
197
|
+
```
|
198
|
+
|
199
|
+
### Command Placeholders
|
200
|
+
|
201
|
+
Dump and restore commands are templated. You define the command with placeholders and appropriate setting values are substituted in when the task is run.
|
202
|
+
|
203
|
+
Command placeholders should correspond with keys in the source or target settings. Dump commands use the source settings and restore commands use the target settings.
|
204
|
+
|
205
|
+
### Special Placeholders
|
206
|
+
|
207
|
+
There are two special placeholders that are added to the source and target settings automatically:
|
208
|
+
|
209
|
+
* `:output_dir`
|
210
|
+
dir the dump file is written to or read from (depending on whether dumping or restoring). This is generated by the task instance. By default, no specific root value is used - pass in a `:output_root` value to the source and target to specify one.
|
211
|
+
|
212
|
+
* `:dump_file`
|
213
|
+
path of the dump file - uses the :output_dir setting
|
214
|
+
|
215
|
+
You should at least use the `:dump_file` placeholder in your dump and restore commands to ensure proper dump handling and usage.
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
dump_file { "dump.bz2" }
|
219
|
+
|
220
|
+
dump { "mysqldump :db | bzip2 > :dump_file" }
|
221
|
+
restore { "bunzip2 -c :dump_file | mysql :db" }
|
222
|
+
```
|
223
|
+
|
224
|
+
## Source / Target settings
|
225
|
+
|
226
|
+
A Dk::Dumpdb task needs to be told about its source and target settings. You tell it these when you define your task:
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
class MysqlFullRestoreScript
|
230
|
+
include Dk::Dumpdb::Script
|
231
|
+
|
232
|
+
config do
|
233
|
+
source do
|
234
|
+
{ :user => 'something',
|
235
|
+
:pw => 'secret',
|
236
|
+
:db => 'something_production',
|
237
|
+
:something => 'else'
|
238
|
+
}
|
239
|
+
end
|
240
|
+
|
241
|
+
target do
|
242
|
+
{ :user => 'root',
|
243
|
+
:pw => 'supersecret',
|
244
|
+
:db => 'something_development'
|
245
|
+
}
|
246
|
+
end
|
247
|
+
|
248
|
+
# ...
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
```
|
253
|
+
|
254
|
+
Any settings keys can be used as command placeholders in dump and restore commands.
|
255
|
+
|
256
|
+
### Building Commands
|
257
|
+
|
258
|
+
The task DSL settings methods all take a proc as their argument. This is because the procs are lazy-eval'd in the scope of the task instance. This allows you to use interpolation to help build commands with dynamic data.
|
259
|
+
|
260
|
+
Take this example where you want your dump task to honor ignored tables.
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
class MysqlFullRestoreScript
|
264
|
+
include Dk::Dumpdb::Script
|
265
|
+
|
266
|
+
config do
|
267
|
+
# ...
|
268
|
+
dump { "mysqldump -u :user -p :pw :db #{ignored_tables} | bzip2 > :dump_file" }
|
269
|
+
# ...
|
270
|
+
end
|
271
|
+
|
272
|
+
def initialize(opts={})
|
273
|
+
opts[:ignored_tables] ||= []
|
274
|
+
@opts = opts
|
275
|
+
end
|
276
|
+
|
277
|
+
def ignored_tables
|
278
|
+
@opts[:ignored_tables].map{ |t| "--ignore-table=#{source.db}.#{t}" }.join(' ')
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
```
|
10
283
|
|
11
284
|
## Installation
|
12
285
|
|
data/dk-dumpdb.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_development_dependency("assert", ["~> 2.16.
|
22
|
-
gem.add_development_dependency("much-plugin", ["~> 0.2.0"])
|
21
|
+
gem.add_development_dependency("assert", ["~> 2.16.3"])
|
23
22
|
|
24
|
-
gem.add_dependency("dk",
|
23
|
+
gem.add_dependency("dk", ["~> 0.1.0"])
|
24
|
+
gem.add_dependency("much-plugin", ["~> 0.2.0"])
|
25
25
|
|
26
26
|
end
|
data/lib/dk-dumpdb.rb
CHANGED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'dk-dumpdb/db'
|
2
|
+
|
3
|
+
module Dk::Dumpdb
|
4
|
+
|
5
|
+
class Config
|
6
|
+
|
7
|
+
attr_reader :copy_dump_cmd_args, :dump_cmds, :restore_cmds
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@ssh = Ssh.new('')
|
11
|
+
@dump_file = DumpFile.new('')
|
12
|
+
@source = SourceTargetDb.new({})
|
13
|
+
@target = SourceTargetDb.new({})
|
14
|
+
|
15
|
+
@copy_dump_cmd_args = CopyDumpCmdArgs.new
|
16
|
+
|
17
|
+
@dump_cmds = CmdList.new([])
|
18
|
+
@restore_cmds = CmdList.new([])
|
19
|
+
end
|
20
|
+
|
21
|
+
def ssh(&block)
|
22
|
+
@ssh = Ssh.new(block) if !block.nil?
|
23
|
+
@ssh
|
24
|
+
end
|
25
|
+
|
26
|
+
def dump_file(&block)
|
27
|
+
@dump_file = DumpFile.new(block) if !block.nil?
|
28
|
+
@dump_file
|
29
|
+
end
|
30
|
+
|
31
|
+
def source(&block)
|
32
|
+
@source = SourceTargetDb.new(block) if !block.nil?
|
33
|
+
@source
|
34
|
+
end
|
35
|
+
|
36
|
+
def target(&block)
|
37
|
+
@target = SourceTargetDb.new(block) if !block.nil?
|
38
|
+
@target
|
39
|
+
end
|
40
|
+
|
41
|
+
def dump(&block); @dump_cmds << DumpCmd.new(block); end
|
42
|
+
def restore(&block); @restore_cmds << RestoreCmd.new(block); end
|
43
|
+
|
44
|
+
def dump_cmd(script, &block); DumpCmd.new(block).value(script); end
|
45
|
+
def restore_cmd(script, &block) RestoreCmd.new(block).value(script); end
|
46
|
+
|
47
|
+
class Value
|
48
|
+
|
49
|
+
attr_reader :proc
|
50
|
+
|
51
|
+
def initialize(proc = nil)
|
52
|
+
@proc = proc.kind_of?(::Proc) ? proc : Proc.new{ proc }
|
53
|
+
end
|
54
|
+
|
55
|
+
def value(script)
|
56
|
+
script.instance_eval(&@proc)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
class Ssh < Value; end
|
62
|
+
|
63
|
+
class DumpFile < Value; end
|
64
|
+
|
65
|
+
class SourceTargetDb < Value
|
66
|
+
|
67
|
+
def value(script)
|
68
|
+
hash = super
|
69
|
+
Db.new(script.dump_file, hash)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class CopyDumpCmdArgs < Value
|
75
|
+
|
76
|
+
def value(script)
|
77
|
+
"#{script.source_dump_file} #{script.target_dump_file}"
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class Cmd < Value
|
83
|
+
|
84
|
+
def value(script, placeholder_vals)
|
85
|
+
hsub(super(script), placeholder_vals)
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def hsub(string, hash)
|
91
|
+
hash.inject(string){ |new_str, (k, v)| new_str.gsub(":#{k}", v.to_s) }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
class DumpCmd < Cmd
|
97
|
+
|
98
|
+
def value(script, placeholder_vals = {})
|
99
|
+
super(script, script.source_hash.merge(placeholder_vals))
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
class RestoreCmd < Cmd
|
105
|
+
|
106
|
+
def value(script, placeholder_vals = {})
|
107
|
+
super(script, script.target_hash.merge(placeholder_vals))
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
class CmdList < ::Array
|
113
|
+
|
114
|
+
def value(script, placeholder_vals = {})
|
115
|
+
self.map{ |cmd| cmd.value(script, placeholder_vals) }
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|