dk 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/README.md +643 -1
- data/bin/dk +7 -0
- data/dk.gemspec +7 -3
- data/lib/dk/ansi.rb +98 -0
- data/lib/dk/cli.rb +173 -0
- data/lib/dk/config.rb +217 -0
- data/lib/dk/config_runner.rb +24 -0
- data/lib/dk/dk_runner.rb +13 -0
- data/lib/dk/dry_runner.rb +43 -0
- data/lib/dk/has_set_param.rb +42 -0
- data/lib/dk/has_ssh_opts.rb +36 -0
- data/lib/dk/has_the_runs.rb +23 -0
- data/lib/dk/has_the_stubs.rb +116 -0
- data/lib/dk/local.rb +84 -0
- data/lib/dk/null_logger.rb +13 -0
- data/lib/dk/remote.rb +132 -0
- data/lib/dk/runner.rb +202 -0
- data/lib/dk/task.rb +266 -0
- data/lib/dk/task_run.rb +17 -0
- data/lib/dk/test_runner.rb +54 -0
- data/lib/dk/tree_runner.rb +64 -0
- data/lib/dk/version.rb +1 -1
- data/lib/dk.rb +23 -1
- data/test/helper.rb +6 -1
- data/test/support/config/dk.rb +7 -0
- data/test/support/config/task_defs.rb +10 -0
- data/test/support/factory.rb +38 -0
- data/test/support/log/.gitkeep +0 -0
- data/test/system/has_the_stubs_tests.rb +355 -0
- data/test/system/runner_tests.rb +222 -0
- data/test/unit/ansi_tests.rb +40 -0
- data/test/unit/cli_tests.rb +317 -0
- data/test/unit/config_runner_tests.rb +60 -0
- data/test/unit/config_tests.rb +427 -0
- data/test/unit/dk_runner_tests.rb +34 -0
- data/test/unit/dk_tests.rb +49 -0
- data/test/unit/dry_runner_tests.rb +71 -0
- data/test/unit/has_set_param_tests.rb +46 -0
- data/test/unit/has_ssh_opts_tests.rb +81 -0
- data/test/unit/has_the_runs_tests.rb +37 -0
- data/test/unit/has_the_stubs_tests.rb +279 -0
- data/test/unit/local_tests.rb +174 -0
- data/test/unit/null_logger_tests.rb +17 -0
- data/test/unit/remote_tests.rb +330 -0
- data/test/unit/runner_tests.rb +398 -0
- data/test/unit/task_run_tests.rb +40 -0
- data/test/unit/task_tests.rb +943 -0
- data/test/unit/test_runner_tests.rb +189 -0
- data/test/unit/tree_runner_tests.rb +152 -0
- metadata +106 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
SHA1:
|
3
|
-
data.tar.gz: d2d1893fb49305eb768384b4d9bf8a60a41552b0
|
4
|
-
metadata.gz: d8ed8258fd4b6ea24b0a0955fb39fe542a919fd5
|
5
2
|
SHA512:
|
6
|
-
data.tar.gz:
|
7
|
-
metadata.gz:
|
3
|
+
data.tar.gz: 6d18c6023b43628117f27c2b7c60441a125ba6f126cd40a712cf635e7f9956728b68d94387ccfee8d4a4b26047dd1de48328304c428c5477727aa560238c46b9
|
4
|
+
metadata.gz: c3224e1ceea343b4a365dde9955d30e4cb6062365053e44a0fe17c00b90a32363365135259fdaf6b3651a24e6bff0b7f2fc9a704c0902fdf85f6460391610778
|
5
|
+
SHA1:
|
6
|
+
data.tar.gz: 5dc5bf7f2a83491664acdb2a9d55112149eed2e3
|
7
|
+
metadata.gz: 494082902e15484e13409bad7f209d6342ac671a
|
data/README.md
CHANGED
@@ -6,7 +6,649 @@ This is some automated task runner thingy ala cap/rake (except without all the d
|
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
|
9
|
+
First define a task:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'dk/task'
|
13
|
+
|
14
|
+
class MyTask
|
15
|
+
include Dk::Task
|
16
|
+
|
17
|
+
desc "my task that does something great"
|
18
|
+
|
19
|
+
def run!
|
20
|
+
log_info "this task does something"
|
21
|
+
|
22
|
+
# ... do something ...
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
Now route this task with a name so it can be run from the CLI:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
# in config/dk.rb or whatever
|
32
|
+
require 'dk'
|
33
|
+
|
34
|
+
Dk.configure do
|
35
|
+
|
36
|
+
task 'my-task', MyTask
|
37
|
+
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Now run this task using the CLI:
|
42
|
+
|
43
|
+
```
|
44
|
+
$ dk -T
|
45
|
+
my-task # my task that does something great
|
46
|
+
$ dk my-task
|
47
|
+
```
|
48
|
+
|
49
|
+
### CLI
|
50
|
+
|
51
|
+
```
|
52
|
+
$ dk --help
|
53
|
+
Usage: dk [TASKS] [options]
|
54
|
+
|
55
|
+
Tasks:
|
56
|
+
my-other-task # my other task that does something great
|
57
|
+
my-task # my task that does something great
|
58
|
+
|
59
|
+
Options:
|
60
|
+
-T, --[no-]list-tasks list all tasks available to run
|
61
|
+
-d, --[no-]dry-run run the tasks without executing any local/remote cmds
|
62
|
+
-t, --[no-]tree print out the tree of tasks/sub-tasks that would be run
|
63
|
+
-v, --[no-]verbose run tasks showing verbose (ie debug log level) details
|
64
|
+
--version
|
65
|
+
--help
|
66
|
+
```
|
67
|
+
|
68
|
+
##### `--list-tasks` option
|
69
|
+
|
70
|
+
Use this option (or its `-T` abbrev) to list out all tasks that are available to run. This is similar to the `-T` option on cap and rake.
|
71
|
+
|
72
|
+
```
|
73
|
+
$ dk -T
|
74
|
+
my-other-task # my other task that does something great
|
75
|
+
my-task # my task that does something great
|
76
|
+
```
|
77
|
+
|
78
|
+
##### `--dry-run` option
|
79
|
+
|
80
|
+
This option runs the tasks and logs everything just like the live runner does. However, this runner disables all system commands: both local commands and remote ssh commands. Use this to see what a task would do do without running any of the system commands.
|
81
|
+
|
82
|
+
##### `--tree` option
|
83
|
+
|
84
|
+
This option runs the tasks like the live runner does and disables all system commands like the `--dry-run` option does. However, this option also disables all logging and tracks all tasks and sub-tasks that are run. It then outputs the tree of tasks that was run:
|
85
|
+
|
86
|
+
TODO: show task tree output example
|
87
|
+
|
88
|
+
Use this to show the user all the tasks/sub-tasks that are run and which parent tasks are running them.
|
89
|
+
|
90
|
+
##### `--verbose` option
|
91
|
+
|
92
|
+
This option runs tasks showing more verbose output/details (ie it sets the logger's stdout log level to 'debug'). All Task `log_debug` messages will be shown on stdout with this option. This option also makes the stdout and file logs identical.
|
93
|
+
|
94
|
+
### Config
|
95
|
+
|
96
|
+
Dk stores settings in a config. To modify the settings add a configure block:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
require 'dk'
|
100
|
+
|
101
|
+
Dk.configure do
|
102
|
+
|
103
|
+
# settings go here...
|
104
|
+
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
There are a number of DSL settings that can be configured. Use these to set param values, set default ssh settings, configure tasks that can be called from the CLI, etc.
|
109
|
+
|
110
|
+
##### `set_param`
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
require 'dk'
|
114
|
+
|
115
|
+
Dk.configure do
|
116
|
+
|
117
|
+
set_param 'app_name', 'myapp'
|
118
|
+
set_param 'number_of_things', 5
|
119
|
+
# ...
|
120
|
+
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
Use the `set_param` method to set new global param values. Any tasks that are run will have these param values available to them using the tasks's `params` helper method.
|
125
|
+
|
126
|
+
##### `before`, `prepend_before`, `after`, `prepend_after`
|
127
|
+
|
128
|
+
You can configure tasks as callbacks on other tasks using these helper methods:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
require 'dk'
|
132
|
+
|
133
|
+
Dk.configure do
|
134
|
+
|
135
|
+
before MyTask, MyBeforeTask
|
136
|
+
prepend_before MyTask, MyOtherBeforeTask, 'some_param' => 'some_value'
|
137
|
+
after MyTask, MyAfterTask, 'some_param' => 'some_value'
|
138
|
+
prepend_after MyTask, MyOtherAfterTask
|
139
|
+
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
Each callback can be optionally configured with a set of params. Callbacks can either be appended or prepended (this can be especially useful when you want to control the order 3rd-party tasks are run in).
|
144
|
+
|
145
|
+
The callback tasks will be run in the order they are added before/after the `run!` method of the task they are added to. The [`halt` task helper](https://github.com/redding/dk#halt) does not stop these callbacks from running.
|
146
|
+
|
147
|
+
##### `ssh_hosts`, `ssh_args`, `host_ssh_args`
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
require 'dk'
|
151
|
+
|
152
|
+
Dk.configure do
|
153
|
+
|
154
|
+
ssh_hosts 'all_servers', '1.example.com',
|
155
|
+
'2.example.com',
|
156
|
+
'3.example.com',
|
157
|
+
'user@4.example.com',
|
158
|
+
'user@5.example.com'
|
159
|
+
|
160
|
+
ssh_hosts 'primary_server', '1.example.com'
|
161
|
+
|
162
|
+
ssh_hosts 'web_servers', '1.example.com',
|
163
|
+
'2.example.com'
|
164
|
+
|
165
|
+
ssh_hosts 'db_server', '3.example.com'
|
166
|
+
|
167
|
+
ssh_hosts 'bg_servers', 'user@4.example.com',
|
168
|
+
'user@5.example.com'
|
169
|
+
|
170
|
+
# these are custom args to use on all SSH cmds
|
171
|
+
ssh_args "-o ForwardAgent=yes "\
|
172
|
+
"-o ControlMaster=auto "\
|
173
|
+
"-o ControlPersist=60s "\
|
174
|
+
"-o UserKnownHostsFile=/dev/null "\
|
175
|
+
"-o StrictHostKeyChecking=no "\
|
176
|
+
"-o ConnectTimeout=10 "\
|
177
|
+
"-o LogLevel=quiet "
|
178
|
+
|
179
|
+
# these two hosts use custom SSH ports
|
180
|
+
host_ssh_args 'user@4.example.com', '-p 12345'
|
181
|
+
host_ssh_args 'user@5.example.com', '-p 12345'
|
182
|
+
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
Use the `ssh_hosts` method to define a named set of hosts. These hosts can now be referred to by name when running `ssh` cmds in tasks.
|
187
|
+
|
188
|
+
Use the `ssh_args` and `host_ssh_args` methods to configure ssh cmd arguments to apply to all SSH cmds. The host-specific args are only applied to SSH cmds run on the specific host.
|
189
|
+
|
190
|
+
##### `log_pattern`, `log_file`, `log_file_pattern`
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
require 'dk'
|
194
|
+
|
195
|
+
Dk.configure do
|
196
|
+
|
197
|
+
log_pattern '[%-5l] : %m\n' # [INFO] : blah blah\n"
|
198
|
+
|
199
|
+
log_file "log/dk.log" # log all task run details to this file
|
200
|
+
log_file_pattern '[%d %-5l] : %m\n' # [<datetime> INFO] : blah blah\n"
|
201
|
+
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
Use the `log_pattern` and `log_file_pattern` methods to override the default log entry format for stdout and file logging respectively. By default, stdout logs just log the message while the file logs log the date level and message. Uese these to tweak as desired. Dk uses [Logsly](https://github.com/redding/logsly) for its loggers so check out its README for [details on using patterns](https://github.com/redding/logsly#patterns).
|
206
|
+
|
207
|
+
Use the `log_file` method to turn on file logging. If given a file path, Dk will log all task run details (verbosely) to the file. This is handy when problems occur running tasks in non-verbose mode. File logging is always done verbosely so you can use this to refere to the details of previous task runs even though you may not have seen these details in your stdout logs.
|
208
|
+
|
209
|
+
##### `task`
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
require 'dk'
|
213
|
+
|
214
|
+
Dk.configure do
|
215
|
+
|
216
|
+
task 'deploy', MyDeployTask
|
217
|
+
task 'deploy:setup' MyDeploySetupTask
|
218
|
+
|
219
|
+
# ...
|
220
|
+
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
224
|
+
Use the `task` method to configure tasks that are runnable via the CLI. This also will display information about the task when using the `--help option in the CLI.
|
225
|
+
|
226
|
+
**Note**: only tasks configured using this method will be runnable from the CLI.
|
227
|
+
|
228
|
+
##### `stub_dry_tree_cmd`, `stub_dry_tree_ssh`
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
require 'dk'
|
232
|
+
|
233
|
+
Dk.configure do
|
234
|
+
|
235
|
+
stub_dry_tree_cmd("ls -la") do |spy| # spy is a Local::CmdSpy
|
236
|
+
spy.stdout = "..."
|
237
|
+
end
|
238
|
+
|
239
|
+
stub_dry_tree_ssh("ls -la") do |spy| # spy is a Remote::CmdSpy
|
240
|
+
spy.exitstatus = 1 # simulare the ssh call failing
|
241
|
+
end
|
242
|
+
|
243
|
+
# ...
|
244
|
+
|
245
|
+
end
|
246
|
+
```
|
247
|
+
|
248
|
+
Use the `stub_dry_tree_cmd` and `stub_dry_tree_ssh` methods to add cmd and ssh stubs when using `--dry-run` or `--tree`. This can be used to control the stdout, stderr or exitstatus of a command. This is useful when a task uses the output of one command for another command or when the task does different logic depending on if a command succeeds or fails.
|
249
|
+
|
250
|
+
### Task
|
251
|
+
|
252
|
+
#### Helper Methods
|
253
|
+
|
254
|
+
The `Dk::Task` mixin provides a bunch of helper methods to make writing tasks easier and for commonizing common functions.
|
255
|
+
|
256
|
+
##### `params`, `set_param`, `param?`, `try_param`
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
require 'dk/task'
|
260
|
+
|
261
|
+
class MyTask
|
262
|
+
include Dk::Task
|
263
|
+
|
264
|
+
def run!
|
265
|
+
param?('some_param') #=> true
|
266
|
+
params['some_param'] #=> "some value"
|
267
|
+
try_param('some_param') #=> "some value"
|
268
|
+
|
269
|
+
param?('some_other_param') #=> false
|
270
|
+
params['some_other_param'] #=> Dk::NoParamError
|
271
|
+
try_param('some_other_param') #=> nil
|
272
|
+
|
273
|
+
set_param('some_other_param', 'some other value')
|
274
|
+
param?('some_other_param') #=> true
|
275
|
+
params['some_other_param'] #=> "some other value"
|
276
|
+
try_param('some_other_param') #=> "some other value"
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
Use the `param` helper to access named params that the task was run with. Params can be added two ways: globally [from the main config](https://github.com/redding/dk#set_param) or from [callback definitions](https://github.com/redding/dk#task-callbacks) and [`run_task` calls](https://github.com/redding/dk#run_task).
|
283
|
+
|
284
|
+
Use the `set_param` method to set new global param values like you would on the main config. Any subsequent tasks that are run will have these param values available to them.
|
285
|
+
|
286
|
+
Use the `param?` method to check whether a specific param has been set. Prefer this over `params.key?` as the task params have special logic for interacting with any runner params that makes the traditional `key?` method unreliable.
|
287
|
+
|
288
|
+
By default, the params will raise an exception if you try and access a missing key (it will raise Dk::NoParamerror). The idea is that Dk will loudly notify you if you are accessing a param you expect to be set and it is not set. However, this may not be appropriate for every scenario, therefore you can use the `try_param` helper and it will just return `nil` if the param is not set.
|
289
|
+
|
290
|
+
##### `before`, `prepend_before`, `after`, `prepend_after`
|
291
|
+
|
292
|
+
[Like in the Config](https://github.com/redding/dk#before-prepend_before-after-prepend_after), you can add tasks as callbacks on other tasks using these helper methods:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
require 'dk/task'
|
296
|
+
|
297
|
+
class MyTask
|
298
|
+
include Dk::Task
|
299
|
+
|
300
|
+
def run!
|
301
|
+
before SomeTask, MyBeforeTask
|
302
|
+
prepend_before SomeTask, MyOtherBeforeTask, 'some_param' => 'some_value'
|
303
|
+
after SomeTask, MyAfterTask, 'some_param' => 'some_value'
|
304
|
+
prepend_after SomeTask, MyOtherAfterTask
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
310
|
+
Each callback can be optionally configured with a set of params. Callbacks can either be appended or prepended (this can be especially useful when you want to control the order 3rd-party tasks are run in). Once a callback is added, it works just as it would if added via the Config.
|
311
|
+
|
312
|
+
##### `ssh_hosts`
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
require 'dk/task'
|
316
|
+
|
317
|
+
class MyTask
|
318
|
+
include Dk::Task
|
319
|
+
|
320
|
+
def run!
|
321
|
+
ssh_hosts('my-app-servers') # => nil
|
322
|
+
ssh_hosts('my-web-servers') # => nil
|
323
|
+
|
324
|
+
ssh_hosts 'my-app-servers', '1.example.com'
|
325
|
+
ssh_hosts 'my-web-servers', '2.example.com', '3.example.com'
|
326
|
+
|
327
|
+
ssh_hosts('my-app-servers') # => ['1.example.com']
|
328
|
+
ssh_hosts('my-web-servers') # => ['2.example.com', '3.example.com']
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
Use the `ssh_hosts` method to set new ssh host lists values like you would on the main config. Any subsequent tasks that are run will have these ssh hosts available to their `ssh` commands.
|
335
|
+
|
336
|
+
##### `run_task`
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
require 'dk/task'
|
340
|
+
require 'my_other_task'
|
341
|
+
|
342
|
+
class MyTask
|
343
|
+
include Dk::Task
|
344
|
+
|
345
|
+
def run!
|
346
|
+
# ... do something before ...
|
347
|
+
|
348
|
+
run_task MyOtherTask, 'some_param' => 'some value'
|
349
|
+
|
350
|
+
# ... do something after ...
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
```
|
355
|
+
|
356
|
+
Use the `run_task` helper to run other tasks. This method takes an optional set of param values. Any params given will be merged onto the global config params and made available to just the task being run.
|
357
|
+
|
358
|
+
##### `cmd`, `cmd!`
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
require 'dk/task'
|
362
|
+
|
363
|
+
class MyTask
|
364
|
+
include Dk::Task
|
365
|
+
|
366
|
+
def run!
|
367
|
+
cmd "ls -la", :env => { 'PWD' => '/path/to/some/dir' }
|
368
|
+
cmd! "test -d some_file"
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
```
|
373
|
+
|
374
|
+
Use the `cmd` helper to run local system cmds. Pass it a string system command to run and it runs it using [Scmd](https://github.com/redding/scmd). You can [optionally pass in an `:env` param](https://github.com/redding/scmd#environment-variables) with any ENV vars that need to be set. A `Dk::Local::Cmd` object is returned so you can access data such as the `stdout`, `stderr` and whether the command was successful or not.
|
375
|
+
|
376
|
+
The `cmd!` helper is identical to the `cmd` helper except that it raises a `Dk::Task::CmdRunError` if the command was not successful.
|
377
|
+
|
378
|
+
##### `ssh`, `ssh!`
|
379
|
+
|
380
|
+
```ruby
|
381
|
+
require 'dk/task'
|
382
|
+
|
383
|
+
class MyTask
|
384
|
+
include Dk::Task
|
385
|
+
|
386
|
+
def run!
|
387
|
+
hosts = ['1.example.com', 'user@2.example.com']
|
388
|
+
ssh "ls -la", :hosts => hosts
|
389
|
+
ssh! "test -d some_file", :hosts => hosts
|
390
|
+
end
|
391
|
+
|
392
|
+
end
|
393
|
+
```
|
394
|
+
|
395
|
+
Use the `ssh` helper to run remote system cmds on hosts using ssh. Like the normal `cmd*` helpers, pass it a string system command and it runs the command on each host using by creating a local system cmd that runs ssh. Like `cmd*` you can optionally pass in an `:env` param with any ENV vars that need to be set locally. Similare to `cmd*`, a `Dk::Remote::Cmd` object is returned so you can access whether the command was successful or not.
|
396
|
+
|
397
|
+
The `ssh!` helper is identical to the `ssh` helper except that it raises a `Dk::Task::SSHRunError` if the command was not successful.
|
398
|
+
|
399
|
+
##### `:dry_tree_run` cmd/ssh opt
|
400
|
+
|
401
|
+
```ruby
|
402
|
+
require 'dk/task'
|
403
|
+
|
404
|
+
class MyTask
|
405
|
+
include Dk::Task
|
406
|
+
|
407
|
+
def run!
|
408
|
+
cmd! "test -d some_file", :dry_tree_run => true
|
409
|
+
ssh! "test -d some_file", :dry_tree_run => true
|
410
|
+
end
|
411
|
+
|
412
|
+
end
|
413
|
+
```
|
414
|
+
|
415
|
+
Use this option to force the cmd/ssh to *always* run, even using the `--dry-run` and `--tree` CLI options (which put Scmd in test mode and don't run any cmds by default). The idea is that some cmds are essential to the running of the task and if they don't actually run, the task will error out. This is handy for tasks that don't change anything they just read data and that data is used to determine how a task should proceed. This allows you to still get the advantages of the dry run and tree CLI options.
|
416
|
+
|
417
|
+
##### `halt`
|
418
|
+
|
419
|
+
```ruby
|
420
|
+
require 'dk/task'
|
421
|
+
|
422
|
+
class MyTask
|
423
|
+
include Dk::Task
|
424
|
+
|
425
|
+
def run!
|
426
|
+
# ... do something ...
|
427
|
+
|
428
|
+
halt if nothing_more_to_do
|
429
|
+
|
430
|
+
# ... otherwise keep going ...
|
431
|
+
end
|
432
|
+
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
436
|
+
Use the `halt` helper to stop executing the current task. This doesn't halt the entire run (callbacks, subsequent tasks, etc). It only halts the current task. If you want to stop running everything, just raise an exception.
|
437
|
+
|
438
|
+
##### `log_info`, `log_debug`, `log_error`
|
439
|
+
|
440
|
+
```ruby
|
441
|
+
require 'dk/task'
|
442
|
+
|
443
|
+
class MyTask
|
444
|
+
include Dk::Task
|
445
|
+
|
446
|
+
def run!
|
447
|
+
log_info "will always show up in the CLI output"
|
448
|
+
log_debug "will only show up in the CLI output in verbose mode"
|
449
|
+
log_error "will always show, but has special error handling"
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
453
|
+
```
|
454
|
+
|
455
|
+
Use the `log_*` helpers to log information as the task is running. Each corresponds to a logger level. The CLI logs to stdout on the INFO level by default. When run in verbose mode, it logs to stdout on the DEBUG level. If an optional log file has been configured, the CLI will log to the file on DEBUG level regardless of any verbose mode setting.
|
456
|
+
|
457
|
+
You can optionally style your log messages:
|
458
|
+
|
459
|
+
```ruby
|
460
|
+
log_info "my message", :red, :on_white
|
461
|
+
log_info "my " + Dk::Ansi.styled_msg("special", :bold, :blue) + " message"
|
462
|
+
```
|
463
|
+
|
464
|
+
See `Dk::Ansi::CODES.keys` for a list of available style names.
|
465
|
+
|
466
|
+
#### Task Descriptions
|
467
|
+
|
468
|
+
```ruby
|
469
|
+
require 'dk/task'
|
470
|
+
|
471
|
+
class MyTask
|
472
|
+
include Dk::Task
|
473
|
+
|
474
|
+
desc "This is a task that does something"
|
475
|
+
|
476
|
+
def run!
|
477
|
+
# ... do something ...
|
478
|
+
end
|
479
|
+
|
480
|
+
end
|
481
|
+
```
|
482
|
+
|
483
|
+
The descriptions of any routed tasks will be displayed when running `--help` in the CLI.
|
484
|
+
|
485
|
+
#### Task Callbacks
|
486
|
+
|
487
|
+
You can configure other tasks as callbacks to your task:
|
488
|
+
|
489
|
+
```ruby
|
490
|
+
require 'dk/task'
|
491
|
+
|
492
|
+
class MyTask
|
493
|
+
include Dk::Task
|
494
|
+
|
495
|
+
before MyBeforeTask
|
496
|
+
prepend_before MyOtherBeforeTask, 'some_param' => 'some_value'
|
497
|
+
after MyAfterTask, 'some_param' => 'some_value'
|
498
|
+
prepend_after MyOtherAfterTask
|
499
|
+
|
500
|
+
def run!
|
501
|
+
# ... do something ...
|
502
|
+
end
|
503
|
+
|
504
|
+
end
|
505
|
+
```
|
506
|
+
|
507
|
+
Each callback can be optionally configured with a set of params. These tasks will be run in the order they are added before/after the `run!` method of the current task. The [`halt` helper](https://github.com/redding/dk#halt) does not stop these callbacks from running.
|
508
|
+
|
509
|
+
#### Default SSH Hosts
|
510
|
+
|
511
|
+
You can configure a default list of hosts to use for ssh commands made in a Task. These hosts will be used on all commands that don't specify a custom `:hosts` option:
|
512
|
+
|
513
|
+
```ruby
|
514
|
+
require 'dk/task'
|
515
|
+
|
516
|
+
class MyTask
|
517
|
+
include Dk::Task
|
518
|
+
|
519
|
+
ssh_hosts ['1.example.com', 'user@2.example.com']
|
520
|
+
|
521
|
+
def run!
|
522
|
+
ssh('ls -la') # => will ssh to 1.example.com and user@2.example.com
|
523
|
+
ssh('ls -la', :hosts => ['3.example.com']) # => will ssh to 3.example.com
|
524
|
+
end
|
525
|
+
|
526
|
+
end
|
527
|
+
```
|
528
|
+
|
529
|
+
You can also specify a named list of hosts that have been configured:
|
530
|
+
|
531
|
+
```ruby
|
532
|
+
require 'dk/task'
|
533
|
+
|
534
|
+
class MyTask
|
535
|
+
include Dk::Task
|
536
|
+
|
537
|
+
ssh_hosts 'my-app-servers'
|
538
|
+
|
539
|
+
def run!
|
540
|
+
ssh('ls -la') # => will ssh to the configured 'my-app-servers' hosts
|
541
|
+
end
|
542
|
+
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
You can also specify a proc that will be instance eval'd on the task instance:
|
547
|
+
|
548
|
+
```ruby
|
549
|
+
require 'dk/task'
|
550
|
+
|
551
|
+
class MyTask
|
552
|
+
include Dk::Task
|
553
|
+
|
554
|
+
ssh_hosts{ params['some-servers'] }
|
555
|
+
|
556
|
+
def run!
|
557
|
+
ssh('ls -la') # => will ssh to the hosts specified by the 'some-servers' param
|
558
|
+
end
|
559
|
+
|
560
|
+
end
|
561
|
+
```
|
562
|
+
|
563
|
+
#### Ensure Tasks Only Run Once
|
564
|
+
|
565
|
+
```ruby
|
566
|
+
require 'dk/task'
|
567
|
+
|
568
|
+
class MyTask
|
569
|
+
include Dk::Task
|
570
|
+
|
571
|
+
run_only_once true
|
572
|
+
|
573
|
+
def run!
|
574
|
+
# ... do something ...
|
575
|
+
end
|
576
|
+
|
577
|
+
end
|
578
|
+
```
|
579
|
+
|
580
|
+
Use this setting to ensure that a task only runs once no matter how many other tasks or sub-tasks either run it manually or configure it as a callback. This is useful for "gatekeeper" tasks such as tasks that validate params, etc. By default, tasks can run multiple times.
|
581
|
+
|
582
|
+
#### Testing Tasks
|
583
|
+
|
584
|
+
Dk comes with a test runner and some test helpers to assist in unit testing tasks. The test runner doesn't run any callback tasks and captures spies for the task, cmd and ssh calls it runs. It also turns off any logging.
|
585
|
+
|
586
|
+
```ruby
|
587
|
+
# in your test file or whatever
|
588
|
+
|
589
|
+
include Dk::Task::TestHelpers
|
590
|
+
|
591
|
+
test "my task should do something" do
|
592
|
+
runner = test_runner(MyTask)
|
593
|
+
runner.run
|
594
|
+
runner.runs #=> [TaskRun, Local::CmdSpy, Remote::CmdSpy, ... ]
|
595
|
+
|
596
|
+
# make assertions that the logic you expect to run actually ran
|
597
|
+
task = runner.task #=> MyTask instance
|
598
|
+
|
599
|
+
# make assertions about your task instance if needed
|
600
|
+
end
|
601
|
+
```
|
602
|
+
|
603
|
+
Dk's test helpers include methods for stubbing cmd and ssh calls. This allows controlling cmd/ssh behavior such as exit status, stdout and stderr. If a task expects to use the stdout/stderr or does special handling when a call errors then the stubbing methods can be used for testing.
|
604
|
+
|
605
|
+
```ruby
|
606
|
+
# in your test file or whatever
|
607
|
+
|
608
|
+
include Dk::Task::TestHelpers
|
609
|
+
|
610
|
+
test "my task should do something" do
|
611
|
+
runner = test_runner(MyTask)
|
612
|
+
runner.stub_cmd("ls -la") do |spy| # spy is a Local::CmdSpy
|
613
|
+
spy.stdout = "..."
|
614
|
+
end
|
615
|
+
runner.stub_ssh("ls -la", :input => 'whatever') do |spy| # spy is a Remote::CmdSpy
|
616
|
+
spy.exitstatus = 1 # simulare the ssh call failing
|
617
|
+
end
|
618
|
+
|
619
|
+
# ....
|
620
|
+
end
|
621
|
+
```
|
622
|
+
|
623
|
+
You can even stub with procs. Those procs will be instance eval'd against the task to determine if the stub is a match. This allows you to stub the same way the call is made in the task (which is handy when the cmds are driven by dynamic values on the task instance).
|
624
|
+
|
625
|
+
```ruby
|
626
|
+
# in your test file or whatever
|
627
|
+
|
628
|
+
include Dk::Task::TestHelpers
|
629
|
+
|
630
|
+
test "my task should do something" do
|
631
|
+
runner = test_runner(MyTask)
|
632
|
+
runner.stub_cmd(proc{ self.class.some_cmd_str }, :opts => proc{ some_opts }) do |spy| # spy is a Local::CmdSpy
|
633
|
+
spy.stdout = "..."
|
634
|
+
end
|
635
|
+
runner.stub_ssh("ls -la", :input => proc{ some_task_input_val }) do |spy| # spy is a Remote::CmdSpy
|
636
|
+
spy.exitstatus = 1 # simulare the ssh call failing
|
637
|
+
end
|
638
|
+
|
639
|
+
# ....
|
640
|
+
end
|
641
|
+
```
|
642
|
+
|
643
|
+
## Dk 3rd-party gems
|
644
|
+
|
645
|
+
These gems extend Dk for specific behavior:
|
646
|
+
|
647
|
+
* [dk-pkg](https://github.com/redding/dk-pkg): Dk logic for installing pkgs
|
648
|
+
* [dk-abdeploy](https://github.com/redding/dk-abdeploy): Dk tasks that implement the A/B deploy scheme
|
649
|
+
* [dk-dumpdb](https://github.com/redding/dk-dumpdb): Build Dk tasks to dump and restore your databases
|
650
|
+
|
651
|
+
(if you build your own gem that extends Dk, let us know and we'll link it here)
|
10
652
|
|
11
653
|
## Installation
|
12
654
|
|
data/bin/dk
ADDED
data/dk.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Dk::VERSION
|
9
9
|
gem.authors = ["Kelly Redding", "Collin Redding"]
|
10
10
|
gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
|
11
|
-
gem.summary = "\"Why'd you name this repo
|
12
|
-
gem.description = "\"Why'd you name this repo
|
11
|
+
gem.summary = "\"Why'd you name this repo dk?\" \"Don't know\" (this is some automated task runner thingy ala cap/rake)"
|
12
|
+
gem.description = "\"Why'd you name this repo dk?\" \"Don't know\" (this is some automated task runner thingy ala cap/rake)"
|
13
13
|
gem.homepage = "https://github.com/redding/dk"
|
14
14
|
gem.license = 'MIT'
|
15
15
|
|
@@ -18,6 +18,10 @@ 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.
|
21
|
+
gem.add_development_dependency("assert", ["~> 2.16.3"])
|
22
|
+
|
23
|
+
gem.add_dependency("much-plugin", ["~> 0.2.0"])
|
24
|
+
gem.add_dependency("scmd", ["~> 3.0.3"])
|
25
|
+
gem.add_dependency("logsly", ["~> 1.3.2"])
|
22
26
|
|
23
27
|
end
|