choria-mcorpc-support 2.21.1 → 2.23.1

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mcollective.rb +1 -2
  3. data/lib/mcollective/agent/bolt_tasks.ddl +253 -0
  4. data/lib/mcollective/agent/bolt_tasks.json +365 -0
  5. data/lib/mcollective/agent/bolt_tasks.rb +178 -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 +8 -4
  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 +189 -0
  23. data/lib/mcollective/application/completion.rb +6 -6
  24. data/lib/mcollective/application/facts.rb +11 -11
  25. data/lib/mcollective/application/federation.rb +237 -0
  26. data/lib/mcollective/application/find.rb +4 -4
  27. data/lib/mcollective/application/help.rb +3 -3
  28. data/lib/mcollective/application/inventory.rb +3 -341
  29. data/lib/mcollective/application/ping.rb +5 -51
  30. data/lib/mcollective/application/playbook.rb +207 -0
  31. data/lib/mcollective/application/plugin.rb +106 -106
  32. data/lib/mcollective/application/rpc.rb +3 -108
  33. data/lib/mcollective/application/tasks.rb +425 -0
  34. data/lib/mcollective/applications.rb +11 -10
  35. data/lib/mcollective/audit/choria.rb +33 -0
  36. data/lib/mcollective/cache.rb +2 -4
  37. data/lib/mcollective/client.rb +11 -10
  38. data/lib/mcollective/config.rb +21 -34
  39. data/lib/mcollective/connector/base.rb +2 -1
  40. data/lib/mcollective/connector/nats.ddl +9 -0
  41. data/lib/mcollective/connector/nats.rb +450 -0
  42. data/lib/mcollective/data.rb +8 -3
  43. data/lib/mcollective/data/agent_data.rb +1 -1
  44. data/lib/mcollective/data/base.rb +6 -5
  45. data/lib/mcollective/data/bolt_task_data.ddl +90 -0
  46. data/lib/mcollective/data/bolt_task_data.rb +32 -0
  47. data/lib/mcollective/data/collective_data.rb +1 -1
  48. data/lib/mcollective/data/fact_data.rb +6 -6
  49. data/lib/mcollective/data/fstat_data.rb +2 -4
  50. data/lib/mcollective/data/result.rb +7 -2
  51. data/lib/mcollective/ddl/agentddl.rb +5 -17
  52. data/lib/mcollective/ddl/base.rb +10 -13
  53. data/lib/mcollective/discovery.rb +24 -39
  54. data/lib/mcollective/discovery/choria.ddl +11 -0
  55. data/lib/mcollective/discovery/choria.rb +223 -0
  56. data/lib/mcollective/discovery/flatfile.rb +7 -8
  57. data/lib/mcollective/discovery/mc.rb +2 -2
  58. data/lib/mcollective/discovery/stdin.rb +17 -18
  59. data/lib/mcollective/exceptions.rb +13 -0
  60. data/lib/mcollective/facts/base.rb +9 -9
  61. data/lib/mcollective/facts/yaml_facts.rb +12 -12
  62. data/lib/mcollective/generators.rb +3 -3
  63. data/lib/mcollective/generators/agent_generator.rb +3 -4
  64. data/lib/mcollective/generators/base.rb +14 -15
  65. data/lib/mcollective/generators/data_generator.rb +5 -6
  66. data/lib/mcollective/log.rb +2 -2
  67. data/lib/mcollective/logger/base.rb +3 -2
  68. data/lib/mcollective/logger/console_logger.rb +10 -10
  69. data/lib/mcollective/logger/file_logger.rb +7 -7
  70. data/lib/mcollective/logger/syslog_logger.rb +11 -15
  71. data/lib/mcollective/message.rb +8 -39
  72. data/lib/mcollective/monkey_patches.rb +2 -4
  73. data/lib/mcollective/optionparser.rb +2 -1
  74. data/lib/mcollective/pluginmanager.rb +3 -5
  75. data/lib/mcollective/pluginpackager.rb +1 -3
  76. data/lib/mcollective/pluginpackager/agent_definition.rb +3 -8
  77. data/lib/mcollective/pluginpackager/forge_packager.rb +7 -9
  78. data/lib/mcollective/pluginpackager/standard_definition.rb +1 -2
  79. data/lib/mcollective/registration/base.rb +18 -16
  80. data/lib/mcollective/rpc.rb +2 -4
  81. data/lib/mcollective/rpc/actionrunner.rb +16 -18
  82. data/lib/mcollective/rpc/agent.rb +26 -43
  83. data/lib/mcollective/rpc/audit.rb +1 -0
  84. data/lib/mcollective/rpc/client.rb +67 -85
  85. data/lib/mcollective/rpc/helpers.rb +55 -62
  86. data/lib/mcollective/rpc/progress.rb +2 -2
  87. data/lib/mcollective/rpc/reply.rb +17 -19
  88. data/lib/mcollective/rpc/request.rb +7 -5
  89. data/lib/mcollective/rpc/result.rb +6 -8
  90. data/lib/mcollective/rpc/stats.rb +49 -58
  91. data/lib/mcollective/security/base.rb +13 -56
  92. data/lib/mcollective/security/choria.rb +765 -0
  93. data/lib/mcollective/shell.rb +9 -4
  94. data/lib/mcollective/signer/base.rb +28 -0
  95. data/lib/mcollective/signer/choria.rb +185 -0
  96. data/lib/mcollective/ssl.rb +8 -6
  97. data/lib/mcollective/util.rb +58 -55
  98. data/lib/mcollective/util/bolt_support.rb +176 -0
  99. data/lib/mcollective/util/bolt_support/plan_runner.rb +167 -0
  100. data/lib/mcollective/util/bolt_support/task_result.rb +94 -0
  101. data/lib/mcollective/util/bolt_support/task_results.rb +128 -0
  102. data/lib/mcollective/util/choria.rb +946 -0
  103. data/lib/mcollective/util/indifferent_hash.rb +12 -0
  104. data/lib/mcollective/util/natswrapper.rb +242 -0
  105. data/lib/mcollective/util/playbook.rb +435 -0
  106. data/lib/mcollective/util/playbook/data_stores.rb +201 -0
  107. data/lib/mcollective/util/playbook/data_stores/base.rb +99 -0
  108. data/lib/mcollective/util/playbook/data_stores/consul_data_store.rb +88 -0
  109. data/lib/mcollective/util/playbook/data_stores/environment_data_store.rb +33 -0
  110. data/lib/mcollective/util/playbook/data_stores/etcd_data_store.rb +42 -0
  111. data/lib/mcollective/util/playbook/data_stores/file_data_store.rb +106 -0
  112. data/lib/mcollective/util/playbook/data_stores/shell_data_store.rb +103 -0
  113. data/lib/mcollective/util/playbook/inputs.rb +265 -0
  114. data/lib/mcollective/util/playbook/nodes.rb +207 -0
  115. data/lib/mcollective/util/playbook/nodes/mcollective_nodes.rb +86 -0
  116. data/lib/mcollective/util/playbook/nodes/pql_nodes.rb +40 -0
  117. data/lib/mcollective/util/playbook/nodes/shell_nodes.rb +55 -0
  118. data/lib/mcollective/util/playbook/nodes/terraform_nodes.rb +65 -0
  119. data/lib/mcollective/util/playbook/nodes/yaml_nodes.rb +47 -0
  120. data/lib/mcollective/util/playbook/playbook_logger.rb +47 -0
  121. data/lib/mcollective/util/playbook/puppet_logger.rb +51 -0
  122. data/lib/mcollective/util/playbook/report.rb +152 -0
  123. data/lib/mcollective/util/playbook/task_result.rb +55 -0
  124. data/lib/mcollective/util/playbook/tasks.rb +196 -0
  125. data/lib/mcollective/util/playbook/tasks/base.rb +45 -0
  126. data/lib/mcollective/util/playbook/tasks/graphite_event_task.rb +64 -0
  127. data/lib/mcollective/util/playbook/tasks/mcollective_task.rb +356 -0
  128. data/lib/mcollective/util/playbook/tasks/shell_task.rb +93 -0
  129. data/lib/mcollective/util/playbook/tasks/slack_task.rb +105 -0
  130. data/lib/mcollective/util/playbook/tasks/webhook_task.rb +136 -0
  131. data/lib/mcollective/util/playbook/template_util.rb +98 -0
  132. data/lib/mcollective/util/playbook/uses.rb +169 -0
  133. data/lib/mcollective/util/tasks_support.rb +751 -0
  134. data/lib/mcollective/util/tasks_support/cli.rb +260 -0
  135. data/lib/mcollective/util/tasks_support/default_formatter.rb +138 -0
  136. data/lib/mcollective/util/tasks_support/json_formatter.rb +108 -0
  137. data/lib/mcollective/validator.rb +6 -1
  138. data/lib/mcollective/validator/bolt_task_name_validator.ddl +7 -0
  139. data/lib/mcollective/validator/bolt_task_name_validator.rb +11 -0
  140. data/lib/mcollective/validator/length_validator.rb +1 -3
  141. metadata +65 -6
  142. data/lib/mcollective/application/describe_filter.rb +0 -87
  143. data/lib/mcollective/matcher.rb +0 -220
  144. data/lib/mcollective/matcher/parser.rb +0 -128
  145. data/lib/mcollective/matcher/scanner.rb +0 -241
@@ -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,425 @@
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
+
152
+ self.class.option :__run_as,
153
+ :arguments => ["--run-as USERNAME"],
154
+ :description => "Run task as user USERNAME",
155
+ :required => false,
156
+ :default => nil,
157
+ :type => String
158
+ end
159
+
160
+ def say(msg="")
161
+ puts(msg) unless configuration[:__json_format]
162
+ end
163
+
164
+ def run_command
165
+ task = ARGV.shift
166
+
167
+ input = cli.task_input(configuration)
168
+
169
+ say("Retrieving task metadata for task %s from the Puppet Server" % task)
170
+
171
+ begin
172
+ meta = cli.task_metadata(task, "production")
173
+ rescue
174
+ abort($!.to_s)
175
+ end
176
+
177
+ cli.transform_hash_strings(meta, input)
178
+ cli.validate_task_input(task, meta, input)
179
+
180
+ say("Attempting to download and run task %s on %d nodes" % [Util.colorize(:bold, task), bolt_tasks.discover.size])
181
+ say
182
+
183
+ download_files(task, meta["files"])
184
+
185
+ request = {
186
+ :task => task,
187
+ :files => meta["files"].to_json
188
+ }
189
+
190
+ request[:run_as] = configuration[:__run_as] if configuration[:__run_as]
191
+
192
+ request[:input] = input.to_json if input
193
+
194
+ if configuration[:__background]
195
+ puts("Starting task %s in the background" % [Util.colorize(:bold, task)])
196
+
197
+ if configuration[:__batch_size]
198
+ bolt_tasks.batch_size = configuration[:__batch_size]
199
+ bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
200
+ bolt_tasks.progress = true
201
+ end
202
+
203
+ printrpc bolt_tasks.run_no_wait(request)
204
+ printrpcstats
205
+
206
+ if bolt_tasks.stats.okcount > 0
207
+ puts
208
+ puts("Request detailed status for the task using 'mco tasks status %s'" % [Util.colorize(:bold, bolt_tasks.stats.requestid)])
209
+ end
210
+ else
211
+ say("Running task %s and waiting up to %s seconds for it to complete" % [
212
+ Util.colorize(:bold, task),
213
+ Util.colorize(:bold, bolt_tasks.ddl.meta[:timeout])
214
+ ])
215
+
216
+ request_and_report(:run_and_wait, request)
217
+ end
218
+ ensure
219
+ reset_client!
220
+ end
221
+
222
+ def download_files(task, files)
223
+ bolt_tasks.batch_size = 50
224
+ bolt_tasks.batch_sleep_time = 1
225
+
226
+ failed = false
227
+
228
+ downloads = []
229
+ cnt = bolt_tasks.discover.size
230
+ idx = 0
231
+
232
+ bolt_tasks.download(:environment => "production", :task => task, :files => files.to_json) do |_, s|
233
+ unless configuration[:__json_format]
234
+ print(cli.twirl("Downloading and verifying %d file(s) from the Puppet Server to all nodes:" % [files.size], cnt, idx + 1))
235
+ puts if cnt == idx + 1
236
+ end
237
+
238
+ idx += 1
239
+ downloads << s
240
+ end
241
+
242
+ downloads.select {|d| d[:statuscode] > 0}.each_with_index do |download, i|
243
+ failed = true
244
+ puts if i == 0
245
+ puts(" %s: %s" % [Util.colorize(:red, "Could not download files onto %s" % download[:sender]), download[:statusmsg]])
246
+ end
247
+
248
+ unless bolt_tasks.stats.noresponsefrom.empty?
249
+ puts
250
+ puts bolt_tasks.stats.no_response_report
251
+ failed = true
252
+ end
253
+
254
+ if failed
255
+ puts
256
+ abort("Could not download the task %s onto all nodes" % task)
257
+ end
258
+ end
259
+
260
+ def status_command
261
+ taskid = ARGV.shift
262
+
263
+ abort("Please specify a task id to display") unless taskid
264
+
265
+ if configuration[:__metadata]
266
+ say("Requesting task metadata for request %s" % Util.colorize(:bold, taskid)) unless options[:verbose]
267
+
268
+ bolt_tasks.task_status(:task_id => taskid).each do |status|
269
+ cli.print_result_metadata(status)
270
+ end
271
+
272
+ cli.print_rpc_stats(bolt_tasks.stats)
273
+ else
274
+ say("Requesting task status for request %s, showing failures only pass --verbose for all output" % Util.colorize(:bold, taskid)) unless options[:verbose]
275
+
276
+ request_and_report(:task_status, {:task_id => taskid}, taskid)
277
+ end
278
+ end
279
+
280
+ def request_and_report(action, arguments, taskid=nil) # rubocop:disable Metrics/MethodLength
281
+ task_not_known_nodes = 0
282
+ wrapper_failure = 0
283
+ completed_nodes = 0
284
+ running_nodes = 0
285
+ runtime = 0.0
286
+ success_nodes = 0
287
+ fail_nodes = 0
288
+ progress = configuration[:__summary] || configuration[:__batch_size] ? RPC::Progress.new : nil
289
+ cnt = 0
290
+ expected = bolt_tasks.discover.size
291
+ task_names = []
292
+ callers = []
293
+
294
+ if configuration[:__batch_size]
295
+ bolt_tasks.batch_size = configuration[:__batch_size]
296
+ bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
297
+ end
298
+
299
+ say
300
+
301
+ bolt_tasks.send(action, arguments) do |_, reply|
302
+ status = reply[:data]
303
+
304
+ if reply[:statuscode] == 3
305
+ fail_nodes += 1
306
+ task_not_known_nodes += 1
307
+ elsif [-1, 0].include?(status[:exitcode])
308
+ status[:completed] ? completed_nodes += 1 : running_nodes += 1
309
+ runtime += status[:runtime]
310
+ reply[:statuscode] == 0 ? success_nodes += 1 : fail_nodes += 1
311
+ elsif reply[:statuscode] == 5
312
+ wrapper_failure += 1
313
+ fail_nodes += 1
314
+ else
315
+ fail_nodes += 1
316
+ end
317
+
318
+ task_names << status[:task] if status[:task]
319
+ callers << status[:callerid] if status[:callerid]
320
+
321
+ if progress
322
+ print(progress.twirl(cnt + 1, expected))
323
+
324
+ say if cnt + 1 == expected
325
+ else
326
+ cli.print_result(reply)
327
+ end
328
+
329
+ cnt += 1
330
+ end
331
+
332
+ taskid ||= bolt_tasks.stats.requestid
333
+
334
+ callers.compact!
335
+ callers.uniq!
336
+ task_names.compact!
337
+ task_names.uniq!
338
+
339
+ say
340
+
341
+ cli.print_task_summary(
342
+ taskid,
343
+ task_names,
344
+ callers,
345
+ completed_nodes,
346
+ running_nodes,
347
+ task_not_known_nodes,
348
+ wrapper_failure,
349
+ success_nodes,
350
+ fail_nodes,
351
+ runtime,
352
+ bolt_tasks.stats
353
+ )
354
+ ensure
355
+ reset_client!
356
+ end
357
+
358
+ def list_command
359
+ cli.show_task_list("production", configuration[:__detail])
360
+ end
361
+
362
+ def run
363
+ command = ARGV[0]
364
+ command = "list" unless valid_commands.include?(command)
365
+
366
+ send("%s_options" % command)
367
+
368
+ super
369
+ end
370
+
371
+ def show_task_help(task)
372
+ cli.show_task_help(task, "production")
373
+ end
374
+
375
+ def bolt_tasks
376
+ @_bolt_tasks ||= rpcclient("bolt_tasks")
377
+ end
378
+
379
+ def reset_client!
380
+ bolt_tasks.batch_size = 0
381
+ bolt_tasks.progress = options[:verbose]
382
+ end
383
+
384
+ def extract_environment_from_argv
385
+ idx = ARGV.index("--environment")
386
+
387
+ return "production" unless idx
388
+
389
+ ARGV[idx + 1]
390
+ end
391
+
392
+ def valid_commands
393
+ methods.grep(/_command$/).map {|c| c.to_s.gsub("_command", "")}
394
+ end
395
+
396
+ def choria
397
+ Util.loadclass("MCollective::Util::Choria")
398
+
399
+ @_choria ||= Util::Choria.new
400
+ end
401
+
402
+ def tasks_support
403
+ @_tasks_support ||= choria.tasks_support
404
+ end
405
+
406
+ def cli
407
+ format = configuration[:__json_format] ? :json : :default
408
+
409
+ if options
410
+ @_cli ||= tasks_support.cli(format, options[:verbose])
411
+ else
412
+ tasks_support.cli(format, false)
413
+ end
414
+ end
415
+
416
+ def main
417
+ if valid_commands.include?(configuration[:__command])
418
+ send("%s_command" % configuration[:__command])
419
+ else
420
+ show_task_help(configuration[:__command])
421
+ end
422
+ end
423
+ end
424
+ end
425
+ end