choria-mcorpc-support 2.21.0 → 2.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mcollective.rb +1 -1
  3. data/lib/mcollective/agent/bolt_tasks.ddl +235 -0
  4. data/lib/mcollective/agent/bolt_tasks.json +347 -0
  5. data/lib/mcollective/agent/bolt_tasks.rb +176 -0
  6. data/lib/mcollective/agent/choria_util.ddl +152 -0
  7. data/lib/mcollective/agent/choria_util.json +244 -0
  8. data/lib/mcollective/agent/rpcutil.ddl +7 -3
  9. data/lib/mcollective/agent/rpcutil.json +333 -0
  10. data/lib/mcollective/agent/scout.ddl +169 -0
  11. data/lib/mcollective/agent/scout.json +224 -0
  12. data/lib/mcollective/agents.rb +7 -6
  13. data/lib/mcollective/aggregate.rb +4 -4
  14. data/lib/mcollective/aggregate/average.rb +2 -2
  15. data/lib/mcollective/aggregate/base.rb +2 -2
  16. data/lib/mcollective/aggregate/result.rb +3 -3
  17. data/lib/mcollective/aggregate/result/collection_result.rb +2 -2
  18. data/lib/mcollective/aggregate/result/numeric_result.rb +2 -2
  19. data/lib/mcollective/aggregate/sum.rb +2 -2
  20. data/lib/mcollective/aggregate/summary.rb +3 -4
  21. data/lib/mcollective/application.rb +57 -21
  22. data/lib/mcollective/application/choria.rb +249 -0
  23. data/lib/mcollective/application/completion.rb +6 -6
  24. data/lib/mcollective/application/describe_filter.rb +20 -20
  25. data/lib/mcollective/application/facts.rb +19 -11
  26. data/lib/mcollective/application/federation.rb +239 -0
  27. data/lib/mcollective/application/find.rb +4 -4
  28. data/lib/mcollective/application/help.rb +3 -3
  29. data/lib/mcollective/application/inventory.rb +3 -341
  30. data/lib/mcollective/application/ping.rb +3 -77
  31. data/lib/mcollective/application/playbook.rb +207 -0
  32. data/lib/mcollective/application/plugin.rb +106 -106
  33. data/lib/mcollective/application/rpc.rb +3 -108
  34. data/lib/mcollective/application/tasks.rb +416 -0
  35. data/lib/mcollective/applications.rb +11 -10
  36. data/lib/mcollective/audit/choria.rb +33 -0
  37. data/lib/mcollective/cache.rb +2 -4
  38. data/lib/mcollective/client.rb +11 -10
  39. data/lib/mcollective/config.rb +21 -34
  40. data/lib/mcollective/connector/base.rb +2 -1
  41. data/lib/mcollective/connector/nats.ddl +9 -0
  42. data/lib/mcollective/connector/nats.rb +450 -0
  43. data/lib/mcollective/data.rb +8 -3
  44. data/lib/mcollective/data/agent_data.rb +1 -1
  45. data/lib/mcollective/data/base.rb +6 -5
  46. data/lib/mcollective/data/bolt_task_data.ddl +90 -0
  47. data/lib/mcollective/data/bolt_task_data.rb +32 -0
  48. data/lib/mcollective/data/collective_data.rb +1 -1
  49. data/lib/mcollective/data/fact_data.rb +6 -6
  50. data/lib/mcollective/data/fstat_data.rb +2 -4
  51. data/lib/mcollective/data/result.rb +7 -2
  52. data/lib/mcollective/ddl/agentddl.rb +5 -17
  53. data/lib/mcollective/ddl/base.rb +10 -13
  54. data/lib/mcollective/discovery.rb +12 -26
  55. data/lib/mcollective/discovery/choria.ddl +11 -0
  56. data/lib/mcollective/discovery/choria.rb +223 -0
  57. data/lib/mcollective/discovery/flatfile.rb +7 -8
  58. data/lib/mcollective/discovery/mc.rb +2 -2
  59. data/lib/mcollective/discovery/stdin.rb +17 -18
  60. data/lib/mcollective/exceptions.rb +13 -0
  61. data/lib/mcollective/facts/base.rb +9 -9
  62. data/lib/mcollective/facts/yaml_facts.rb +12 -12
  63. data/lib/mcollective/generators.rb +3 -3
  64. data/lib/mcollective/generators/agent_generator.rb +3 -4
  65. data/lib/mcollective/generators/base.rb +14 -15
  66. data/lib/mcollective/generators/data_generator.rb +5 -6
  67. data/lib/mcollective/log.rb +2 -2
  68. data/lib/mcollective/logger/base.rb +3 -2
  69. data/lib/mcollective/logger/console_logger.rb +10 -10
  70. data/lib/mcollective/logger/file_logger.rb +7 -7
  71. data/lib/mcollective/logger/syslog_logger.rb +11 -15
  72. data/lib/mcollective/matcher.rb +14 -14
  73. data/lib/mcollective/matcher/parser.rb +31 -41
  74. data/lib/mcollective/matcher/scanner.rb +69 -74
  75. data/lib/mcollective/message.rb +10 -17
  76. data/lib/mcollective/monkey_patches.rb +2 -4
  77. data/lib/mcollective/optionparser.rb +1 -0
  78. data/lib/mcollective/pluginmanager.rb +3 -5
  79. data/lib/mcollective/pluginpackager.rb +1 -3
  80. data/lib/mcollective/pluginpackager/agent_definition.rb +3 -8
  81. data/lib/mcollective/pluginpackager/forge_packager.rb +7 -9
  82. data/lib/mcollective/pluginpackager/standard_definition.rb +1 -2
  83. data/lib/mcollective/registration/base.rb +18 -16
  84. data/lib/mcollective/rpc.rb +2 -4
  85. data/lib/mcollective/rpc/actionrunner.rb +16 -18
  86. data/lib/mcollective/rpc/agent.rb +26 -43
  87. data/lib/mcollective/rpc/audit.rb +1 -0
  88. data/lib/mcollective/rpc/client.rb +67 -85
  89. data/lib/mcollective/rpc/helpers.rb +55 -62
  90. data/lib/mcollective/rpc/progress.rb +2 -2
  91. data/lib/mcollective/rpc/reply.rb +17 -19
  92. data/lib/mcollective/rpc/request.rb +7 -5
  93. data/lib/mcollective/rpc/result.rb +6 -8
  94. data/lib/mcollective/rpc/stats.rb +49 -58
  95. data/lib/mcollective/security/base.rb +29 -36
  96. data/lib/mcollective/security/choria.rb +765 -0
  97. data/lib/mcollective/shell.rb +9 -4
  98. data/lib/mcollective/signer/base.rb +28 -0
  99. data/lib/mcollective/signer/choria.rb +185 -0
  100. data/lib/mcollective/ssl.rb +8 -6
  101. data/lib/mcollective/util.rb +58 -55
  102. data/lib/mcollective/util/bolt_support.rb +176 -0
  103. data/lib/mcollective/util/bolt_support/plan_runner.rb +167 -0
  104. data/lib/mcollective/util/bolt_support/task_result.rb +94 -0
  105. data/lib/mcollective/util/bolt_support/task_results.rb +128 -0
  106. data/lib/mcollective/util/choria.rb +1103 -0
  107. data/lib/mcollective/util/indifferent_hash.rb +12 -0
  108. data/lib/mcollective/util/natswrapper.rb +242 -0
  109. data/lib/mcollective/util/playbook.rb +435 -0
  110. data/lib/mcollective/util/playbook/data_stores.rb +201 -0
  111. data/lib/mcollective/util/playbook/data_stores/base.rb +99 -0
  112. data/lib/mcollective/util/playbook/data_stores/consul_data_store.rb +88 -0
  113. data/lib/mcollective/util/playbook/data_stores/environment_data_store.rb +33 -0
  114. data/lib/mcollective/util/playbook/data_stores/etcd_data_store.rb +42 -0
  115. data/lib/mcollective/util/playbook/data_stores/file_data_store.rb +106 -0
  116. data/lib/mcollective/util/playbook/data_stores/shell_data_store.rb +103 -0
  117. data/lib/mcollective/util/playbook/inputs.rb +265 -0
  118. data/lib/mcollective/util/playbook/nodes.rb +207 -0
  119. data/lib/mcollective/util/playbook/nodes/mcollective_nodes.rb +86 -0
  120. data/lib/mcollective/util/playbook/nodes/pql_nodes.rb +40 -0
  121. data/lib/mcollective/util/playbook/nodes/shell_nodes.rb +55 -0
  122. data/lib/mcollective/util/playbook/nodes/terraform_nodes.rb +65 -0
  123. data/lib/mcollective/util/playbook/nodes/yaml_nodes.rb +47 -0
  124. data/lib/mcollective/util/playbook/playbook_logger.rb +47 -0
  125. data/lib/mcollective/util/playbook/puppet_logger.rb +51 -0
  126. data/lib/mcollective/util/playbook/report.rb +152 -0
  127. data/lib/mcollective/util/playbook/task_result.rb +55 -0
  128. data/lib/mcollective/util/playbook/tasks.rb +196 -0
  129. data/lib/mcollective/util/playbook/tasks/base.rb +45 -0
  130. data/lib/mcollective/util/playbook/tasks/graphite_event_task.rb +64 -0
  131. data/lib/mcollective/util/playbook/tasks/mcollective_task.rb +356 -0
  132. data/lib/mcollective/util/playbook/tasks/shell_task.rb +93 -0
  133. data/lib/mcollective/util/playbook/tasks/slack_task.rb +105 -0
  134. data/lib/mcollective/util/playbook/tasks/webhook_task.rb +136 -0
  135. data/lib/mcollective/util/playbook/template_util.rb +98 -0
  136. data/lib/mcollective/util/playbook/uses.rb +169 -0
  137. data/lib/mcollective/util/tasks_support.rb +733 -0
  138. data/lib/mcollective/util/tasks_support/cli.rb +260 -0
  139. data/lib/mcollective/util/tasks_support/default_formatter.rb +138 -0
  140. data/lib/mcollective/util/tasks_support/json_formatter.rb +108 -0
  141. data/lib/mcollective/validator.rb +6 -1
  142. data/lib/mcollective/validator/bolt_task_name_validator.ddl +7 -0
  143. data/lib/mcollective/validator/bolt_task_name_validator.rb +11 -0
  144. data/lib/mcollective/validator/length_validator.rb +1 -3
  145. metadata +65 -2
@@ -1,111 +1,6 @@
1
- class MCollective::Application::Rpc<MCollective::Application
1
+ class MCollective::Application::Rpc < MCollective::Application # rubocop:disable Style/ClassAndModuleChildren
2
2
  description "Generic RPC agent client application"
3
3
 
4
- usage "mco rpc [options] [filters] --agent <agent> --action <action> [--argument <key=val> --argument ...]"
5
- usage "mco rpc [options] [filters] <agent> <action> [<key=val> <key=val> ...]"
6
-
7
- option :show_results,
8
- :description => "Do not process results, just send request",
9
- :arguments => ["--no-results", "--nr"],
10
- :default => true,
11
- :type => :bool
12
-
13
- option :agent,
14
- :description => "Agent to call",
15
- :arguments => ["-a", "--agent AGENT"]
16
-
17
- option :action,
18
- :description => "Action to call",
19
- :arguments => ["--action ACTION"]
20
-
21
- option :arguments,
22
- :description => "Arguments to pass to agent",
23
- :arguments => ["--arg", "--argument ARGUMENT"],
24
- :type => :array,
25
- :default => [],
26
- :validate => Proc.new {|val| val.match(/^(.+?)=(.+)$/) ? true : "Could not parse --arg #{val} should be of the form key=val" }
27
-
28
- def post_option_parser(configuration)
29
- # handle the alternative format that optparse cant parse
30
- unless (configuration.include?(:agent) && configuration.include?(:action))
31
- if ARGV.length >= 2
32
- configuration[:agent] = ARGV[0]
33
- ARGV.delete_at(0)
34
-
35
- configuration[:action] = ARGV[0]
36
- ARGV.delete_at(0)
37
-
38
- ARGV.each do |v|
39
- if v =~ /^(.+?)=(.+)$/
40
- configuration[:arguments] = [] unless configuration.include?(:arguments)
41
- configuration[:arguments] << v
42
- else
43
- STDERR.puts("Could not parse --arg #{v}")
44
- exit(1)
45
- end
46
- end
47
- else
48
- STDERR.puts("No agent, action and arguments specified")
49
- exit(1)
50
- end
51
- end
52
-
53
- # convert arguments to symbols for keys to comply with simplerpc conventions
54
- args = configuration[:arguments].clone
55
- configuration[:arguments] = {}
56
-
57
- args.each do |v|
58
- if v =~ /^(.+?)=(.+)$/
59
- configuration[:arguments][$1.to_sym] = $2
60
- end
61
- end
62
- end
63
-
64
- def string_to_ddl_type(arguments, ddl)
65
- return if ddl.empty?
66
-
67
- arguments.keys.each do |key|
68
- if ddl[:input].keys.include?(key)
69
- case ddl[:input][key][:type]
70
- when :boolean
71
- arguments[key] = MCollective::DDL.string_to_boolean(arguments[key])
72
-
73
- when :number, :integer, :float
74
- arguments[key] = MCollective::DDL.string_to_number(arguments[key])
75
- end
76
- end
77
- end
78
- end
79
-
80
- def main
81
- mc = rpcclient(configuration[:agent])
82
-
83
- mc.agent_filter(configuration[:agent])
84
-
85
- string_to_ddl_type(configuration[:arguments], mc.ddl.action_interface(configuration[:action])) if mc.ddl
86
-
87
- mc.validate_request(configuration[:action], configuration[:arguments])
88
-
89
- if mc.reply_to
90
- configuration[:arguments][:process_results] = true
91
-
92
- puts "Request sent with id: " + mc.send(configuration[:action], configuration[:arguments]) + " replies to #{mc.reply_to}"
93
- elsif !configuration[:show_results]
94
- configuration[:arguments][:process_results] = false
95
-
96
- puts "Request sent with id: " + mc.send(configuration[:action], configuration[:arguments])
97
- else
98
- discover_args = {:verbose => true}
99
-
100
- mc.detect_and_set_stdin_discovery
101
-
102
- mc.discover discover_args
103
-
104
- printrpc mc.send(configuration[:action], configuration[:arguments])
105
-
106
- printrpcstats :summarize => true, :caption => "#{configuration[:agent]}##{configuration[:action]} call stats" if mc.discover.size > 0
107
-
108
- halt mc.stats
109
- end
110
- end
4
+ external(:command => "choria", :args => ["req"])
5
+ external_help(:command => "choria", :args => ["req", "--help"])
111
6
  end
@@ -0,0 +1,416 @@
1
+ module MCollective
2
+ class Application
3
+ class Tasks < Application
4
+ description "Puppet Task Orchestrator"
5
+
6
+ usage <<-USAGE
7
+
8
+ mco tasks [--detail]
9
+ mco tasks <TASK NAME>
10
+ mco tasks run <TASK NAME> [OPTIONS]
11
+ mco tasks status <REQUEST> [FLAGS]
12
+
13
+ The Task Orchestrator is designed to provide a consistent
14
+ management environment for Puppet Tasks.
15
+
16
+ It will download tasks from your Puppet Server onto all nodes
17
+ and after verifying they were able to correctly download the
18
+ same task across the entire fleet will run the task.
19
+
20
+ Tasks are run in the background, the CLI can wait for up to 60
21
+ seconds for your task to complete and show the status or you
22
+ can use the status comment to review a completed task later.
23
+ USAGE
24
+
25
+ exclude_argument_sections "rpc"
26
+
27
+ def post_option_parser(configuration)
28
+ configuration[:__command] = ARGV.shift || "list"
29
+ end
30
+
31
+ def list_options
32
+ self.class.option :__detail,
33
+ :arguments => ["--detail"],
34
+ :description => "Show command descriptions",
35
+ :default => false,
36
+ :type => :boolean
37
+ end
38
+
39
+ def status_options
40
+ application_options[:usage].clear
41
+
42
+ self.class.usage <<-USAGE
43
+
44
+ mco tasks status <REQUEST> [FLAGS]
45
+
46
+ Retrieves the status for a task you previously requested. It can be running or completed.
47
+
48
+ By default only failed exuecutions are shown, use --verbose to see them all.
49
+
50
+ USAGE
51
+
52
+ self.class.option :__summary,
53
+ :arguments => ["--summary"],
54
+ :description => "Only show a overall summary of the task",
55
+ :default => false,
56
+ :type => :boolean
57
+
58
+ self.class.option :__metadata,
59
+ :arguments => ["--metadata"],
60
+ :description => "Only show task metadata for each node",
61
+ :default => false,
62
+ :type => :boolean
63
+
64
+ self.class.option :__json_format,
65
+ :arguments => ["--json"],
66
+ :description => "Display results in JSON format",
67
+ :default => false,
68
+ :type => :boolean
69
+ end
70
+
71
+ def run_options # rubocop:disable Metrics/MethodLength
72
+ application_options[:usage].clear
73
+
74
+ self.class.usage <<-USAGE
75
+
76
+ mco tasks run <TASK NAME> [OPTIONS]
77
+
78
+ Runs a task in the background and wait up to 50 seconds for it to complete.
79
+
80
+ Task inputs are handled using --argument=value for basic String, Numeric and Boolean
81
+ types, others can be passed using --input
82
+
83
+ Input can also be read from a file using "--input @file.json" or "--input @file.yaml".
84
+
85
+ For complex data types like Hashes, Arrays or Variants you have to supply input
86
+ as YAML or JSON.
87
+
88
+ Once a task is run the task ID will be displayed which can later be used with
89
+ the "mco tasks status" command to extract results.
90
+
91
+ Examples:
92
+
93
+ Run myapp::upgrade task in the background and wait for it to complete:
94
+
95
+ mco tasks run myapp::upgrade --version 1.0.0
96
+
97
+ Run myapp::upgrade task in the background and return immediately:
98
+
99
+ mco tasks run myapp::upgrade --version 1.0.0 --background
100
+
101
+ Supply complex data input to the task:
102
+
103
+ Should input be given on both the CLI arguments and a file
104
+ the CLI arguments will override the file
105
+
106
+ mco tasks run myapp::upgrade --input @input.json
107
+ mco tasks run myapp::upgrade --input @input.yaml
108
+ mco tasks run myapp::upgrade --version 1.0.0 --input \\
109
+ '{"source": {
110
+ "url": "http://repo/archive-1.0.0.tgz",
111
+ "hash": "68b329da9893e34099c7d8ad5cb9c940"}}'
112
+
113
+ USAGE
114
+
115
+ task = ARGV[1]
116
+
117
+ abort("Please specify a task to run") unless task
118
+
119
+ cli.create_task_options(task, "production", self)
120
+
121
+ self.class.option :__summary,
122
+ :arguments => ["--summary"],
123
+ :description => "Only show a overall summary of the task",
124
+ :default => false,
125
+ :type => :boolean
126
+
127
+ self.class.option :__background,
128
+ :arguments => ["--background"],
129
+ :description => "Do not wait for the task to complete",
130
+ :default => false,
131
+ :type => :boolean
132
+
133
+ self.class.option :__json_input,
134
+ :arguments => ["--input INPUT"],
135
+ :description => "JSON input to pass to the task",
136
+ :required => false,
137
+ :type => String
138
+
139
+ self.class.option :__batch_size,
140
+ :arguments => ["--batch SIZE"],
141
+ :description => "Run tasks on nodes in batches",
142
+ :required => false,
143
+ :type => String
144
+
145
+ self.class.option :__batch_sleep,
146
+ :arguments => ["--batch-sleep SECONDS"],
147
+ :description => "Time to sleep between invocations of batches of nodes",
148
+ :required => false,
149
+ :default => 1,
150
+ :type => Integer
151
+ end
152
+
153
+ def say(msg="")
154
+ puts(msg) unless configuration[:__json_format]
155
+ end
156
+
157
+ def run_command
158
+ task = ARGV.shift
159
+
160
+ input = cli.task_input(configuration)
161
+
162
+ say("Retrieving task metadata for task %s from the Puppet Server" % task)
163
+
164
+ begin
165
+ meta = cli.task_metadata(task, "production")
166
+ rescue
167
+ abort($!.to_s)
168
+ end
169
+
170
+ cli.transform_hash_strings(meta, input)
171
+ cli.validate_task_input(task, meta, input)
172
+
173
+ say("Attempting to download and run task %s on %d nodes" % [Util.colorize(:bold, task), bolt_tasks.discover.size])
174
+ say
175
+
176
+ download_files(task, meta["files"])
177
+
178
+ request = {
179
+ :task => task,
180
+ :files => meta["files"].to_json
181
+ }
182
+
183
+ request[:input] = input.to_json if input
184
+
185
+ if configuration[:__background]
186
+ puts("Starting task %s in the background" % [Util.colorize(:bold, task)])
187
+
188
+ if configuration[:__batch_size]
189
+ bolt_tasks.batch_size = configuration[:__batch_size]
190
+ bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
191
+ bolt_tasks.progress = true
192
+ end
193
+
194
+ printrpc bolt_tasks.run_no_wait(request)
195
+ printrpcstats
196
+
197
+ if bolt_tasks.stats.okcount > 0
198
+ puts
199
+ puts("Request detailed status for the task using 'mco tasks status %s'" % [Util.colorize(:bold, bolt_tasks.stats.requestid)])
200
+ end
201
+ else
202
+ say("Running task %s and waiting up to %s seconds for it to complete" % [
203
+ Util.colorize(:bold, task),
204
+ Util.colorize(:bold, bolt_tasks.ddl.meta[:timeout])
205
+ ])
206
+
207
+ request_and_report(:run_and_wait, request)
208
+ end
209
+ ensure
210
+ reset_client!
211
+ end
212
+
213
+ def download_files(task, files)
214
+ bolt_tasks.batch_size = 50
215
+ bolt_tasks.batch_sleep_time = 1
216
+
217
+ failed = false
218
+
219
+ downloads = []
220
+ cnt = bolt_tasks.discover.size
221
+ idx = 0
222
+
223
+ bolt_tasks.download(:environment => "production", :task => task, :files => files.to_json) do |_, s|
224
+ unless configuration[:__json_format]
225
+ print(cli.twirl("Downloading and verifying %d file(s) from the Puppet Server to all nodes:" % [files.size], cnt, idx + 1))
226
+ puts if cnt == idx + 1
227
+ end
228
+
229
+ idx += 1
230
+ downloads << s
231
+ end
232
+
233
+ downloads.select {|d| d[:statuscode] > 0}.each_with_index do |download, i|
234
+ failed = true
235
+ puts if i == 0
236
+ puts(" %s: %s" % [Util.colorize(:red, "Could not download files onto %s" % download[:sender]), download[:statusmsg]])
237
+ end
238
+
239
+ unless bolt_tasks.stats.noresponsefrom.empty?
240
+ puts
241
+ puts bolt_tasks.stats.no_response_report
242
+ failed = true
243
+ end
244
+
245
+ if failed
246
+ puts
247
+ abort("Could not download the task %s onto all nodes" % task)
248
+ end
249
+ end
250
+
251
+ def status_command
252
+ taskid = ARGV.shift
253
+
254
+ abort("Please specify a task id to display") unless taskid
255
+
256
+ if configuration[:__metadata]
257
+ say("Requesting task metadata for request %s" % Util.colorize(:bold, taskid)) unless options[:verbose]
258
+
259
+ bolt_tasks.task_status(:task_id => taskid).each do |status|
260
+ cli.print_result_metadata(status)
261
+ end
262
+
263
+ cli.print_rpc_stats(bolt_tasks.stats)
264
+ else
265
+ say("Requesting task status for request %s, showing failures only pass --verbose for all output" % Util.colorize(:bold, taskid)) unless options[:verbose]
266
+
267
+ request_and_report(:task_status, {:task_id => taskid}, taskid)
268
+ end
269
+ end
270
+
271
+ def request_and_report(action, arguments, taskid=nil) # rubocop:disable Metrics/MethodLength
272
+ task_not_known_nodes = 0
273
+ wrapper_failure = 0
274
+ completed_nodes = 0
275
+ running_nodes = 0
276
+ runtime = 0.0
277
+ success_nodes = 0
278
+ fail_nodes = 0
279
+ progress = configuration[:__summary] || configuration[:__batch_size] ? RPC::Progress.new : nil
280
+ cnt = 0
281
+ expected = bolt_tasks.discover.size
282
+ task_names = []
283
+ callers = []
284
+
285
+ if configuration[:__batch_size]
286
+ bolt_tasks.batch_size = configuration[:__batch_size]
287
+ bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
288
+ end
289
+
290
+ say
291
+
292
+ bolt_tasks.send(action, arguments) do |_, reply|
293
+ status = reply[:data]
294
+
295
+ if reply[:statuscode] == 3
296
+ fail_nodes += 1
297
+ task_not_known_nodes += 1
298
+ elsif [-1, 0].include?(status[:exitcode])
299
+ status[:completed] ? completed_nodes += 1 : running_nodes += 1
300
+ runtime += status[:runtime]
301
+ reply[:statuscode] == 0 ? success_nodes += 1 : fail_nodes += 1
302
+ elsif reply[:statuscode] == 5
303
+ wrapper_failure += 1
304
+ fail_nodes += 1
305
+ else
306
+ fail_nodes += 1
307
+ end
308
+
309
+ task_names << status[:task] if status[:task]
310
+ callers << status[:callerid] if status[:callerid]
311
+
312
+ if progress
313
+ print(progress.twirl(cnt + 1, expected))
314
+
315
+ say if cnt + 1 == expected
316
+ else
317
+ cli.print_result(reply)
318
+ end
319
+
320
+ cnt += 1
321
+ end
322
+
323
+ taskid ||= bolt_tasks.stats.requestid
324
+
325
+ callers.compact!
326
+ callers.uniq!
327
+ task_names.compact!
328
+ task_names.uniq!
329
+
330
+ say
331
+
332
+ cli.print_task_summary(
333
+ taskid,
334
+ task_names,
335
+ callers,
336
+ completed_nodes,
337
+ running_nodes,
338
+ task_not_known_nodes,
339
+ wrapper_failure,
340
+ success_nodes,
341
+ fail_nodes,
342
+ runtime,
343
+ bolt_tasks.stats
344
+ )
345
+ ensure
346
+ reset_client!
347
+ end
348
+
349
+ def list_command
350
+ cli.show_task_list("production", configuration[:__detail])
351
+ end
352
+
353
+ def run
354
+ command = ARGV[0]
355
+ command = "list" unless valid_commands.include?(command)
356
+
357
+ send("%s_options" % command)
358
+
359
+ super
360
+ end
361
+
362
+ def show_task_help(task)
363
+ cli.show_task_help(task, "production")
364
+ end
365
+
366
+ def bolt_tasks
367
+ @_bolt_tasks ||= rpcclient("bolt_tasks")
368
+ end
369
+
370
+ def reset_client!
371
+ bolt_tasks.batch_size = 0
372
+ bolt_tasks.progress = options[:verbose]
373
+ end
374
+
375
+ def extract_environment_from_argv
376
+ idx = ARGV.index("--environment")
377
+
378
+ return "production" unless idx
379
+
380
+ ARGV[idx + 1]
381
+ end
382
+
383
+ def valid_commands
384
+ methods.grep(/_command$/).map {|c| c.to_s.gsub("_command", "")}
385
+ end
386
+
387
+ def choria
388
+ Util.loadclass("MCollective::Util::Choria")
389
+
390
+ @_choria ||= Util::Choria.new
391
+ end
392
+
393
+ def tasks_support
394
+ @_tasks_support ||= choria.tasks_support
395
+ end
396
+
397
+ def cli
398
+ format = configuration[:__json_format] ? :json : :default
399
+
400
+ if options
401
+ @_cli ||= tasks_support.cli(format, options[:verbose])
402
+ else
403
+ tasks_support.cli(format, false)
404
+ end
405
+ end
406
+
407
+ def main
408
+ if valid_commands.include?(configuration[:__command])
409
+ send("%s_command" % configuration[:__command])
410
+ else
411
+ show_task_help(configuration[:__command])
412
+ end
413
+ end
414
+ end
415
+ end
416
+ end