dk 0.0.1 → 0.1.0

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.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +643 -1
  3. data/bin/dk +7 -0
  4. data/dk.gemspec +7 -3
  5. data/lib/dk/ansi.rb +98 -0
  6. data/lib/dk/cli.rb +173 -0
  7. data/lib/dk/config.rb +217 -0
  8. data/lib/dk/config_runner.rb +24 -0
  9. data/lib/dk/dk_runner.rb +13 -0
  10. data/lib/dk/dry_runner.rb +43 -0
  11. data/lib/dk/has_set_param.rb +42 -0
  12. data/lib/dk/has_ssh_opts.rb +36 -0
  13. data/lib/dk/has_the_runs.rb +23 -0
  14. data/lib/dk/has_the_stubs.rb +116 -0
  15. data/lib/dk/local.rb +84 -0
  16. data/lib/dk/null_logger.rb +13 -0
  17. data/lib/dk/remote.rb +132 -0
  18. data/lib/dk/runner.rb +202 -0
  19. data/lib/dk/task.rb +266 -0
  20. data/lib/dk/task_run.rb +17 -0
  21. data/lib/dk/test_runner.rb +54 -0
  22. data/lib/dk/tree_runner.rb +64 -0
  23. data/lib/dk/version.rb +1 -1
  24. data/lib/dk.rb +23 -1
  25. data/test/helper.rb +6 -1
  26. data/test/support/config/dk.rb +7 -0
  27. data/test/support/config/task_defs.rb +10 -0
  28. data/test/support/factory.rb +38 -0
  29. data/test/support/log/.gitkeep +0 -0
  30. data/test/system/has_the_stubs_tests.rb +355 -0
  31. data/test/system/runner_tests.rb +222 -0
  32. data/test/unit/ansi_tests.rb +40 -0
  33. data/test/unit/cli_tests.rb +317 -0
  34. data/test/unit/config_runner_tests.rb +60 -0
  35. data/test/unit/config_tests.rb +427 -0
  36. data/test/unit/dk_runner_tests.rb +34 -0
  37. data/test/unit/dk_tests.rb +49 -0
  38. data/test/unit/dry_runner_tests.rb +71 -0
  39. data/test/unit/has_set_param_tests.rb +46 -0
  40. data/test/unit/has_ssh_opts_tests.rb +81 -0
  41. data/test/unit/has_the_runs_tests.rb +37 -0
  42. data/test/unit/has_the_stubs_tests.rb +279 -0
  43. data/test/unit/local_tests.rb +174 -0
  44. data/test/unit/null_logger_tests.rb +17 -0
  45. data/test/unit/remote_tests.rb +330 -0
  46. data/test/unit/runner_tests.rb +398 -0
  47. data/test/unit/task_run_tests.rb +40 -0
  48. data/test/unit/task_tests.rb +943 -0
  49. data/test/unit/test_runner_tests.rb +189 -0
  50. data/test/unit/tree_runner_tests.rb +152 -0
  51. metadata +106 -9
@@ -0,0 +1,943 @@
1
+ require 'assert'
2
+ require 'dk/task'
3
+
4
+ require 'much-plugin'
5
+ require 'dk'
6
+ require 'dk/remote'
7
+ require 'dk/runner'
8
+
9
+ module Dk::Task
10
+
11
+ class UnitTests < Assert::Context
12
+ desc "Dk::Task"
13
+ setup do
14
+ @task_class = Class.new{ include Dk::Task }
15
+ end
16
+ subject{ @task_class }
17
+
18
+ should have_imeths :description, :desc
19
+ should have_imeths :before_callbacks, :after_callbacks
20
+ should have_imeths :before_callback_task_classes
21
+ should have_imeths :after_callback_task_classes
22
+ should have_imeths :before, :after, :prepend_before, :prepend_after
23
+ should have_imeths :ssh_hosts, :run_only_once
24
+
25
+ should "use much-plugin" do
26
+ assert_includes MuchPlugin, Dk::Task
27
+ end
28
+
29
+ should "set its description" do
30
+ exp = Factory.string
31
+ subject.description exp
32
+ assert_equal exp, subject.description
33
+ assert_equal exp, subject.desc
34
+
35
+ exp = Factory.string
36
+ subject.desc exp
37
+ assert_equal exp, subject.description
38
+ assert_equal exp, subject.desc
39
+ end
40
+
41
+ should "know its default callbacks" do
42
+ assert_equal [], subject.before_callbacks
43
+ assert_equal [], subject.after_callbacks
44
+ assert_equal [], subject.before_callback_task_classes
45
+ assert_equal [], subject.after_callback_task_classes
46
+ end
47
+
48
+ should "append callbacks" do
49
+ task_class = Factory.string
50
+ params = Factory.string
51
+
52
+ subject.before_callbacks << Factory.task_callback(Factory.string)
53
+ subject.before(task_class, params)
54
+ assert_equal task_class, subject.before_callbacks.last.task_class
55
+ assert_equal params, subject.before_callbacks.last.params
56
+
57
+ exp = subject.before_callbacks.map(&:task_class)
58
+ assert_equal exp, subject.before_callback_task_classes
59
+
60
+ subject.after_callbacks << Factory.task_callback(Factory.string)
61
+ subject.after(task_class, params)
62
+ assert_equal task_class, subject.after_callbacks.last.task_class
63
+ assert_equal params, subject.after_callbacks.last.params
64
+
65
+ exp = subject.after_callbacks.map(&:task_class)
66
+ assert_equal exp, subject.after_callback_task_classes
67
+ end
68
+
69
+ should "prepend callbacks" do
70
+ task_class = Factory.string
71
+ params = Factory.string
72
+
73
+ subject.before_callbacks << Factory.task_callback(Factory.string)
74
+ subject.prepend_before(task_class, params)
75
+ assert_equal task_class, subject.before_callbacks.first.task_class
76
+ assert_equal params, subject.before_callbacks.first.params
77
+
78
+ exp = subject.before_callbacks.map(&:task_class)
79
+ assert_equal exp, subject.before_callback_task_classes
80
+
81
+ subject.after_callbacks << Factory.task_callback(Factory.string)
82
+ subject.prepend_after(task_class, params)
83
+ assert_equal task_class, subject.after_callbacks.first.task_class
84
+ assert_equal params, subject.after_callbacks.first.params
85
+
86
+ exp = subject.after_callbacks.map(&:task_class)
87
+ assert_equal exp, subject.after_callback_task_classes
88
+ end
89
+
90
+ should "know its ssh hosts proc" do
91
+ assert_kind_of Proc, subject.ssh_hosts
92
+ assert_nil subject.ssh_hosts.call
93
+
94
+ hosts = Factory.hosts
95
+
96
+ subject.ssh_hosts hosts
97
+ assert_kind_of Proc, subject.ssh_hosts
98
+ assert_equal hosts, subject.ssh_hosts.call
99
+
100
+ subject.ssh_hosts{ hosts }
101
+ assert_kind_of Proc, subject.ssh_hosts
102
+ assert_equal hosts, subject.ssh_hosts.call
103
+ end
104
+
105
+ should "set whether it should run only once" do
106
+ assert_nil subject.run_only_once
107
+
108
+ value = [true, Factory.string, Factory.integer].sample
109
+ subject.run_only_once value
110
+ assert_true subject.run_only_once
111
+
112
+ value = false
113
+ subject.run_only_once value
114
+ assert_false subject.run_only_once
115
+ end
116
+
117
+ end
118
+
119
+ class InitTests < UnitTests
120
+ include Dk::Task::TestHelpers
121
+
122
+ desc "when init"
123
+ setup do
124
+ @default_ssh_cmd_opts = {
125
+ :ssh_args => Factory.string,
126
+ :host_ssh_args => { Factory.string => Factory.string },
127
+ :hosts => Factory.hosts
128
+ }
129
+
130
+ @hosts_group_name = Factory.string
131
+ @runner_ssh_hosts = { @hosts_group_name => @default_ssh_cmd_opts[:hosts] }
132
+ @task_class.ssh_hosts @hosts_group_name
133
+ @runner = test_runner(@task_class, {
134
+ :params => { Factory.string => Factory.string },
135
+ :ssh_hosts => @runner_ssh_hosts,
136
+ :ssh_args => @default_ssh_cmd_opts[:ssh_args],
137
+ :host_ssh_args => @default_ssh_cmd_opts[:host_ssh_args]
138
+ })
139
+ @task = @runner.task
140
+ end
141
+ subject{ @task }
142
+
143
+ should have_imeths :dk_run, :run!, :dk_dsl_ssh_hosts
144
+
145
+ should "not implement its run! method" do
146
+ assert_raises NotImplementedError do
147
+ subject.run!
148
+ end
149
+ end
150
+
151
+ should "know its configured DSL ssh hosts" do
152
+ assert_equal @hosts_group_name, subject.dk_dsl_ssh_hosts
153
+
154
+ hosts = Factory.hosts
155
+ task_class = Class.new{ include Dk::Task; ssh_hosts hosts; }
156
+ task = test_task(task_class)
157
+ assert_equal hosts, task.dk_dsl_ssh_hosts
158
+
159
+ task_class = Class.new{ include Dk::Task }
160
+ task = test_task(task_class)
161
+ assert_nil task.dk_dsl_ssh_hosts
162
+ end
163
+
164
+ should "know if it is equal to another task" do
165
+ task = @task_class.new(@runner)
166
+ assert_equal task, subject
167
+
168
+ task = Class.new{ include Dk::Task }.new(@runner)
169
+ assert_not_equal task, subject
170
+ end
171
+
172
+ end
173
+
174
+ class RunTests < InitTests
175
+ desc "and run"
176
+ setup do
177
+ # build a call orders object to pass around to the callback tasks for
178
+ # shared state call order
179
+ @call_orders = CallOrders.new
180
+
181
+ # build a base runner and task manually so the callback tasks actually
182
+ # run (b/c the test runner doesn't run callbacks). Note: the task's
183
+ # callbacks are intentionally duplicated on the runner to ensure that
184
+ # duplicate runner/task callbacks are ignored and the callback is only
185
+ # run once
186
+ @runner = Dk::Runner.new({
187
+ :params => { 'call_orders' => @call_orders },
188
+ :before_callbacks => {
189
+ CallbacksTask => [
190
+ Callback.new(CallbackTask, 'callback' => 'runner_before'),
191
+ *CallbacksTask.before_callbacks
192
+ ]
193
+ },
194
+ :prepend_before_callbacks => {
195
+ CallbacksTask => [
196
+ Callback.new(CallbackTask, 'callback' => 'runner_prepend_before')
197
+ ]
198
+ },
199
+ :after_callbacks => {
200
+ CallbacksTask => [
201
+ Callback.new(CallbackTask, 'callback' => 'runner_after'),
202
+ *CallbacksTask.after_callbacks
203
+ ]
204
+ },
205
+ :prepend_after_callbacks => {
206
+ CallbacksTask => [
207
+ Callback.new(CallbackTask, 'callback' => 'runner_prepend_after')
208
+ ]
209
+ }
210
+ })
211
+
212
+ # use this CallbacksTask that has a bunch of callbacks configured so we
213
+ # can test callback run and call order. Also this CallbacksTask uses
214
+ # callback params which will test all the params handling in callbacks
215
+ # and the task running behavior.
216
+ @task = CallbacksTask.new(@runner)
217
+
218
+ @task.dk_run
219
+ end
220
+
221
+ should "call `run!` and run any callback tasks" do
222
+ assert_equal 1, @call_orders.runner_prepend_before_call_order
223
+ assert_equal 2, @call_orders.prepend_before_call_order
224
+ assert_equal 3, @call_orders.first_before_call_order
225
+ assert_equal 4, @call_orders.second_before_call_order
226
+ assert_equal 5, @call_orders.runner_before_call_order
227
+ assert_equal 6, @call_orders.run_call_order
228
+ assert_equal 7, @call_orders.runner_prepend_after_call_order
229
+ assert_equal 8, @call_orders.prepend_after_call_order
230
+ assert_equal 9, @call_orders.first_after_call_order
231
+ assert_equal 10, @call_orders.second_after_call_order
232
+ assert_equal 11, @call_orders.runner_after_call_order
233
+ end
234
+
235
+ should "log the task run with its runner" do
236
+ runner = test_runner(@task_class)
237
+
238
+ log_task_run_called_with = nil
239
+ Assert.stub(runner, :log_task_run){ |*args| log_task_run_called_with = args }
240
+ task = @task_class.new(runner)
241
+ task.dk_run
242
+
243
+ assert_equal [@task_class], log_task_run_called_with
244
+ end
245
+
246
+ end
247
+
248
+ class RunOnlyOnceTests < RunTests
249
+ desc "with run only once set"
250
+ setup do
251
+ CallbacksTask.run_only_once false
252
+ end
253
+ teardown do
254
+ CallbacksTask.run_only_once false
255
+ end
256
+
257
+ # the logic controlling this is in the runner, however this test exists
258
+ # as sort of a 'system-y' test to ensure the logic at the task level
259
+ should "run only once" do
260
+ @call_orders.reset
261
+ @runner.run(CallbacksTask)
262
+
263
+ # should run the task even though it has already been run by the runner
264
+ assert_equal 6, @call_orders.run_call_order
265
+
266
+ CallbacksTask.run_only_once true
267
+ @call_orders.reset
268
+ @runner.run(CallbacksTask)
269
+
270
+ # should not run the task since it has already been run by the runner
271
+ assert_nil @call_orders.run_call_order
272
+ end
273
+
274
+ end
275
+
276
+ class RunTaskPrivateHelperTests < InitTests
277
+ setup do
278
+ @runner_run_task_called_with = nil
279
+ Assert.stub(@runner, :run_task){ |*args| @runner_run_task_called_with = args }
280
+ end
281
+
282
+ should "run other tasks by calling the runner's `run_task` method" do
283
+ other_task_class = Class.new{ include Dk::Task }
284
+ other_task_params = { Factory.string => Factory.string }
285
+ subject.instance_eval{ run_task(other_task_class, other_task_params) }
286
+
287
+ exp = [other_task_class, other_task_params]
288
+ assert_equal exp, @runner_run_task_called_with
289
+ end
290
+
291
+ end
292
+
293
+ class CmdPrivateHelpersTests < InitTests
294
+
295
+ should "run local cmds, calling to the runner" do
296
+ runner_cmd_called_with = nil
297
+ Assert.stub(@runner, :cmd) do |*args|
298
+ runner_cmd_called_with = args
299
+ Assert.stub_send(@runner, :cmd, *args)
300
+ end
301
+
302
+ cmd_str = Factory.string
303
+ cmd_input = Factory.string
304
+ cmd_opts = { Factory.string => Factory.string }
305
+
306
+ subject.instance_eval{ cmd(cmd_str, cmd_input, cmd_opts) }
307
+ exp = [subject, cmd_str, cmd_input, cmd_opts]
308
+ assert_equal exp, runner_cmd_called_with
309
+
310
+ subject.instance_eval{ cmd(cmd_str) }
311
+ exp = [subject, cmd_str, nil, nil]
312
+ assert_equal exp, runner_cmd_called_with
313
+
314
+ subject.instance_eval{ cmd(cmd_str, cmd_input) }
315
+ exp = [subject, cmd_str, cmd_input, nil]
316
+ assert_equal exp, runner_cmd_called_with
317
+
318
+ subject.instance_eval{ cmd(cmd_str, cmd_opts) }
319
+ exp = [subject, cmd_str, nil, cmd_opts]
320
+ assert_equal exp, runner_cmd_called_with
321
+
322
+ subject.instance_eval{ cmd!(cmd_str, cmd_input, cmd_opts) }
323
+ exp = [subject, cmd_str, cmd_input, cmd_opts]
324
+ assert_equal exp, runner_cmd_called_with
325
+
326
+ subject.instance_eval{ cmd!(cmd_str) }
327
+ exp = [subject, cmd_str, nil, nil]
328
+ assert_equal exp, runner_cmd_called_with
329
+
330
+ subject.instance_eval{ cmd!(cmd_str, cmd_input) }
331
+ exp = [subject, cmd_str, cmd_input, nil]
332
+ assert_equal exp, runner_cmd_called_with
333
+
334
+ subject.instance_eval{ cmd!(cmd_str, cmd_opts) }
335
+ exp = [subject, cmd_str, nil, cmd_opts]
336
+ assert_equal exp, runner_cmd_called_with
337
+ end
338
+
339
+ should "run local cmds and error if not successful" do
340
+ runner_cmd_called_with = nil
341
+ Assert.stub(@runner, :cmd) do |*args|
342
+ runner_cmd_called_with = args
343
+ Assert.stub_send(@runner, :cmd, *args).tap do |cmd_spy|
344
+ Assert.stub(cmd_spy, :success?){ false }
345
+ end
346
+ end
347
+
348
+ cmd_str = Factory.string
349
+ cmd_input = Factory.string
350
+ cmd_opts = { Factory.string => Factory.string }
351
+
352
+ err = assert_raises(CmdRunError) do
353
+ subject.instance_eval{ cmd!(cmd_str, cmd_input, cmd_opts) }
354
+ end
355
+
356
+ exp = "error running `#{cmd_str}`"
357
+ assert_equal exp, err.message
358
+
359
+ exp = [subject, cmd_str, cmd_input, cmd_opts]
360
+ assert_equal exp, runner_cmd_called_with
361
+ end
362
+
363
+ end
364
+
365
+ class SSHPrivateHelpersTests < InitTests
366
+
367
+ should "run ssh cmds, calling to the runner" do
368
+ runner_ssh_called_with = nil
369
+ Assert.stub(@runner, :ssh) do |*args|
370
+ runner_ssh_called_with = args
371
+ Assert.stub_send(@runner, :ssh, *args)
372
+ end
373
+
374
+ cmd_str = Factory.string
375
+ cmd_input = Factory.string
376
+ cmd_given_opts = Factory.ssh_cmd_opts
377
+
378
+ exp_cmd_ssh_opts = @default_ssh_cmd_opts.merge(cmd_given_opts)
379
+
380
+ subject.instance_eval{ ssh(cmd_str, cmd_input, cmd_given_opts) }
381
+ exp = [subject, cmd_str, cmd_input, cmd_given_opts, exp_cmd_ssh_opts]
382
+ assert_equal exp, runner_ssh_called_with
383
+
384
+ subject.instance_eval{ ssh(cmd_str) }
385
+ exp = [subject, cmd_str, nil, nil, @default_ssh_cmd_opts]
386
+ assert_equal exp, runner_ssh_called_with
387
+
388
+ subject.instance_eval{ ssh(cmd_str, cmd_input) }
389
+ exp = [subject, cmd_str, cmd_input, nil, @default_ssh_cmd_opts]
390
+ assert_equal exp, runner_ssh_called_with
391
+
392
+ subject.instance_eval{ ssh(cmd_str, cmd_given_opts) }
393
+ exp = [subject, cmd_str, nil, cmd_given_opts, exp_cmd_ssh_opts]
394
+ assert_equal exp, runner_ssh_called_with
395
+
396
+ subject.instance_eval{ ssh!(cmd_str, cmd_input, cmd_given_opts) }
397
+ exp = [subject, cmd_str, cmd_input, cmd_given_opts, exp_cmd_ssh_opts]
398
+ assert_equal exp, runner_ssh_called_with
399
+
400
+ subject.instance_eval{ ssh!(cmd_str) }
401
+ exp = [subject, cmd_str, nil, nil, @default_ssh_cmd_opts]
402
+ assert_equal exp, runner_ssh_called_with
403
+
404
+ subject.instance_eval{ ssh!(cmd_str, cmd_input) }
405
+ exp = [subject, cmd_str, cmd_input, nil, @default_ssh_cmd_opts]
406
+ assert_equal exp, runner_ssh_called_with
407
+
408
+ subject.instance_eval{ ssh!(cmd_str, cmd_given_opts) }
409
+ exp = [subject, cmd_str, nil, cmd_given_opts, exp_cmd_ssh_opts]
410
+ assert_equal exp, runner_ssh_called_with
411
+ end
412
+
413
+ should "build ssh cmd strs" do
414
+ remote_ssh_called_with = nil
415
+ Assert.stub(Dk::Remote, :ssh_cmd_str){ |*args| remote_ssh_called_with = args }
416
+
417
+ cmd_str = Factory.string
418
+ cmd_opts = {
419
+ :host => Factory.string,
420
+ :ssh_args => Factory.string,
421
+ :host_ssh_args => { Factory.string => Factory.string }
422
+ }
423
+ subject.instance_eval{ ssh_cmd_str(cmd_str, cmd_opts) }
424
+
425
+ exp = [cmd_str, cmd_opts[:host], cmd_opts[:ssh_args], cmd_opts[:host_ssh_args]]
426
+ assert_equal exp, remote_ssh_called_with
427
+ end
428
+
429
+ should "force any given hosts value to an Array" do
430
+ runner_ssh_called_with_opts = nil
431
+ Assert.stub(@runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
432
+
433
+ host = Factory.string
434
+ subject.instance_eval{ ssh(Factory.string, :hosts => host) }
435
+
436
+ exp = [host]
437
+ assert_equal exp, runner_ssh_called_with_opts[:hosts]
438
+ end
439
+
440
+ should "run ssh cmds and error if not successful" do
441
+ runner_ssh_called_with = nil
442
+ Assert.stub(@runner, :ssh) do |*args|
443
+ runner_ssh_called_with = args
444
+ Assert.stub_send(@runner, :ssh, *args).tap do |cmd_spy|
445
+ Assert.stub(cmd_spy, :success?){ false }
446
+ end
447
+ end
448
+
449
+ cmd_str = Factory.string
450
+ cmd_input = Factory.string
451
+ cmd_given_opts = Factory.ssh_cmd_opts
452
+
453
+ err = assert_raises(SSHRunError) do
454
+ subject.instance_eval{ ssh!(cmd_str, cmd_input, cmd_given_opts) }
455
+ end
456
+
457
+ exp = "error running `#{cmd_str}` over ssh"
458
+ assert_equal exp, err.message
459
+
460
+ exp_cmd_ssh_opts = @default_ssh_cmd_opts.merge(cmd_given_opts)
461
+ exp = [subject, cmd_str, cmd_input, cmd_given_opts, exp_cmd_ssh_opts]
462
+ assert_equal exp, runner_ssh_called_with
463
+ end
464
+
465
+ should "use the task's ssh hosts if none are specified" do
466
+ task_class = Class.new{ include Dk::Task; ssh_hosts Factory.hosts; }
467
+ runner = test_runner(task_class)
468
+ task = runner.task
469
+
470
+ runner_ssh_called_with_opts = nil
471
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
472
+
473
+ task.instance_eval{ ssh(Factory.string) }
474
+ assert_equal task_class.ssh_hosts.call, runner_ssh_called_with_opts[:hosts]
475
+ end
476
+
477
+ should "lookup the task's ssh hosts from the runner hosts" do
478
+ hosts = Factory.hosts
479
+ task_class = Class.new{ include Dk::Task; ssh_hosts Factory.string; }
480
+
481
+ runner = test_runner(task_class, :ssh_hosts => {
482
+ task_class.ssh_hosts.call => hosts
483
+ })
484
+ task = runner.task
485
+
486
+ runner_ssh_called_with_opts = nil
487
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
488
+
489
+ task.instance_eval{ ssh(Factory.string) }
490
+ assert_equal hosts, runner_ssh_called_with_opts[:hosts]
491
+ end
492
+
493
+ should "instance eval the task's ssh hosts" do
494
+ hosts = Factory.hosts
495
+ app_hosts = Factory.string
496
+ task_class = Class.new{ include Dk::Task; ssh_hosts{ params['app_hosts'] }; }
497
+
498
+ runner = test_runner(task_class, {
499
+ :params => { 'app_hosts' => app_hosts },
500
+ :ssh_hosts => { app_hosts => hosts }
501
+ })
502
+ task = runner.task
503
+
504
+ runner_ssh_called_with_opts = nil
505
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
506
+
507
+ task.instance_eval{ ssh(Factory.string) }
508
+ assert_equal hosts, runner_ssh_called_with_opts[:hosts]
509
+ end
510
+
511
+ should "lookup given hosts from the runner hosts" do
512
+ hosts = Factory.hosts
513
+ hosts_name = Factory.string
514
+ task_class = Class.new{ include Dk::Task }
515
+
516
+ runner = test_runner(task_class, :ssh_hosts => {
517
+ hosts_name => hosts
518
+ })
519
+ task = runner.task
520
+
521
+ runner_ssh_called_with_opts = nil
522
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
523
+
524
+ task.instance_eval{ ssh(Factory.string, :hosts => hosts_name) }
525
+ assert_equal hosts, runner_ssh_called_with_opts[:hosts]
526
+ end
527
+
528
+ should "use the runner's ssh args if none are given" do
529
+ args = Factory.string
530
+ task_class = Class.new{ include Dk::Task }
531
+ runner = test_runner(task_class, :ssh_args => args)
532
+ task = runner.task
533
+
534
+ runner_ssh_called_with_opts = nil
535
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
536
+
537
+ task.instance_eval{ ssh(Factory.string) }
538
+ assert_equal args, runner_ssh_called_with_opts[:ssh_args]
539
+ end
540
+
541
+ should "use the runner's ssh args to build ssh cmd strs if none are given" do
542
+ ssh_args = Factory.string
543
+ task_class = Class.new{ include Dk::Task }
544
+ runner = test_runner(task_class, :ssh_args => ssh_args)
545
+ task = runner.task
546
+
547
+ remote_ssh_called_with = nil
548
+ Assert.stub(Dk::Remote, :ssh_cmd_str){ |*args| remote_ssh_called_with = args }
549
+
550
+ cmd_str = Factory.string
551
+ cmd_opts = {
552
+ :host => Factory.string,
553
+ :host_ssh_args => { Factory.string => Factory.string }
554
+ }
555
+ task.instance_eval{ ssh_cmd_str(cmd_str, cmd_opts) }
556
+
557
+ exp = [cmd_str, cmd_opts[:host], ssh_args, cmd_opts[:host_ssh_args]]
558
+ assert_equal exp, remote_ssh_called_with
559
+ end
560
+
561
+ should "use the runner's host ssh args if none are given" do
562
+ args = { Factory.string => Factory.string }
563
+ task_class = Class.new{ include Dk::Task }
564
+ runner = test_runner(task_class, :host_ssh_args => args)
565
+ task = runner.task
566
+
567
+ runner_ssh_called_with_opts = nil
568
+ Assert.stub(runner, :ssh){ |_, _, _, _, o| runner_ssh_called_with_opts = o }
569
+
570
+ task.instance_eval{ ssh(Factory.string) }
571
+ assert_equal args, runner_ssh_called_with_opts[:host_ssh_args]
572
+ end
573
+
574
+ should "use the runner's host ssh args to build cmd strs if none are given" do
575
+ ssh_args = { Factory.string => Factory.string }
576
+ task_class = Class.new{ include Dk::Task }
577
+ runner = test_runner(task_class, :host_ssh_args => ssh_args)
578
+ task = runner.task
579
+
580
+ remote_ssh_called_with = nil
581
+ Assert.stub(Dk::Remote, :ssh_cmd_str){ |*args| remote_ssh_called_with = args }
582
+
583
+ cmd_str = Factory.string
584
+ cmd_opts = {
585
+ :host => Factory.string,
586
+ :ssh_args => Factory.string
587
+ }
588
+ task.instance_eval{ ssh_cmd_str(cmd_str, cmd_opts) }
589
+
590
+ exp = [cmd_str, cmd_opts[:host], cmd_opts[:ssh_args], ssh_args]
591
+ assert_equal exp, remote_ssh_called_with
592
+ end
593
+
594
+ end
595
+
596
+ class ParamsPrivateHelpersTests < InitTests
597
+ setup do
598
+ @task_params = { Factory.string => Factory.string }
599
+ end
600
+
601
+ should "call to the runner for `params`" do
602
+ p = @runner.params.keys.first
603
+ assert_equal @runner.params[p], subject.instance_eval{ params[p] }
604
+
605
+ assert_raises(Dk::NoParamError) do
606
+ subject.instance_eval{ params[Factory.string] }
607
+ end
608
+ end
609
+
610
+ should "allow params access that doesn't error if the param is missing" do
611
+ p = @runner.params.keys.first
612
+ assert_equal @runner.params[p], subject.instance_eval{ params.try_param(p) }
613
+ assert_equal @runner.params[p], subject.instance_eval{ try_param(p) }
614
+
615
+ assert_nil subject.instance_eval{ params.try_param(Factory.string) }
616
+ assert_nil subject.instance_eval{ try_param(Factory.string) }
617
+ end
618
+
619
+ should "call to the runner for `set_param`" do
620
+ set_param_called_with = nil
621
+ Assert.stub(@runner, :set_param){ |*args| set_param_called_with = args }
622
+
623
+ key, value = Factory.string, Factory.string
624
+ subject.instance_eval{ set_param(key, value) }
625
+
626
+ exp = [key, value]
627
+ assert_equal exp, set_param_called_with
628
+ end
629
+
630
+ should "merge any given task params" do
631
+ task_w_params = @task_class.new(@runner, @task_params)
632
+
633
+ p = @runner.params.keys.first
634
+ assert_equal @runner.params[p], task_w_params.instance_eval{ params[p] }
635
+
636
+ p = @task_params.keys.first
637
+ assert_equal @task_params[p], task_w_params.instance_eval{ params[p] }
638
+
639
+ assert_raises(Dk::NoParamError) do
640
+ task_w_params.instance_eval{ params[Factory.string] }
641
+ end
642
+ end
643
+
644
+ should "only write task params and not write runner params" do
645
+ p = Factory.string
646
+ val = Factory.string
647
+ subject.instance_eval{ params[p] = val }
648
+
649
+ assert_equal val, subject.instance_eval{ params[p] }
650
+ assert_raises(Dk::NoParamError){ @runner.params[p] }
651
+ end
652
+
653
+ should "set a runner (and task) param using `set_param`" do
654
+ p = Factory.string
655
+ val = Factory.string
656
+ subject.instance_eval{ set_param(p, val) }
657
+
658
+ assert_equal val, subject.instance_eval{ params[p] }
659
+ assert_equal val, @runner.params[p]
660
+ end
661
+
662
+ should "know if either a task or runner param is set" do
663
+ task_w_params = @task_class.new(@runner, @task_params)
664
+
665
+ p = @runner.params.keys.first
666
+ assert_true task_w_params.instance_eval{ param?(p) }
667
+
668
+ p = @task_params.keys.first
669
+ assert_true task_w_params.instance_eval{ param?(p) }
670
+
671
+ assert_false task_w_params.instance_eval{ param?(Factory.string) }
672
+ end
673
+
674
+ end
675
+
676
+ class CallbackPrivateHelpersTests < InitTests
677
+
678
+ should "append callbacks" do
679
+ subj = Factory.string
680
+ cb = Factory.string
681
+ params = Factory.string
682
+
683
+ @runner.add_task_callback('before', Factory.string, Factory.string, {})
684
+ subject.instance_eval{ before(subj, cb, params) }
685
+ callback = @runner.task_callbacks('before', subj).last
686
+ assert_equal cb, callback.task_class
687
+ assert_equal params, callback.params
688
+
689
+ @runner.add_task_callback('after', Factory.string, Factory.string, {})
690
+ subject.instance_eval{ after(subj, cb, params) }
691
+ callback = @runner.task_callbacks('after', subj).last
692
+ assert_equal cb, callback.task_class
693
+ assert_equal params, callback.params
694
+ end
695
+
696
+ should "prepend callbacks" do
697
+ subj = Factory.string
698
+ cb = Factory.string
699
+ params = Factory.string
700
+
701
+ @runner.add_task_callback('prepend_before', Factory.string, Factory.string, {})
702
+ subject.instance_eval{ prepend_before(subj, cb, params) }
703
+ callback = @runner.task_callbacks('prepend_before', subj).first
704
+ assert_equal cb, callback.task_class
705
+ assert_equal params, callback.params
706
+
707
+ @runner.add_task_callback('prepend_after', Factory.string, Factory.string, {})
708
+ subject.instance_eval{ prepend_after(subj, cb, params) }
709
+ callback = @runner.task_callbacks('prepend_after', subj).first
710
+ assert_equal cb, callback.task_class
711
+ assert_equal params, callback.params
712
+ end
713
+
714
+ end
715
+
716
+ class SSHHostsPrivateHelpersTests < InitTests
717
+
718
+ should "know and set its runner's ssh hosts" do
719
+ group_name = Factory.string
720
+ hosts = Factory.hosts
721
+
722
+ assert_equal @runner.ssh_hosts, subject.instance_eval{ ssh_hosts }
723
+ assert_nil subject.instance_eval{ ssh_hosts(group_name) }
724
+
725
+ assert_equal hosts, subject.instance_eval{ ssh_hosts(group_name, hosts) }
726
+ assert_equal hosts, subject.instance_eval{ ssh_hosts(group_name) }
727
+
728
+ exp = @runner_ssh_hosts.merge(group_name => hosts)
729
+ assert_equal exp, @runner.ssh_hosts
730
+ assert_equal @runner.ssh_hosts, subject.instance_eval{ ssh_hosts }
731
+ end
732
+
733
+ end
734
+
735
+ class HaltPrivateHelperTests < InitTests
736
+ setup do
737
+ # build a runs object to pass around to the callback tasks for
738
+ # shared state of what has been run
739
+ @runs = Runs.new([])
740
+
741
+ # build a base runner and task manually so the callback tasks actually
742
+ # run (b/c the test runner doesn't run callbacks)
743
+ @runner = Dk::Runner.new({
744
+ :params => { 'runs' => @runs }
745
+ })
746
+
747
+ # use this HaltTask that has a bunch of callbacks configured so we can
748
+ # test callback halt handling.
749
+ @task = HaltTask.new(@runner)
750
+
751
+ @task.dk_run
752
+ end
753
+
754
+ should "halt just the run! execution (not the callbacks) with `halt`" do
755
+ exp = ['first_before', 'run_before_halt', 'second_after']
756
+ assert_equal exp, @runs.list
757
+ end
758
+
759
+ end
760
+
761
+ class LogPrivateHelpersTests < InitTests
762
+ setup do
763
+ @runner_log_info_called_with = nil
764
+ Assert.stub(@runner, :log_info){ |*args| @runner_log_info_called_with = args }
765
+
766
+ @runner_log_debug_called_with = nil
767
+ Assert.stub(@runner, :log_debug){ |*args| @runner_log_debug_called_with = args }
768
+
769
+ @runner_log_error_called_with = nil
770
+ Assert.stub(@runner, :log_error){ |*args| @runner_log_error_called_with = args }
771
+ end
772
+
773
+ should "log by calling the runner's log methods" do
774
+ msg = Factory.string
775
+ styles = [[], [:bold, :red]].sample
776
+
777
+ subject.instance_eval{ log_info(msg, *styles) }
778
+ assert_equal [msg, *styles], @runner_log_info_called_with
779
+
780
+ subject.instance_eval{ log_debug(msg, *styles) }
781
+ assert_equal [msg, *styles], @runner_log_debug_called_with
782
+
783
+ subject.instance_eval{ log_error(msg, *styles) }
784
+ assert_equal [msg, *styles], @runner_log_error_called_with
785
+ end
786
+
787
+ end
788
+
789
+ class TestHelpersTests < UnitTests
790
+ desc "TestHelpers"
791
+ setup do
792
+ @args = {
793
+ :params => { Factory.string => Factory.string }
794
+ }
795
+
796
+ context_class = Class.new{ include Dk::Task::TestHelpers }
797
+ @context = context_class.new
798
+ end
799
+ subject{ @context }
800
+
801
+ should have_imeths :test_runner, :test_task, :ssh_cmd_str
802
+
803
+ should "build a test runner for a given handler class" do
804
+ runner = subject.test_runner(@task_class, @args)
805
+
806
+ assert_kind_of Dk::TestRunner, runner
807
+ assert_equal @task_class, runner.task_class
808
+ assert_equal @args[:params], runner.params
809
+ end
810
+
811
+ should "return an initialized task instance" do
812
+ task = subject.test_task(@task_class, @args)
813
+ assert_kind_of @task_class, task
814
+
815
+ exp = subject.test_runner(@task_class, @args).task
816
+ assert_equal exp, task
817
+ end
818
+
819
+ should "build task ssh cmd strs" do
820
+ task = subject.test_task(@task_class)
821
+ cmd_str = Factory.string
822
+ cmd_opts = {
823
+ :host => Factory.string,
824
+ :ssh_args => Factory.string,
825
+ :host_ssh_args => { Factory.string => Factory.string }
826
+ }
827
+
828
+ exp = task.instance_eval{ ssh_cmd_str(cmd_str, cmd_opts) }
829
+ assert_equal exp, subject.ssh_cmd_str(task, cmd_str, cmd_opts)
830
+ end
831
+
832
+ end
833
+
834
+ class CallOrders
835
+ attr_reader :first_before_call_order, :second_before_call_order
836
+ attr_reader :prepend_before_call_order
837
+ attr_reader :runner_prepend_before_call_order
838
+ attr_reader :runner_before_call_order
839
+ attr_reader :first_after_call_order, :second_after_call_order
840
+ attr_reader :prepend_after_call_order
841
+ attr_reader :runner_prepend_after_call_order
842
+ attr_reader :runner_after_call_order
843
+ attr_reader :run_call_order
844
+
845
+ def first_before; @first_before_call_order = next_call_order; end
846
+ def second_before; @second_before_call_order = next_call_order; end
847
+ def prepend_before; @prepend_before_call_order = next_call_order; end
848
+ def runner_prepend_before; @runner_prepend_before_call_order = next_call_order; end
849
+ def runner_before; @runner_before_call_order = next_call_order; end
850
+ def first_after; @first_after_call_order = next_call_order; end
851
+ def second_after; @second_after_call_order = next_call_order; end
852
+ def prepend_after; @prepend_after_call_order = next_call_order; end
853
+ def runner_prepend_after; @runner_prepend_after_call_order = next_call_order; end
854
+ def runner_after; @runner_after_call_order = next_call_order; end
855
+
856
+ def run; @run_call_order = next_call_order; end
857
+
858
+ def reset
859
+ @first_before_call_order = nil
860
+ @second_before_call_order = nil
861
+ @prepend_before_call_order = nil
862
+ @runner_prepend_before_call_order = nil
863
+ @runner_before_call_order = nil
864
+ @first_after_call_order = nil
865
+ @second_after_call_order = nil
866
+ @prepend_after_call_order = nil
867
+ @runner_prepend_after_call_order = nil
868
+ @runner_after_call_order = nil
869
+ @run_call_order = nil
870
+ @order = nil
871
+ end
872
+
873
+ private
874
+
875
+ def next_call_order
876
+ @order ||= 0
877
+ @order += 1
878
+ end
879
+ end
880
+
881
+ class CallbackTask
882
+ include Dk::Task
883
+
884
+ def run!
885
+ params['call_orders'].send(params['callback'])
886
+ end
887
+ end
888
+
889
+ class CallbacksTask
890
+ include Dk::Task
891
+
892
+ # note: callbacks are intentionally duplicated here to help test that
893
+ # duplicate callbacks are not allowed. if these duplicate callbacks each
894
+ # ran, they would break the callback order tests.
895
+
896
+ before CallbackTask, 'callback' => 'first_before'
897
+ before CallbackTask, 'callback' => 'first_before'
898
+ before CallbackTask, 'callback' => 'second_before'
899
+ before CallbackTask, 'callback' => 'second_before'
900
+ prepend_before CallbackTask, 'callback' => 'prepend_before'
901
+ prepend_before CallbackTask, 'callback' => 'prepend_before'
902
+
903
+ after CallbackTask, 'callback' => 'first_after'
904
+ after CallbackTask, 'callback' => 'first_after'
905
+ after CallbackTask, 'callback' => 'second_after'
906
+ after CallbackTask, 'callback' => 'second_after'
907
+ prepend_after CallbackTask, 'callback' => 'prepend_after'
908
+ prepend_after CallbackTask, 'callback' => 'prepend_after'
909
+
910
+ run_only_once false
911
+
912
+ def run!
913
+ params['call_orders'].run
914
+ end
915
+ end
916
+
917
+ Runs = Struct.new(:list)
918
+
919
+ class HaltCallbackTask
920
+ include Dk::Task
921
+
922
+ def run!
923
+ halt if params.key?('halt')
924
+ params['runs'].list << params['run']
925
+ end
926
+ end
927
+
928
+ class HaltTask
929
+ include Dk::Task
930
+
931
+ before HaltCallbackTask, 'run' => 'first_before'
932
+ before HaltCallbackTask, 'run' => 'second_before', 'halt' => true
933
+ after HaltCallbackTask, 'run' => 'first_after', 'halt' => true
934
+ after HaltCallbackTask, 'run' => 'second_after'
935
+
936
+ def run!
937
+ params['runs'].list << 'run_before_halt'
938
+ halt
939
+ params['runs'].list << 'run_after_halt'
940
+ end
941
+ end
942
+
943
+ end