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.
@@ -0,0 +1,69 @@
1
+ module Dk; end
2
+ module Dk::Dumpdb
3
+
4
+ class Db
5
+
6
+ DEFAULT_VALUE = ''.freeze
7
+
8
+ def initialize(dump_file_name = nil, values = nil)
9
+ dump_file_name = dump_file_name || 'dump.output'
10
+ @values = dk_dumpdb_symbolize_keys(values)
11
+
12
+ [:host, :port, :user, :pw, :db, :output_root].each do |key|
13
+ @values[key] ||= DEFAULT_VALUE
14
+ end
15
+
16
+ @values[:output_dir] = dk_dumpdb_build_output_dir(
17
+ self.output_root,
18
+ self.host,
19
+ self.db
20
+ )
21
+ @values[:dump_file] = File.join(self.output_dir, dump_file_name)
22
+ end
23
+
24
+ def to_hash; @values; end
25
+
26
+ def method_missing(meth, *args, &block)
27
+ if @values.has_key?(meth.to_sym)
28
+ @values[meth.to_sym]
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def respond_to?(meth)
35
+ @values.has_key?(meth.to_sym) || super
36
+ end
37
+
38
+ def ==(other_db)
39
+ if other_db.kind_of?(Db)
40
+ self.to_hash == other_db.to_hash
41
+ else
42
+ super
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def dk_dumpdb_build_output_dir(output_root, host, database)
49
+ dir_name = dk_dumpdb_build_output_dir_name(host, database)
50
+ if output_root && !output_root.to_s.empty?
51
+ File.join(output_root, dir_name)
52
+ else
53
+ dir_name
54
+ end
55
+ end
56
+
57
+ def dk_dumpdb_build_output_dir_name(host, database)
58
+ [host, database, Time.now.to_f].map(&:to_s).reject(&:empty?).join("__")
59
+ end
60
+
61
+ def dk_dumpdb_symbolize_keys(values)
62
+ (values || {}).inject({}) do |h, (k, v)|
63
+ h.merge(k.to_sym => v)
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,83 @@
1
+ require 'much-plugin'
2
+ require 'dk-dumpdb/config'
3
+ require 'dk-dumpdb/task'
4
+
5
+ module Dk::Dumpdb
6
+
7
+ module Script
8
+ include MuchPlugin
9
+
10
+ plugin_included do
11
+ include InstanceMethods
12
+ extend ClassMethods
13
+
14
+ class self::Task
15
+ include Dk::Dumpdb::Task
16
+ end
17
+ self::Task.script_class self
18
+
19
+ end
20
+
21
+ module InstanceMethods
22
+
23
+ attr_reader :params
24
+
25
+ def initialize(task_params = nil)
26
+ @params = task_params || {}
27
+ end
28
+
29
+ def config
30
+ @config ||= Config.new.tap do |config|
31
+ self.class.config_blocks.each do |config_block|
32
+ config.instance_eval(&config_block)
33
+ end
34
+ end
35
+ end
36
+
37
+ def ssh; @ssh ||= config.ssh.value(self); end
38
+ def dump_file; @dump_file ||= config.dump_file.value(self); end
39
+ def source; @source ||= config.source.value(self); end
40
+ def target; @target ||= config.target.value(self); end
41
+
42
+ def copy_dump_cmd_args
43
+ @copy_dump_cmd_args ||= config.copy_dump_cmd_args.value(self)
44
+ end
45
+
46
+ def dump_cmds; @dump_cmds ||= config.dump_cmds.value(self); end
47
+ def restore_cmds; @restore_cmds ||= config.restore_cmds.value(self); end
48
+
49
+ def source_dump_file; self.source.dump_file; end
50
+ def target_dump_file; self.target.dump_file; end
51
+
52
+ def source_hash; self.source.to_hash; end
53
+ def target_hash; self.target.to_hash; end
54
+
55
+ def ssh?
56
+ self.ssh && !self.ssh.empty?
57
+ end
58
+
59
+ def dump_cmd(&block); config.dump_cmd(self, &block); end
60
+ def restore_cmd(&block) config.restore_cmd(self, &block); end
61
+
62
+ end
63
+
64
+ module ClassMethods
65
+
66
+ def config_blocks
67
+ @config_blocks ||= []
68
+ end
69
+
70
+ def config(&block)
71
+ self.config_blocks << block if !block.nil?
72
+ end
73
+
74
+ def task_description(value = nil)
75
+ self::Task.description(value)
76
+ end
77
+ alias_method :task_desc, :task_description
78
+
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,58 @@
1
+ require 'dk/task'
2
+ require 'much-plugin'
3
+ require 'dk-dumpdb/task/copy_dump'
4
+ require 'dk-dumpdb/task/dump'
5
+ require 'dk-dumpdb/task/restore'
6
+ require 'dk-dumpdb/task/setup'
7
+ require 'dk-dumpdb/task/teardown'
8
+
9
+ module Dk::Dumpdb
10
+
11
+ module Task
12
+ include MuchPlugin
13
+
14
+ plugin_included do
15
+ include Dk::Task
16
+ include InstanceMethods
17
+ extend ClassMethods
18
+
19
+ end
20
+
21
+ module InstanceMethods
22
+
23
+ def run!
24
+ script = self.class.script_class.new(params)
25
+
26
+ run_task Setup, 'script' => script
27
+ begin
28
+ run_task Dump, 'script' => script
29
+ run_task CopyDump, 'script' => script
30
+ run_task Restore, 'script' => script
31
+ ensure
32
+ run_task Teardown, 'script' => script
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ module ClassMethods
39
+
40
+ def script_class(value = nil)
41
+ @script_class = value if !value.nil?
42
+ @script_class
43
+ end
44
+
45
+ end
46
+
47
+ module TestHelpers
48
+ include MuchPlugin
49
+
50
+ plugin_included do
51
+ include Dk::Task::TestHelpers
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,16 @@
1
+ require 'dk-dumpdb/task/internal_task'
2
+
3
+ module Dk::Dumpdb::Task
4
+
5
+ class CopyDump
6
+ include Dk::Dumpdb::Task::InternalTask
7
+
8
+ desc "(dk-dumpdb) copy the given script's dump file from source to target"
9
+
10
+ def run!
11
+ copy_cmd! params['script'].copy_dump_cmd_args
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'dk-dumpdb/task/internal_task'
2
+
3
+ module Dk::Dumpdb::Task
4
+
5
+ class Dump
6
+ include Dk::Dumpdb::Task::InternalTask
7
+
8
+ desc "(dk-dumpdb) run the given script's dump cmds"
9
+
10
+ def run!
11
+ params['script'].dump_cmds.each{ |cmd_str| source_cmd!(cmd_str) }
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,44 @@
1
+ require 'dk/task'
2
+ require 'much-plugin'
3
+ require 'dk-dumpdb'
4
+
5
+ module Dk::Dumpdb::Task
6
+
7
+ module InternalTask
8
+ include MuchPlugin
9
+
10
+ plugin_included do
11
+ include Dk::Task
12
+ include InstanceMethods
13
+
14
+ end
15
+
16
+ module InstanceMethods
17
+
18
+ private
19
+
20
+ def source_cmd!(cmd_str)
21
+ if params['script'].ssh?
22
+ ssh!(cmd_str, :hosts => params['script'].ssh)
23
+ else
24
+ cmd!(cmd_str)
25
+ end
26
+ end
27
+
28
+ def copy_cmd!(args)
29
+ if (s = params['script']).ssh?
30
+ cmd! "scp #{try_param(Dk::Dumpdb::SCP_ARGS_PARAM_NAME)} #{s.ssh}:#{args}"
31
+ else
32
+ cmd! "cp #{args}"
33
+ end
34
+ end
35
+
36
+ def target_cmd!(cmd_str)
37
+ cmd!(cmd_str)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,16 @@
1
+ require 'dk-dumpdb/task/internal_task'
2
+
3
+ module Dk::Dumpdb::Task
4
+
5
+ class Restore
6
+ include Dk::Dumpdb::Task::InternalTask
7
+
8
+ desc "(dk-dumpdb) run the given script's restore cmds"
9
+
10
+ def run!
11
+ params['script'].restore_cmds.each{ |cmd_str| target_cmd!(cmd_str) }
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,17 @@
1
+ require 'dk-dumpdb/task/internal_task'
2
+
3
+ module Dk::Dumpdb::Task
4
+
5
+ class Setup
6
+ include Dk::Dumpdb::Task::InternalTask
7
+
8
+ desc "(dk-dumpdb) setup a script run"
9
+
10
+ def run!
11
+ source_cmd!(params['script'].dump_cmd{ "mkdir -p #{source.output_dir}" })
12
+ target_cmd!(params['script'].restore_cmd{ "mkdir -p #{target.output_dir}" })
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'dk-dumpdb/task/internal_task'
2
+
3
+ module Dk::Dumpdb::Task
4
+
5
+ class Teardown
6
+ include Dk::Dumpdb::Task::InternalTask
7
+
8
+ desc "(dk-dumpdb) teardown a script run"
9
+
10
+ def run!
11
+ source_cmd!(params['script'].dump_cmd{ "rm -rf #{source.output_dir}" })
12
+ target_cmd!(params['script'].restore_cmd{ "rm -rf #{target.output_dir}" })
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -1,4 +1,4 @@
1
1
  module Dk; end
2
2
  module Dk::Dumpdb
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
@@ -1,6 +1,18 @@
1
1
  require 'assert/factory'
2
+ require 'dk-dumpdb/script'
2
3
 
3
4
  module Factory
4
5
  extend Assert::Factory
5
6
 
7
+ def self.script_class(&config_proc)
8
+ Class.new do
9
+ include Dk::Dumpdb::Script
10
+ config &config_proc
11
+ end
12
+ end
13
+
14
+ def self.script(script_class = nil, &config_proc)
15
+ (script_class || self.script_class(&config_proc)).new
16
+ end
17
+
6
18
  end
@@ -0,0 +1,27 @@
1
+ require 'dk/task'
2
+ require 'much-plugin'
3
+ require 'dk-dumpdb/task/internal_task'
4
+
5
+ module Dk::Dumpdb::Task::InternalTask
6
+
7
+ module TestHelpers
8
+ include MuchPlugin
9
+
10
+ plugin_included do
11
+ include Dk::Task::TestHelpers
12
+ include InstanceMethods
13
+
14
+ end
15
+
16
+ module InstanceMethods
17
+
18
+ def set_dk_dumpdb_script_param(*args, &block)
19
+ @params ||= {}
20
+ @params['script'] = Factory.script(*args, &block)
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,259 @@
1
+ require 'assert'
2
+ require 'dk-dumpdb/config'
3
+
4
+ require 'dk-dumpdb/db'
5
+ # require 'test/support/test_scripts'
6
+
7
+ class Dk::Dumpdb::Config
8
+
9
+ class UnitTests < Assert::Context
10
+ desc "Dk::Dumpdb::Config"
11
+ setup do
12
+ @script = FakeScript.new
13
+ @config_class = Dk::Dumpdb::Config
14
+ end
15
+
16
+ end
17
+
18
+ class InitTests < UnitTests
19
+ desc "when init"
20
+ setup do
21
+ now = Factory.time
22
+ Assert.stub(Time, :now){ now }
23
+
24
+ @config = @config_class.new
25
+ end
26
+ subject{ @config }
27
+
28
+ should have_readers :copy_dump_cmd_args, :dump_cmds, :restore_cmds
29
+ should have_imeths :ssh, :dump_file, :source, :target, :dump, :restore
30
+ should have_imeths :dump_cmd, :restore_cmd
31
+
32
+ should "default its values" do
33
+ assert_instance_of Ssh, subject.ssh
34
+ assert_equal '', subject.ssh.value(@script)
35
+
36
+ assert_instance_of DumpFile, subject.dump_file
37
+ assert_equal '', subject.dump_file.value(@script)
38
+
39
+ assert_instance_of SourceTargetDb, subject.source
40
+ val = subject.source.value(@script)
41
+ assert_instance_of Dk::Dumpdb::Db, val
42
+ exp = Dk::Dumpdb::Db.new(@script.dump_file, {})
43
+ assert_equal exp, val
44
+
45
+ assert_instance_of SourceTargetDb, subject.target
46
+ val = subject.target.value(@script)
47
+ assert_instance_of Dk::Dumpdb::Db, val
48
+ exp = Dk::Dumpdb::Db.new(@script.dump_file, {})
49
+ assert_equal exp, val
50
+
51
+ assert_instance_of CopyDumpCmdArgs, subject.copy_dump_cmd_args
52
+
53
+ assert_instance_of CmdList, subject.dump_cmds
54
+ assert_equal [], subject.dump_cmds.value(@script)
55
+
56
+ assert_instance_of CmdList, subject.restore_cmds
57
+ assert_equal [], subject.restore_cmds.value(@script)
58
+ end
59
+
60
+ should "allow setting new values" do
61
+ value = Factory.string
62
+ subject.ssh{ value }
63
+ assert_equal value, subject.ssh.value(@script)
64
+
65
+ subject.dump_file{ value }
66
+ assert_equal value, subject.dump_file.value(@script)
67
+
68
+ subject.source do
69
+ { 'pw' => value }
70
+ end
71
+ val = subject.source.value(@script)
72
+ exp = Dk::Dumpdb::Db.new(@script.dump_file, { 'pw' => value })
73
+ assert_equal exp, val
74
+
75
+ subject.target do
76
+ { 'pw' => value }
77
+ end
78
+ val = subject.target.value(@script)
79
+ exp = Dk::Dumpdb::Db.new(@script.dump_file, { 'pw' => value })
80
+ assert_equal exp, val
81
+ end
82
+
83
+ should "append dump/restore cmds" do
84
+ subject.dump{ Factory.string }
85
+ assert_equal 1, subject.dump_cmds.value(@script).size
86
+ assert_instance_of DumpCmd, subject.dump_cmds.first
87
+
88
+ subject.restore{ Factory.string }
89
+ assert_equal 1, subject.restore_cmds.value(@script).size
90
+ assert_instance_of RestoreCmd, subject.restore_cmds.first
91
+ end
92
+
93
+ should "build dump/restore cmd strs" do
94
+ cmd_str = "#{Factory.string}; pw: `:pw`"
95
+
96
+ exp = DumpCmd.new(proc{ cmd_str }).value(@script)
97
+ assert_equal exp, subject.dump_cmd(@script){ cmd_str }
98
+
99
+ exp = RestoreCmd.new(proc{ cmd_str }).value(@script)
100
+ assert_equal exp, subject.restore_cmd(@script){ cmd_str }
101
+ end
102
+
103
+ end
104
+
105
+ class ValueTests < UnitTests
106
+ desc "Value"
107
+ setup do
108
+ @setting = Value.new
109
+ end
110
+ subject{ @setting }
111
+
112
+ should have_readers :proc
113
+ should have_imeths :value
114
+
115
+ should "know its proc" do
116
+ assert_kind_of ::Proc, subject.proc
117
+ assert_nil subject.proc.call
118
+ end
119
+
120
+ should "instance eval its proc in the scope of a script to return a value" do
121
+ setting = Value.new(Proc.new{ "something: #{dump_file}" })
122
+ assert_equal "something: #{@script.dump_file}", setting.value(@script)
123
+ end
124
+
125
+ end
126
+
127
+ class SshTests < UnitTests
128
+ desc "Ssh"
129
+
130
+ should "be a Value" do
131
+ assert_true Ssh < Value
132
+ end
133
+
134
+ end
135
+
136
+ class DumpFileTests < UnitTests
137
+ desc "DumpFile"
138
+
139
+ should "be a Value" do
140
+ assert_true DumpFile < Value
141
+ end
142
+
143
+ end
144
+
145
+ class SourceTargetDbTests < UnitTests
146
+ desc "SourceTargetDb"
147
+
148
+ should "be a Value" do
149
+ assert_true SourceTargetDb < Value
150
+ end
151
+
152
+ should "have a Db value built from a hash" do
153
+ db_hash = { 'host' => Factory.string }
154
+ db = SourceTargetDb.new(db_hash).value(@script)
155
+ assert_instance_of Dk::Dumpdb::Db, db
156
+
157
+ assert_equal db_hash['host'], db.host
158
+ assert_includes @script.dump_file, db.to_hash[:dump_file]
159
+ end
160
+
161
+ end
162
+
163
+ class CopyDumpCmdArgsTests < UnitTests
164
+ desc "CopyDumpCmdArgs"
165
+
166
+ should "be a Value" do
167
+ assert_true CopyDumpCmdArgs < Value
168
+ end
169
+
170
+ should "know its value" do
171
+ exp = "#{@script.source_dump_file} #{@script.target_dump_file}"
172
+ assert_equal exp, CopyDumpCmdArgs.new.value(@script)
173
+ end
174
+
175
+ end
176
+
177
+ class CmdTests < UnitTests
178
+ desc "Cmd"
179
+
180
+ should "be a Value" do
181
+ assert_true Cmd < Value
182
+ end
183
+
184
+ should "eval and apply any placeholders to the cmd string" do
185
+ cmd_str = Proc.new{ "dump file: `#{dump_file}`; pw: `:pw`" }
186
+
187
+ exp = "dump file: `#{@script.dump_file}`; pw: `#{@script.source_hash['pw']}`"
188
+ assert_equal exp, Cmd.new(cmd_str).value(@script, @script.source_hash)
189
+ end
190
+
191
+ end
192
+
193
+ class DumpCmdTests < UnitTests
194
+ desc "DumpCmd"
195
+
196
+ should "be a Cmd" do
197
+ assert_true DumpCmd < Cmd
198
+ end
199
+
200
+ should "eval and apply any source placeholders to the cmd string" do
201
+ cmd_str = Proc.new{ "dump file: `#{dump_file}`; pw: `:pw`" }
202
+
203
+ exp = "dump file: `#{@script.dump_file}`; pw: `#{@script.source_hash['pw']}`"
204
+ assert_equal exp, DumpCmd.new(cmd_str).value(@script)
205
+ end
206
+
207
+ end
208
+
209
+ class RestoreCmdTests < UnitTests
210
+ desc "RestoreCmd"
211
+
212
+ should "be a Cmd" do
213
+ assert_true RestoreCmd < Cmd
214
+ end
215
+
216
+ should "eval and apply any target placeholders to the cmd string" do
217
+ cmd_str = Proc.new{ "dump file: `#{dump_file}`; pw: `:pw`" }
218
+
219
+ exp = "dump file: `#{@script.dump_file}`; pw: `#{@script.target_hash['pw']}`"
220
+ assert_equal exp, RestoreCmd.new(cmd_str).value(@script)
221
+ end
222
+
223
+ end
224
+
225
+ class CmdListTests < UnitTests
226
+ desc "CmdList"
227
+ setup do
228
+ other_cmd = Factory.string
229
+ @cmds = [
230
+ Cmd.new(Proc.new{ "dump file: `#{dump_file}`; pw: `:pw`" }),
231
+ Cmd.new(Proc.new{ other_cmd })
232
+ ]
233
+ end
234
+
235
+ should "be an Array" do
236
+ assert_kind_of ::Array, CmdList.new
237
+ end
238
+
239
+ should "return the commands, eval'd and placeholders applied" do
240
+ exp = @cmds.map{ |c| c.value(@script, @script.source_hash) }
241
+ assert_equal exp, CmdList.new(@cmds).value(@script, @script.source_hash)
242
+ end
243
+
244
+ end
245
+
246
+ class FakeScript
247
+ attr_reader :dump_file, :source_dump_file, :target_dump_file
248
+ attr_reader :source_hash, :target_hash
249
+
250
+ def initialize
251
+ @dump_file = Factory.string
252
+ @source_dump_file = File.join(Factory.path, @dump_file)
253
+ @target_dump_file = File.join(Factory.path, @dump_file)
254
+ @source_hash = { 'pw' => Factory.string }
255
+ @target_hash = { 'pw' => Factory.string }
256
+ end
257
+ end
258
+
259
+ end