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 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: ce8cff208dd90a80d1de4633422585d48529fd0c
7
- metadata.gz: 42602044c3e90a740682c9824bc5b51b48916e9e
3
+ data.tar.gz: e11cb2727d58c1e8d0d41f80ff897667bb498d57
4
+ metadata.gz: c473885515e00293605ba387a45b8fade137e21f
5
+ SHA512:
6
+ data.tar.gz: 2aeecfd06e98c3366edace947408fba6025f253c1ad8436b74f68b6ffbd6eb270048b3ec0cecb75a35e0c17a6fb3c62db4c257290b2c369d5278c65c61d814f4
7
+ metadata.gz: e40f4afbe89db4a169559fbc059345da69d72690932d051caa1f2879232a08b6eef268c1b10f0f3683aef28de846ae1677e23a4d46dd7e578f5608a9409421d4
data/Gemfile CHANGED
@@ -3,5 +3,3 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  gem 'pry', "~> 0.9.0"
6
-
7
- gem 'dk', :github => "redding/dk", :branch => "master"
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 just build Dk tasks instead of "restores".
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
- TODO: Write code samples and usage instructions here
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
 
@@ -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.1"])
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", ["~> 0.0.1"])
23
+ gem.add_dependency("dk", ["~> 0.1.0"])
24
+ gem.add_dependency("much-plugin", ["~> 0.2.0"])
25
25
 
26
26
  end
@@ -1 +1,9 @@
1
- require "dk-dumpdb/version"
1
+ require 'dk-dumpdb/version'
2
+ require 'dk-dumpdb/script'
3
+ require 'dk-dumpdb/task'
4
+
5
+ module Dk::Dumpdb
6
+
7
+ SCP_ARGS_PARAM_NAME = 'dk-dumpdb_scp_args'
8
+
9
+ end
@@ -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