choria-mcorpc-support 2.22.1 → 2.23.0.pre

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 +11 -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 -26
  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 +52 -53
  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 +67 -4
@@ -0,0 +1,224 @@
1
+ {
2
+ "$schema": "https://choria.io/schemas/mcorpc/ddl/v1/agent.json",
3
+ "metadata": {
4
+ "name": "scout",
5
+ "description": "Choria Scout Agent Management API",
6
+ "author": "R.I.Pienaar <rip@devco.net>",
7
+ "license": "Apache-2.0",
8
+ "version": "0.0.1",
9
+ "url": "https://choria.io",
10
+ "provider": "golang",
11
+ "timeout": 5
12
+ },
13
+ "actions": [
14
+ {
15
+ "action": "checks",
16
+ "input": {
17
+ },
18
+ "output": {
19
+ "checks": {
20
+ "description": "Details about each check",
21
+ "display_as": "Checks",
22
+ "default": null,
23
+ "type": "array"
24
+ }
25
+ },
26
+ "display": "ok",
27
+ "description": "Obtain a list of checks and their current status"
28
+ },
29
+ {
30
+ "action": "goss_validate",
31
+ "input": {
32
+ "file": {
33
+ "prompt": "Goss File",
34
+ "description": "Path to the Goss validation specification",
35
+ "type": "string",
36
+ "default": null,
37
+ "optional": false,
38
+ "validation": ".+",
39
+ "maxlength": 256
40
+ },
41
+ "vars": {
42
+ "prompt": "Vars File",
43
+ "description": "Path to a file to use as template variables",
44
+ "type": "string",
45
+ "default": null,
46
+ "optional": true,
47
+ "validation": ".+",
48
+ "maxlength": 256
49
+ }
50
+ },
51
+ "output": {
52
+ "failures": {
53
+ "description": "The number of tests that failed",
54
+ "display_as": "Failed Tests",
55
+ "default": null,
56
+ "type": "integer"
57
+ },
58
+ "results": {
59
+ "description": "The full test results",
60
+ "display_as": "Results",
61
+ "default": null,
62
+ "type": "array"
63
+ },
64
+ "runtime": {
65
+ "description": "The time it took to run the tests, in seconds",
66
+ "display_as": "Runtime",
67
+ "default": null,
68
+ "type": "integer"
69
+ },
70
+ "success": {
71
+ "description": "Indicates if the test passed",
72
+ "display_as": "Success",
73
+ "default": null,
74
+ "type": "string"
75
+ },
76
+ "summary": {
77
+ "description": "A human friendly test result",
78
+ "display_as": "Summary",
79
+ "default": null,
80
+ "type": "string"
81
+ },
82
+ "tests": {
83
+ "description": "The number of tests that were run",
84
+ "display_as": "Tests",
85
+ "default": null,
86
+ "type": "integer"
87
+ }
88
+ },
89
+ "display": "failed",
90
+ "description": "Performs a Goss validation using a specific file",
91
+ "aggregate": [
92
+ {
93
+ "function": "summary",
94
+ "args": [
95
+ "tests",
96
+ {
97
+ "format": "%s Test Cases on %d node(s)"
98
+ }
99
+ ]
100
+ },
101
+ {
102
+ "function": "summary",
103
+ "args": [
104
+ "failures",
105
+ {
106
+ "format": "%s Failed Cases on %d node(s)"
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ "function": "summary",
112
+ "args": [
113
+ "success",
114
+ {
115
+ "format": "%s Passed Cases on %d node(s)"
116
+ }
117
+ ]
118
+ }
119
+ ]
120
+ },
121
+ {
122
+ "action": "maintenance",
123
+ "input": {
124
+ "checks": {
125
+ "prompt": "Checks",
126
+ "description": "Check to pause, empty means all",
127
+ "type": "array",
128
+ "default": null,
129
+ "optional": true
130
+ }
131
+ },
132
+ "output": {
133
+ "failed": {
134
+ "description": "List of checks that could not be paused",
135
+ "display_as": "Failed",
136
+ "default": null,
137
+ "type": "array"
138
+ },
139
+ "skipped": {
140
+ "description": "List of checks that was skipped",
141
+ "display_as": "Skipped",
142
+ "default": null,
143
+ "type": "array"
144
+ },
145
+ "transitioned": {
146
+ "description": "List of checks that were paused",
147
+ "display_as": "Triggered",
148
+ "default": null,
149
+ "type": "array"
150
+ }
151
+ },
152
+ "display": "failed",
153
+ "description": "Pause checking of one or more checks"
154
+ },
155
+ {
156
+ "action": "resume",
157
+ "input": {
158
+ "checks": {
159
+ "prompt": "Checks",
160
+ "description": "Check to resume, empty means all",
161
+ "type": "array",
162
+ "default": null,
163
+ "optional": true
164
+ }
165
+ },
166
+ "output": {
167
+ "failed": {
168
+ "description": "List of checks that could not be resumed",
169
+ "display_as": "Failed",
170
+ "default": null,
171
+ "type": "array"
172
+ },
173
+ "skipped": {
174
+ "description": "List of checks that was skipped",
175
+ "display_as": "Skipped",
176
+ "default": null,
177
+ "type": "array"
178
+ },
179
+ "transitioned": {
180
+ "description": "List of checks that were resumed",
181
+ "display_as": "Triggered",
182
+ "default": null,
183
+ "type": "array"
184
+ }
185
+ },
186
+ "display": "failed",
187
+ "description": "Resume active checking of one or more checks"
188
+ },
189
+ {
190
+ "action": "trigger",
191
+ "input": {
192
+ "checks": {
193
+ "prompt": "Checks",
194
+ "description": "Check to trigger, empty means all",
195
+ "type": "array",
196
+ "default": null,
197
+ "optional": true
198
+ }
199
+ },
200
+ "output": {
201
+ "failed": {
202
+ "description": "List of checks that could not be triggered",
203
+ "display_as": "Failed",
204
+ "default": null,
205
+ "type": "array"
206
+ },
207
+ "skipped": {
208
+ "description": "List of checks that was skipped",
209
+ "display_as": "Skipped",
210
+ "default": null,
211
+ "type": "array"
212
+ },
213
+ "transitioned": {
214
+ "description": "List of checks that were triggered",
215
+ "display_as": "Triggered",
216
+ "default": null,
217
+ "type": "array"
218
+ }
219
+ },
220
+ "display": "failed",
221
+ "description": "Force an immediate check of one or more checks"
222
+ }
223
+ ]
224
+ }
@@ -42,6 +42,7 @@ module MCollective
42
42
  def loadagent(agentname)
43
43
  agentfile = findagentfile(agentname)
44
44
  return false unless agentfile
45
+
45
46
  classname = class_for_agent(agentname)
46
47
 
47
48
  PluginManager.delete("#{agentname}_agent")
@@ -62,16 +63,16 @@ module MCollective
62
63
  Util.subscribe(Util.make_subscriptions(agentname, :broadcast)) unless @@agents.include?(agentname)
63
64
 
64
65
  @@agents[agentname] = {:file => agentfile}
65
- return true
66
+ true
66
67
  else
67
68
  Log.debug("Not activating agent #{agentname} due to agent policy in activate? method")
68
- return false
69
+ false
69
70
  end
70
71
  rescue Exception # rubocop:disable Lint/RescueException
71
72
  Log.error("Loading agent %s failed: %s" % [agentname, $!])
72
73
  PluginManager.delete("%s_agent" % agentname)
73
74
 
74
- return false
75
+ false
75
76
  end
76
77
  end
77
78
 
@@ -87,14 +88,14 @@ module MCollective
87
88
  klass = Kernel.const_get("MCollective").const_get("Agent").const_get(agent.capitalize)
88
89
 
89
90
  if klass.respond_to?("activate?")
90
- return klass.activate?
91
+ klass.activate?
91
92
  else
92
93
  Log.debug("#{klass} does not have an activate? method, activating as default")
93
- return true
94
+ true
94
95
  end
95
96
  rescue Exception # rubocop:disable Lint/RescueException
96
97
  Log.warn("Agent activation check for %s #{agent} failed: %s: %s" % [agent, $!.class, $!])
97
- return false
98
+ false
98
99
  end
99
100
 
100
101
  # searches the libdirs for agents
@@ -25,7 +25,7 @@ module MCollective
25
25
  format = (arguments.delete(:format) if arguments) || nil
26
26
  begin
27
27
  @functions << load_function(agg[:function]).new(output, arguments, format, @action)
28
- rescue Exception => e
28
+ rescue Exception => e # rubocop:disable Lint/RescueException
29
29
  Log.error("Cannot create aggregate function '%s': %s" % [output, e])
30
30
  @failed << {:name => output, :type => :startup}
31
31
  end
@@ -47,7 +47,7 @@ module MCollective
47
47
  Log.debug("Calling aggregate function %s for result" % function)
48
48
  begin
49
49
  function.process_result(reply[:data][function.output_name], reply)
50
- rescue Exception => e
50
+ rescue Exception => e # rubocop:disable Lint/RescueException
51
51
  Log.error("Could not process aggregate function for '%s': %s" % [function.output_name, e])
52
52
  @failed << {:name => function.output_name, :type => :process_result}
53
53
  @functions.delete(function)
@@ -60,7 +60,7 @@ module MCollective
60
60
  summary = @functions.map do |function|
61
61
  begin
62
62
  function.summarize
63
- rescue Exception => e
63
+ rescue Exception => e # rubocop:disable Lint/RescueException
64
64
  Log.error("Could not summarize aggregate result for '%s': %s" % [function.output_name, e])
65
65
  @failed << {:name => function.output_name, :type => :summarize}
66
66
  nil
@@ -78,7 +78,7 @@ module MCollective
78
78
 
79
79
  PluginManager.loadclass("MCollective::Aggregate::%s" % function_name) unless Aggregate.const_defined?(function_name)
80
80
  Aggregate.const_get(function_name)
81
- rescue Exception
81
+ rescue Exception # rubocop:disable Lint/RescueException
82
82
  raise("Aggregate function file '%s.rb' cannot be loaded" % function_name.downcase)
83
83
  end
84
84
  end
@@ -1,6 +1,6 @@
1
1
  module MCollective
2
2
  class Aggregate
3
- class Average<Base
3
+ class Average < Base
4
4
  # Before function is run processing
5
5
  def startup_hook
6
6
  @result[:value] = 0
@@ -9,7 +9,7 @@ module MCollective
9
9
  @count = 0
10
10
 
11
11
  # Set default aggregate_function if it is undefined
12
- @aggregate_format = "Average of #{@result[:output]}: %f" unless @aggregate_format
12
+ @aggregate_format ||= "Average of #{@result[:output]}: %f"
13
13
  end
14
14
 
15
15
  # Determines the average of a set of numerical values
@@ -17,9 +17,9 @@ module MCollective
17
17
  startup_hook
18
18
  end
19
19
 
20
- ['startup_hook', 'process_result'].each do |method|
20
+ ["startup_hook", "process_result"].each do |method|
21
21
  define_method method do
22
- raise RuntimeError, "'#{method}' method of function class #{@name} has not yet been implemented"
22
+ raise "'#{method}' method of function class #{@name} has not yet been implemented"
23
23
  end
24
24
  end
25
25
 
@@ -1,9 +1,9 @@
1
1
  module MCollective
2
2
  class Aggregate
3
3
  module Result
4
- require 'mcollective/aggregate/result/base'
5
- require 'mcollective/aggregate/result/numeric_result'
6
- require 'mcollective/aggregate/result/collection_result'
4
+ require "mcollective/aggregate/result/base"
5
+ require "mcollective/aggregate/result/numeric_result"
6
+ require "mcollective/aggregate/result/collection_result"
7
7
  end
8
8
  end
9
9
  end
@@ -1,13 +1,13 @@
1
1
  module MCollective
2
2
  class Aggregate
3
3
  module Result
4
- class CollectionResult<Base
4
+ class CollectionResult < Base
5
5
  def to_s
6
6
  return "" if @result[:value].keys.include?(nil)
7
7
 
8
8
  result = StringIO.new
9
9
 
10
- @result[:value].sort{|x,y| x[1] <=> y[1]}.reverse.each do |value|
10
+ @result[:value].sort {|x, y| x[1] <=> y[1]}.reverse.each do |value|
11
11
  result.puts @aggregate_format % [value[0], value[1]]
12
12
  end
13
13
 
@@ -1,11 +1,11 @@
1
1
  module MCollective
2
2
  class Aggregate
3
3
  module Result
4
- class NumericResult<Base
4
+ class NumericResult < Base
5
5
  def to_s
6
6
  return "" if @result[:value].nil?
7
7
 
8
- return @aggregate_format % @result[:value]
8
+ @aggregate_format % @result[:value]
9
9
  end
10
10
  end
11
11
  end
@@ -1,12 +1,12 @@
1
1
  module MCollective
2
2
  class Aggregate
3
- class Sum<Base
3
+ class Sum < Base
4
4
  def startup_hook
5
5
  @result[:value] = 0
6
6
  @result[:type] = :numeric
7
7
 
8
8
  # Set default aggregate_function if it is undefined
9
- @aggregate_format = "Sum of #{@result[:output]}: %f" unless @aggregate_format
9
+ @aggregate_format ||= "Sum of #{@result[:output]}: %f"
10
10
  end
11
11
 
12
12
  # Determines the average of a set of numerical values
@@ -1,13 +1,13 @@
1
1
  module MCollective
2
2
  class Aggregate
3
- class Summary<Base
3
+ class Summary < Base
4
4
  # Before function is run processing
5
5
  def startup_hook
6
6
  @result[:value] = {}
7
7
  @result[:type] = :collection
8
8
 
9
9
  # set default aggregate_format if it is undefined
10
- @aggregate_format = :calculate unless @aggregate_format
10
+ @aggregate_format ||= :calculate
11
11
  end
12
12
 
13
13
  # Increments the value field if value has been seen before
@@ -15,7 +15,7 @@ module MCollective
15
15
  def process_result(value, reply)
16
16
  unless value.nil?
17
17
  if value.is_a? Array
18
- value.map{|val| add_value(val)}
18
+ value.map {|val| add_value(val)}
19
19
  else
20
20
  add_value(value)
21
21
  end
@@ -33,7 +33,6 @@ module MCollective
33
33
  def summarize
34
34
  if @aggregate_format == :calculate
35
35
  max_key_length = @result[:value].keys.map do |k|
36
-
37
36
  # Response values retain their types. Here we check
38
37
  # if the response is a string and turn it into a string
39
38
  # if it isn't one.
@@ -31,6 +31,24 @@ module MCollective
31
31
  self[:description] = descr
32
32
  end
33
33
 
34
+ # Executes an external program instead of implement the logic in ruby
35
+ #
36
+ # @param [Hash] command the command to run
37
+ # @option command [String] :command the command to run
38
+ # @option command [Array] :args arguments to pass to the command
39
+ def external(command)
40
+ self[:external] = command
41
+ end
42
+
43
+ # Executes an external program to show help instead of supplying options
44
+ #
45
+ # @param [Hash] command the command to run
46
+ # @option command [String] :command the command to run
47
+ # @option command [Array] :args arguments to pass to the command
48
+ def external_help(command)
49
+ self[:external_help] = command
50
+ end
51
+
34
52
  # Supplies usage information, calling multiple times will
35
53
  # create multiple usage lines in --help output
36
54
  def usage(usage)
@@ -79,10 +97,12 @@ module MCollective
79
97
 
80
98
  # Creates an empty set of options
81
99
  def intialize_application_options
82
- @application_options = {:description => nil,
83
- :usage => [],
84
- :cli_arguments => [],
85
- :exclude_arg_sections => []}
100
+ @application_options = {:description => nil,
101
+ :usage => [],
102
+ :cli_arguments => [],
103
+ :exclude_arg_sections => [],
104
+ :external => nil,
105
+ :external_help => nil}
86
106
  end
87
107
  end
88
108
 
@@ -101,7 +121,7 @@ module MCollective
101
121
  validation_result = blk.call(value)
102
122
 
103
123
  unless validation_result == true
104
- STDERR.puts "Validation of #{name} failed: #{validation_result}"
124
+ warn "Validation of #{name} failed: #{validation_result}"
105
125
  exit 1
106
126
  end
107
127
  end
@@ -123,7 +143,7 @@ module MCollective
123
143
 
124
144
  post_option_parser(configuration) if respond_to?(:post_option_parser)
125
145
 
126
- return options
146
+ options
127
147
  rescue Exception # rubocop:disable Lint/RescueException
128
148
  application_failure($!)
129
149
  end
@@ -205,14 +225,15 @@ module MCollective
205
225
  application_cli_arguments.each do |carg|
206
226
  # Check for required arguments
207
227
  next unless carg[:required]
228
+
208
229
  unless configuration[carg[:name]]
209
230
  validation_passed = false
210
- STDERR.puts "The #{carg[:name]} option is mandatory"
231
+ warn "The #{carg[:name]} option is mandatory"
211
232
  end
212
233
  end
213
234
 
214
235
  unless validation_passed
215
- STDERR.puts "\nPlease run with --help for detailed help"
236
+ warn "\nPlease run with --help for detailed help"
216
237
  exit 1
217
238
  end
218
239
  end
@@ -242,23 +263,23 @@ module MCollective
242
263
 
243
264
  # Handles failure, if we're far enough in the initialization
244
265
  # phase it will log backtraces if its in verbose mode only
245
- def application_failure(e, err_dest=STDERR)
266
+ def application_failure(err, err_dest=$stderr)
246
267
  # peole can use exit() anywhere and not get nasty backtraces as a result
247
- if e.is_a?(SystemExit)
268
+ if err.is_a?(SystemExit)
248
269
  disconnect
249
- raise(e)
270
+ raise(err)
250
271
  end
251
272
 
252
273
  if options[:verbose]
253
- err_dest.puts "\nThe %s application failed to run: %s\n" % [Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]
274
+ err_dest.puts "\nThe %s application failed to run: %s\n" % [Util.colorize(:bold, $0), Util.colorize(:red, err.to_s)]
254
275
  else
255
- err_dest.puts "\nThe %s application failed to run, use -v for full error backtrace details: %s\n" % [Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]
276
+ err_dest.puts "\nThe %s application failed to run, use -v for full error backtrace details: %s\n" % [Util.colorize(:bold, $0), Util.colorize(:red, err.to_s)]
256
277
  end
257
278
 
258
279
  if options.nil? || options[:verbose]
259
- e.backtrace.first << Util.colorize(:red, " <----")
260
- err_dest.puts "\n%s %s" % [Util.colorize(:red, e.to_s), Util.colorize(:bold, "(#{e.class})")]
261
- e.backtrace.each {|l| err_dest.puts "\tfrom #{l}"}
280
+ err.backtrace.first << Util.colorize(:red, " <----")
281
+ err_dest.puts "\n%s %s" % [Util.colorize(:red, err.to_s), Util.colorize(:bold, "(#{err.class})")]
282
+ err.backtrace.each {|l| err_dest.puts "\tfrom #{l}"}
262
283
  end
263
284
 
264
285
  disconnect
@@ -266,7 +287,14 @@ module MCollective
266
287
  exit 1
267
288
  end
268
289
 
290
+ def external_help
291
+ ext = application_options[:external_help]
292
+ exec(ext[:command], ext[:args])
293
+ end
294
+
269
295
  def help
296
+ return external_help if application_options[:external_help]
297
+
270
298
  application_parse_options(true)
271
299
  end
272
300
 
@@ -274,6 +302,8 @@ module MCollective
274
302
  # the main as supplied by the user. Disconnects when done and pass any exception
275
303
  # onto the application_failure helper
276
304
  def run
305
+ return external_main if application_options[:external]
306
+
277
307
  application_parse_options
278
308
 
279
309
  validate_configuration(configuration) if respond_to?(:validate_configuration)
@@ -289,13 +319,21 @@ module MCollective
289
319
 
290
320
  def disconnect
291
321
  MCollective::PluginManager["connector_plugin"].disconnect
292
- rescue # rubocop:disable Lint/HandleExceptions
322
+ rescue # rubocop:disable Lint/SuppressedException
323
+ end
324
+
325
+ def external_main
326
+ ext = application_options[:external]
327
+ args = ext[:args] || []
328
+ args.concat(ARGV)
329
+
330
+ exec(ext[:command], *args)
293
331
  end
294
332
 
295
333
  # Fake abstract class that logs if the user tries to use an application without
296
334
  # supplying a main override method.
297
335
  def main
298
- STDERR.puts "Applications need to supply a 'main' method"
336
+ warn "Applications need to supply a 'main' method"
299
337
  exit 1
300
338
  end
301
339
 
@@ -305,9 +343,7 @@ module MCollective
305
343
  :okcount => 0,
306
344
  :failcount => 0}.merge(stats.to_hash)
307
345
 
308
- if request_stats[:discoverytime] == 0 && request_stats[:responses] == 0
309
- return 4
310
- end
346
+ return 4 if request_stats[:discoverytime] == 0 && request_stats[:responses] == 0
311
347
 
312
348
  if request_stats[:discovered] > 0
313
349
  if request_stats[:responses] == 0