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
data/lib/dk/ansi.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Dk
2
+
3
+ module Ansi
4
+
5
+ def self.styled_msg(msg, *styles)
6
+ code = self.code_for(*styles)
7
+ return msg if code.empty?
8
+ code + msg + self.code_for(:reset)
9
+ end
10
+
11
+ def self.code_for(*style_names)
12
+ style_names.map{ |n| "\e[#{CODES[n]}m" if CODES.key?(n) }.compact.join('')
13
+ end
14
+
15
+ # Table of supported styles/codes (http://en.wikipedia.org/wiki/ANSI_escape_code)
16
+
17
+ CODES = {
18
+ :clear => 0,
19
+ :reset => 0,
20
+ :bright => 1,
21
+ :bold => 1,
22
+ :faint => 2,
23
+ :dark => 2,
24
+ :italic => 3,
25
+ :underline => 4,
26
+ :underscore => 4,
27
+ :blink => 5,
28
+ :slow_blink => 5,
29
+ :rapid => 6,
30
+ :rapid_blink => 6,
31
+ :invert => 7,
32
+ :inverse => 7,
33
+ :reverse => 7,
34
+ :negative => 7,
35
+ :swap => 7,
36
+ :conceal => 8,
37
+ :concealed => 8,
38
+ :hide => 9,
39
+ :strike => 9,
40
+
41
+ :default_font => 10,
42
+ :font_default => 10,
43
+ :font0 => 10,
44
+ :font1 => 11,
45
+ :font2 => 12,
46
+ :font3 => 13,
47
+ :font4 => 14,
48
+ :font5 => 15,
49
+ :font6 => 16,
50
+ :font7 => 17,
51
+ :font8 => 18,
52
+ :font9 => 19,
53
+ :fraktur => 20,
54
+ :bright_off => 21,
55
+ :bold_off => 21,
56
+ :double_underline => 21,
57
+ :clean => 22,
58
+ :italic_off => 23,
59
+ :fraktur_off => 23,
60
+ :underline_off => 24,
61
+ :blink_off => 25,
62
+ :inverse_off => 26,
63
+ :positive => 26,
64
+ :conceal_off => 27,
65
+ :show => 27,
66
+ :reveal => 27,
67
+ :crossed_off => 29,
68
+ :crossed_out_off => 29,
69
+
70
+ :black => 30,
71
+ :red => 31,
72
+ :green => 32,
73
+ :yellow => 33,
74
+ :blue => 34,
75
+ :magenta => 35,
76
+ :cyan => 36,
77
+ :white => 37,
78
+
79
+ :on_black => 40,
80
+ :on_red => 41,
81
+ :on_green => 42,
82
+ :on_yellow => 43,
83
+ :on_blue => 44,
84
+ :on_magenta => 45,
85
+ :on_cyan => 46,
86
+ :on_white => 47,
87
+
88
+ :frame => 51,
89
+ :encircle => 52,
90
+ :overline => 53,
91
+ :frame_off => 54,
92
+ :encircle_off => 54,
93
+ :overline_off => 55,
94
+ }
95
+
96
+ end
97
+
98
+ end
data/lib/dk/cli.rb ADDED
@@ -0,0 +1,173 @@
1
+ require 'dk'
2
+ require 'dk/dk_runner'
3
+ require 'dk/dry_runner'
4
+ require 'dk/tree_runner'
5
+ require 'dk/version'
6
+
7
+ module Dk
8
+
9
+ class CLI
10
+
11
+ DEFAULT_CONFIG_PATH = 'config/dk.rb'.freeze
12
+
13
+ def self.run(args)
14
+ self.new.run(*args)
15
+ end
16
+
17
+ attr_reader :clirb
18
+
19
+ def initialize(kernel = nil)
20
+ @kernel = kernel || Kernel
21
+
22
+ load config_path
23
+ Dk.init
24
+ @config = Dk.config
25
+
26
+ @clirb = CLIRB.new do
27
+ option 'list-tasks', 'list all tasks available to run', {
28
+ :abbrev => 'T'
29
+ }
30
+ option 'dry-run', 'run the tasks without executing any local/remote cmds'
31
+ option 'tree', 'print out the tree of tasks/sub-tasks that would be run'
32
+ option 'verbose', 'run tasks showing verbose (ie debug log level) details'
33
+ end
34
+ end
35
+
36
+ def run(*args)
37
+ begin
38
+ run!(*args)
39
+ rescue ShowTaskList
40
+ @kernel.puts task_list
41
+ rescue CLIRB::HelpExit
42
+ @kernel.puts help
43
+ rescue CLIRB::VersionExit
44
+ @kernel.puts Dk::VERSION
45
+ rescue CLIRB::Error, Dk::Config::UnknownTaskError => exception
46
+ @kernel.puts help
47
+ @kernel.puts "\n\n#{exception.message}\n"
48
+ @kernel.exit 1
49
+ rescue Dk::NoticeError => exception
50
+ @kernel.puts "\n\n#{exception.message}\n\n"
51
+ @kernel.puts exception.backtrace.first
52
+ @kernel.exit 1
53
+ rescue StandardError => exception
54
+ @kernel.puts "\n\n#{exception.class}: #{exception.message}"
55
+ @kernel.puts exception.backtrace.join("\n")
56
+ @kernel.exit 1
57
+ end
58
+ @kernel.exit 0
59
+ end
60
+
61
+ private
62
+
63
+ def run!(*args)
64
+ @clirb.parse!(args)
65
+ raise ShowTaskList if @clirb.opts['list-tasks']
66
+
67
+ @config.stdout_log_level('debug') if @clirb.opts['verbose']
68
+
69
+ unknowns = @clirb.args.select{ |name| !@config.tasks.keys.include?(name) }
70
+ if !unknowns.empty?
71
+ raise Dk::Config::UnknownTaskError, unknowns.map{ |u| "`#{u}`"}.join(', ')
72
+ end
73
+
74
+ runner = get_runner(@config, @clirb.opts)
75
+ runner.log_cli_run(args.join(' ')) do
76
+ @clirb.args.each do |task_name|
77
+ runner.log_cli_task_run(task_name) do
78
+ runner.run(@config.task(task_name))
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def help
85
+ "Usage: dk [TASKS] [options]\n\n" \
86
+ "Tasks:\n" \
87
+ "#{task_list(' ')}\n\n" \
88
+ "Options: #{@clirb}"
89
+ end
90
+
91
+ def task_list(prefix = '')
92
+ max_name_width = @config.tasks.keys.map(&:size).max
93
+ items = @config.tasks.map do |(name, task_class)|
94
+ "#{prefix}#{name.ljust(max_name_width)} # #{task_class.description}"
95
+ end
96
+ items.sort.join("\n")
97
+ end
98
+
99
+ def config_path
100
+ File.expand_path(ENV['DK_CONFIG'] || DEFAULT_CONFIG_PATH, ENV['PWD'])
101
+ end
102
+
103
+ def get_runner(config, opts)
104
+ return Dk::DryRunner.new(config) if opts['dry-run']
105
+
106
+ if opts['tree']
107
+ @kernel.puts "building task tree#{'s' if @clirb.args.size > 1}..."
108
+ return Dk::TreeRunner.new(config, @kernel)
109
+ end
110
+
111
+ Dk::DkRunner.new(config)
112
+ end
113
+
114
+ ShowTaskList = Class.new(RuntimeError)
115
+
116
+ end
117
+
118
+ class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
119
+ Error = Class.new(RuntimeError);
120
+ HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
121
+ attr_reader :argv, :args, :opts, :data
122
+
123
+ def initialize(&block)
124
+ @options = []; instance_eval(&block) if block
125
+ require 'optparse'
126
+ @data, @args, @opts = [], [], {}; @parser = OptionParser.new do |p|
127
+ p.banner = ''; @options.each do |o|
128
+ @opts[o.name] = o.value; p.on(*o.parser_args){ |v| @opts[o.name] = v }
129
+ end
130
+ p.on_tail('--version', ''){ |v| raise VersionExit, v.to_s }
131
+ p.on_tail('--help', ''){ |v| raise HelpExit, v.to_s }
132
+ end
133
+ end
134
+
135
+ def option(*args); @options << Option.new(*args); end
136
+ def parse!(argv)
137
+ @args = (argv || []).dup.tap do |args_list|
138
+ begin; @parser.parse!(args_list)
139
+ rescue OptionParser::ParseError => err; raise Error, err.message; end
140
+ end; @data = @args + [@opts]
141
+ end
142
+ def to_s; @parser.to_s; end
143
+ def inspect
144
+ "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @data=#{@data.inspect}>"
145
+ end
146
+
147
+ class Option
148
+ attr_reader :name, :opt_name, :desc, :abbrev, :value, :klass, :parser_args
149
+
150
+ def initialize(name, *args)
151
+ settings, @desc = args.last.kind_of?(::Hash) ? args.pop : {}, args.pop || ''
152
+ @name, @opt_name, @abbrev = parse_name_values(name, settings[:abbrev])
153
+ @value, @klass = gvalinfo(settings[:value])
154
+ @parser_args = if [TrueClass, FalseClass, NilClass].include?(@klass)
155
+ ["-#{@abbrev}", "--[no-]#{@opt_name}", @desc]
156
+ else
157
+ ["-#{@abbrev}", "--#{@opt_name} #{@opt_name.upcase}", @klass, @desc]
158
+ end
159
+ end
160
+
161
+ private
162
+
163
+ def parse_name_values(name, custom_abbrev)
164
+ [ (processed_name = name.to_s.strip.downcase), processed_name.gsub('_', '-'),
165
+ custom_abbrev || processed_name.gsub(/[^a-z]/, '').chars.first || 'a'
166
+ ]
167
+ end
168
+ def gvalinfo(v); v.kind_of?(Class) ? [nil,gklass(v)] : [v,gklass(v.class)]; end
169
+ def gklass(k); k == Fixnum ? Integer : k; end
170
+ end
171
+ end
172
+
173
+ end
data/lib/dk/config.rb ADDED
@@ -0,0 +1,217 @@
1
+ require 'logsly'
2
+ require 'dk/has_set_param'
3
+ require 'dk/has_ssh_opts'
4
+ require 'dk/task'
5
+
6
+ module Dk
7
+
8
+ class Config
9
+ include Dk::HasSetParam
10
+ include Dk::HasSSHOpts
11
+
12
+ UnknownTaskError = Class.new(ArgumentError) do
13
+ def initialize(task_name)
14
+ super("No task named #{task_name}")
15
+ end
16
+ end
17
+
18
+ DEFAULT_INIT_PROCS = [].freeze
19
+ DEFAULT_PARAMS = {}.freeze
20
+ DEFAULT_CALLBACKS = Hash.new{ |h, k| h[k] = Dk::Task::CallbackSet.new }.freeze
21
+ DEFAULT_SSH_HOSTS = {}.freeze
22
+ DEFAULT_SSH_ARGS = ''.freeze
23
+ DEFAULT_HOST_SSH_ARGS = Hash.new{ |h, k| h[k] = DEFAULT_SSH_ARGS }
24
+ DEFAULT_TASKS = Hash.new{ |h, k| raise UnknownTaskError.new("`#{k}`") }.freeze
25
+ DEFAULT_LOG_PATTERN = "%m\n".freeze
26
+ DEFAULT_LOG_FILE_PATTERN = '[%d %-5l] : %m\n'.freeze
27
+ DEFAULT_STDOUT_LOG_LEVEL = 'info'.freeze
28
+ DEFAULT_STUBS = [].freeze
29
+ FILE_LOG_LEVEL = 'debug'.freeze
30
+
31
+ attr_reader :init_procs, :params
32
+ attr_reader :before_callbacks, :prepend_before_callbacks
33
+ attr_reader :after_callbacks, :prepend_after_callbacks
34
+ attr_reader :tasks, :dry_tree_cmd_stubs, :dry_tree_ssh_stubs
35
+
36
+ def initialize
37
+ @init_procs = DEFAULT_INIT_PROCS.dup
38
+ @params = DEFAULT_PARAMS.dup
39
+ @before_callbacks = DEFAULT_CALLBACKS.dup
40
+ @prepend_before_callbacks = DEFAULT_CALLBACKS.dup
41
+ @after_callbacks = DEFAULT_CALLBACKS.dup
42
+ @prepend_after_callbacks = DEFAULT_CALLBACKS.dup
43
+ @ssh_hosts = DEFAULT_SSH_HOSTS.dup
44
+ @ssh_args = DEFAULT_SSH_ARGS.dup
45
+ @host_ssh_args = DEFAULT_HOST_SSH_ARGS.dup
46
+ @tasks = DEFAULT_TASKS.dup
47
+ @stdout_log_level = DEFAULT_STDOUT_LOG_LEVEL
48
+ @log_pattern = DEFAULT_LOG_PATTERN
49
+ @log_file = nil
50
+ @log_file_pattern = DEFAULT_LOG_FILE_PATTERN
51
+ @dry_tree_cmd_stubs = DEFAULT_STUBS.dup
52
+ @dry_tree_ssh_stubs = DEFAULT_STUBS.dup
53
+ end
54
+
55
+ def init
56
+ self.init_procs.each{ |block| self.instance_eval(&block) }
57
+ end
58
+
59
+ def set_param(key, value)
60
+ self.params.merge!(dk_normalize_params(key => value))
61
+ end
62
+
63
+ def before(subject_task_class, callback_task_class, params = nil)
64
+ self.before_callbacks[subject_task_class] << Task::Callback.new(
65
+ callback_task_class,
66
+ params
67
+ )
68
+ end
69
+
70
+ def prepend_before(subject_task_class, callback_task_class, params = nil)
71
+ self.prepend_before_callbacks[subject_task_class].unshift(Task::Callback.new(
72
+ callback_task_class,
73
+ params
74
+ ))
75
+ end
76
+
77
+ def after(subject_task_class, callback_task_class, params = nil)
78
+ self.after_callbacks[subject_task_class] << Task::Callback.new(
79
+ callback_task_class,
80
+ params
81
+ )
82
+ end
83
+
84
+ def prepend_after(subject_task_class, callback_task_class, params = nil)
85
+ self.prepend_after_callbacks[subject_task_class].unshift(Task::Callback.new(
86
+ callback_task_class,
87
+ params
88
+ ))
89
+ end
90
+
91
+ def before_callback_task_classes(for_task_class)
92
+ self.before_callbacks[for_task_class].map(&:task_class)
93
+ end
94
+
95
+ def prepend_before_callback_task_classes(for_task_class)
96
+ self.prepend_before_callbacks[for_task_class].map(&:task_class)
97
+ end
98
+
99
+ def after_callback_task_classes(for_task_class)
100
+ self.after_callbacks[for_task_class].map(&:task_class)
101
+ end
102
+
103
+ def prepend_after_callback_task_classes(for_task_class)
104
+ self.prepend_after_callbacks[for_task_class].map(&:task_class)
105
+ end
106
+
107
+ def task(name, task_class = nil)
108
+ if !task_class.nil?
109
+ if !task_class.kind_of?(Class) || !task_class.include?(Dk::Task)
110
+ raise ArgumentError, "#{task_class.inspect} is not a Dk::Task"
111
+ end
112
+ @tasks[name.to_s] = task_class
113
+ end
114
+ @tasks[name.to_s]
115
+ end
116
+
117
+ def stdout_log_level(value = nil)
118
+ @stdout_log_level = value if !value.nil?
119
+ @stdout_log_level
120
+ end
121
+
122
+ def log_pattern(value = nil)
123
+ @log_pattern = value if !value.nil?
124
+ @log_pattern
125
+ end
126
+
127
+ def log_file(value = nil)
128
+ @log_file = value if !value.nil?
129
+ @log_file
130
+ end
131
+
132
+ def log_file_pattern(value = nil)
133
+ @log_file_pattern = value if !value.nil?
134
+ @log_file_pattern
135
+ end
136
+
137
+ def stub_dry_tree_cmd(cmd_str, args = nil, &block)
138
+ args ||= {}
139
+
140
+ cmd_str_proc = get_cmd_ssh_proc(cmd_str)
141
+ input_proc = get_cmd_ssh_proc(args[:input])
142
+ given_opts_proc = get_cmd_ssh_proc(args[:opts])
143
+
144
+ @dry_tree_cmd_stubs.unshift(
145
+ DryTreeStub.new(cmd_str_proc, input_proc, given_opts_proc, block)
146
+ )
147
+ end
148
+
149
+ def stub_dry_tree_ssh(cmd_str, args = nil, &block)
150
+ args ||= {}
151
+
152
+ cmd_str_proc = get_cmd_ssh_proc(cmd_str)
153
+ input_proc = get_cmd_ssh_proc(args[:input])
154
+ given_opts_proc = get_cmd_ssh_proc(args[:opts])
155
+
156
+ @dry_tree_ssh_stubs.unshift(
157
+ DryTreeStub.new(cmd_str_proc, input_proc, given_opts_proc, block)
158
+ )
159
+ end
160
+
161
+ # private - intended for internal use only
162
+
163
+ def dk_logger_stdout_output_name
164
+ # include the object id to ensure the output is unique to the instance
165
+ @dk_logger_stdout_output_name ||= "dk-config-#{self.object_id}-stdout"
166
+ end
167
+
168
+ def dk_logger_file_output_name
169
+ # include the object id to ensure the output is unique to the instance
170
+ @dk_logger_file_output_name ||= "dk-config-#{self.object_id}-file"
171
+ end
172
+
173
+ def dk_logger
174
+ @dk_logger ||= LogslyLogger.new(self)
175
+ end
176
+
177
+ private
178
+
179
+ def get_cmd_ssh_proc(obj)
180
+ obj.kind_of?(::Proc) ? obj : proc{ obj }
181
+ end
182
+
183
+ DryTreeStub = Struct.new(:cmd_str_proc, :input_proc, :given_opts_proc, :block)
184
+
185
+ class LogslyLogger
186
+ include Logsly
187
+
188
+ LOG_TYPE = 'dk'.freeze
189
+
190
+ attr_reader :config
191
+
192
+ def initialize(config)
193
+ @config = config # set the reader first so it can be used when supering
194
+
195
+ Logsly.stdout(@config.dk_logger_stdout_output_name) do |logger|
196
+ level logger.config.stdout_log_level
197
+ pattern logger.config.log_pattern
198
+ end
199
+ outputs = [@config.dk_logger_stdout_output_name]
200
+
201
+ if @config.log_file
202
+ Logsly.file(@config.dk_logger_file_output_name) do |logger|
203
+ path File.expand_path(logger.config.log_file, ENV['PWD'])
204
+ level Dk::Config::FILE_LOG_LEVEL
205
+ pattern logger.config.log_file_pattern
206
+ end
207
+ outputs << @config.dk_logger_file_output_name
208
+ end
209
+
210
+ super(LOG_TYPE, :outputs => outputs)
211
+ end
212
+
213
+ end
214
+
215
+ end
216
+
217
+ end
@@ -0,0 +1,24 @@
1
+ require 'dk/runner'
2
+
3
+ module Dk
4
+
5
+ class ConfigRunner < Runner
6
+
7
+ def initialize(config, opts = nil)
8
+ opts ||= {}
9
+ super({
10
+ :params => config.params,
11
+ :before_callbacks => config.before_callbacks,
12
+ :prepend_before_callbacks => config.prepend_before_callbacks,
13
+ :after_callbacks => config.after_callbacks,
14
+ :prepend_after_callbacks => config.prepend_after_callbacks,
15
+ :ssh_hosts => config.ssh_hosts,
16
+ :ssh_args => config.ssh_args,
17
+ :host_ssh_args => config.host_ssh_args,
18
+ :logger => opts[:logger] || config.dk_logger
19
+ })
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'dk/config_runner'
2
+
3
+ module Dk
4
+
5
+ class DkRunner < ConfigRunner
6
+
7
+ def initialize(config)
8
+ super(config)
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,43 @@
1
+ require 'dk/config_runner'
2
+ require 'dk/has_the_stubs'
3
+
4
+ module Dk
5
+
6
+ class DryRunner < ConfigRunner
7
+ include HasTheStubs
8
+
9
+ # run with disabled cmds, just log actions, but run all sub-tasks
10
+
11
+ def initialize(config, *args)
12
+ super(config, *args)
13
+ config.dry_tree_cmd_stubs.each do |s|
14
+ self.stub_cmd(s.cmd_str_proc, {
15
+ :input => s.input_proc,
16
+ :opts => s.given_opts_proc
17
+ }, &s.block)
18
+ end
19
+ config.dry_tree_ssh_stubs.each do |s|
20
+ self.stub_ssh(s.cmd_str_proc, {
21
+ :input => s.input_proc,
22
+ :opts => s.given_opts_proc
23
+ }, &s.block)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def has_the_stubs_build_local_cmd(cmd_str, given_opts)
30
+ given_opts ||= {}
31
+ cmd_klass = given_opts[:dry_tree_run] ? Local::Cmd : Local::CmdSpy
32
+ cmd_klass.new(cmd_str, given_opts)
33
+ end
34
+
35
+ def has_the_stubs_build_remote_cmd(cmd_str, ssh_opts)
36
+ ssh_opts ||= {}
37
+ cmd_klass = ssh_opts[:dry_tree_run] ? Remote::Cmd : Remote::CmdSpy
38
+ cmd_klass.new(cmd_str, ssh_opts)
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,42 @@
1
+ require 'much-plugin'
2
+
3
+ module Dk
4
+
5
+ module HasSetParam
6
+ include MuchPlugin
7
+
8
+ plugin_included do
9
+ include InstanceMethods
10
+
11
+ end
12
+
13
+ module InstanceMethods
14
+
15
+ def set_param(key, value)
16
+ self.params.merge!(dk_normalize_params(key => value))
17
+ end
18
+
19
+ private
20
+
21
+ def dk_normalize_params(params)
22
+ StringifyParams.new(params || {})
23
+ end
24
+
25
+ end
26
+
27
+ module StringifyParams
28
+ def self.new(object)
29
+ case(object)
30
+ when ::Hash
31
+ object.inject({}){ |h, (k, v)| h.merge(k.to_s => self.new(v)) }
32
+ when ::Array
33
+ object.map{ |item| self.new(item) }
34
+ else
35
+ object
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,36 @@
1
+ require 'much-plugin'
2
+
3
+ module Dk
4
+
5
+ module HasSSHOpts
6
+ include MuchPlugin
7
+
8
+ plugin_included do
9
+ include InstanceMethods
10
+
11
+ end
12
+
13
+ module InstanceMethods
14
+
15
+ def ssh_hosts(group_name = nil, *values)
16
+ return @ssh_hosts if group_name.nil?
17
+ @ssh_hosts[group_name.to_s] = values.flatten if !values.empty?
18
+ @ssh_hosts[group_name.to_s]
19
+ end
20
+
21
+ def ssh_args(value = nil)
22
+ @ssh_args = value if !value.nil?
23
+ @ssh_args
24
+ end
25
+
26
+ def host_ssh_args(host_name = nil, value = nil)
27
+ return @host_ssh_args if host_name.nil?
28
+ @host_ssh_args[host_name.to_s] = value if !value.nil?
29
+ @host_ssh_args[host_name.to_s]
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,23 @@
1
+ require 'much-plugin'
2
+
3
+ module Dk
4
+
5
+ module HasTheRuns
6
+ include MuchPlugin
7
+
8
+ plugin_included do
9
+ include InstanceMethods
10
+
11
+ end
12
+
13
+ module InstanceMethods
14
+
15
+ def runs
16
+ @runs ||= []
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end