1 <?xml version="1.0" encoding="iso-8859-1"?>
3 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
8 <title>Class: MCollective::RPC::Agent</title>
9 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10 <meta http-equiv="Content-Script-Type" content="text/javascript" />
11 <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
12 <script type="text/javascript">
15 function popupCode( url ) {
16 window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
19 function toggleCode( id ) {
20 if ( document.getElementById )
21 elem = document.getElementById( id );
22 else if ( document.all )
23 elem = eval( "document.all." + id );
27 elemStyle = elem.style;
29 if ( elemStyle.display != "block" ) {
30 elemStyle.display = "block"
32 elemStyle.display = "none"
38 // Make codeblocks hidden by default
39 document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
49 <div id="classHeader">
50 <table class="header-table">
51 <tr class="top-aligned-row">
52 <td><strong>Class</strong></td>
53 <td class="class-name-in-header">MCollective::RPC::Agent</td>
55 <tr class="top-aligned-row">
56 <td><strong>In:</strong></td>
58 <a href="../../../files/lib/mcollective/rpc/agent_rb.html">
59 lib/mcollective/rpc/agent.rb
65 <tr class="top-aligned-row">
66 <td><strong>Parent:</strong></td>
73 <!-- banner header -->
75 <div id="bodyContent">
79 <div id="contextContent">
81 <div id="description">
83 A wrapper around the traditional agent, it takes care of a lot of the
84 tedious setup you would do for each agent allowing you to just create
85 methods following a naming standard leaving the heavy lifting up to this
90 href="http://marionette-collective.org/simplerpc/agents.html">marionette-collective.org/simplerpc/agents.html</a>
93 It only really makes sense to use this with a Simple <a
94 href="../RPC.html">RPC</a> client on the other end, basic usage would be:
99 class Helloworld<RPC::Agent
100 action "hello" do
101 reply[:msg] = "Hello #{request[:name]}"
104 action "foo" do
105 implemented_by "/some/script.sh"
112 If you wish to implement the logic for an action using an external script
113 use the implemented_by method that will cause your script to be run with 2
117 The first argument is a file containing JSON with the request and the 2nd
118 argument is where the script should save its output as a JSON hash.
121 We also currently have the validation code in here, this will be moved to
130 <div id="method-list">
131 <h3 class="section-bar">Methods</h3>
133 <div class="name-list">
134 <a href="#M000084">actions</a>
135 <a href="#M000083">activate?</a>
136 <a href="#M000082">handlemsg</a>
137 <a href="#M000081">load_ddl</a>
138 <a href="#M000080">new</a>
147 <h3 class="section-bar">Included Modules</h3>
149 <div id="includes-list">
150 <span class="include-name"><a href="../Translatable.html">Translatable</a></span>
160 <div id="attribute-list">
161 <h3 class="section-bar">Attributes</h3>
163 <div class="name-list">
165 <tr class="top-aligned-row context-row">
166 <td class="context-item-name">agent_name</td>
167 <td class="context-item-value"> [RW] </td>
168 <td class="context-item-desc"></td>
170 <tr class="top-aligned-row context-row">
171 <td class="context-item-name">config</td>
172 <td class="context-item-value"> [R] </td>
173 <td class="context-item-desc"></td>
175 <tr class="top-aligned-row context-row">
176 <td class="context-item-name">ddl</td>
177 <td class="context-item-value"> [R] </td>
178 <td class="context-item-desc"></td>
180 <tr class="top-aligned-row context-row">
181 <td class="context-item-name">logger</td>
182 <td class="context-item-value"> [R] </td>
183 <td class="context-item-desc"></td>
185 <tr class="top-aligned-row context-row">
186 <td class="context-item-name">meta</td>
187 <td class="context-item-value"> [R] </td>
188 <td class="context-item-desc"></td>
190 <tr class="top-aligned-row context-row">
191 <td class="context-item-name">reply</td>
192 <td class="context-item-value"> [RW] </td>
193 <td class="context-item-desc"></td>
195 <tr class="top-aligned-row context-row">
196 <td class="context-item-name">request</td>
197 <td class="context-item-value"> [RW] </td>
198 <td class="context-item-desc"></td>
200 <tr class="top-aligned-row context-row">
201 <td class="context-item-name">timeout</td>
202 <td class="context-item-value"> [R] </td>
203 <td class="context-item-desc"></td>
211 <!-- if method_list -->
213 <h3 class="section-bar">Public Class methods</h3>
215 <div id="method-M000084" class="method-detail">
216 <a name="M000084"></a>
218 <div class="method-heading">
219 <a href="#M000084" class="method-signature">
220 <span class="method-name">actions</span><span class="method-args">()</span>
224 <div class="method-description">
226 Returns an array of <a href="Agent.html#M000084">actions</a> this agent
229 <p><a class="source-toggle" href="#"
230 onclick="toggleCode('M000084-source');return false;">[Source]</a></p>
231 <div class="method-source-code" id="M000084-source">
233 <span class="ruby-comment cmt"># File lib/mcollective/rpc/agent.rb, line 157</span>
234 157: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">actions</span>
235 158: <span class="ruby-identifier">public_instance_methods</span>.<span class="ruby-identifier">sort</span>.<span class="ruby-identifier">grep</span>(<span class="ruby-regexp re">/_action$/</span>).<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">method</span><span class="ruby-operator">|</span>
236 159: <span class="ruby-identifier">$1</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">method</span> <span class="ruby-operator">=~</span> <span class="ruby-regexp re">/(.+)_action$/</span>
237 160: <span class="ruby-keyword kw">end</span>
238 161: <span class="ruby-keyword kw">end</span>
244 <div id="method-M000083" class="method-detail">
245 <a name="M000083"></a>
247 <div class="method-heading">
248 <a href="#M000083" class="method-signature">
249 <span class="method-name">activate?</span><span class="method-args">()</span>
253 <div class="method-description">
255 By default <a href="../RPC.html">RPC</a> <a
256 href="../Agents.html">Agents</a> support a toggle in the configuration that
257 can enable and disable them based on the agent name
260 Example an agent called Foo can have:
263 plugin.foo.activate_agent = false
266 and this will prevent the agent from loading on this particular machine.
269 <a href="../Agents.html">Agents</a> can use the activate_when helper to
270 override this for example:
276 File.exist?("/usr/bin/puppet")
281 <p><a class="source-toggle" href="#"
282 onclick="toggleCode('M000083-source');return false;">[Source]</a></p>
283 <div class="method-source-code" id="M000083-source">
285 <span class="ruby-comment cmt"># File lib/mcollective/rpc/agent.rb, line 142</span>
286 142: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">activate?</span>
287 143: <span class="ruby-identifier">agent_name</span> = <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">to_s</span>.<span class="ruby-identifier">split</span>(<span class="ruby-value str">"::"</span>).<span class="ruby-identifier">last</span>.<span class="ruby-identifier">downcase</span>
289 145: <span class="ruby-identifier">log_code</span>(<span class="ruby-identifier">:PLMC37</span>, <span class="ruby-value str">"Starting default activation checks for the '%{agent}' agent"</span>, <span class="ruby-identifier">:debug</span>, <span class="ruby-identifier">:agent</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">agent_name</span>)
291 147: <span class="ruby-identifier">should_activate</span> = <span class="ruby-constant">Util</span>.<span class="ruby-identifier">str_to_bool</span>(<span class="ruby-constant">Config</span>.<span class="ruby-identifier">instance</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">fetch</span>(<span class="ruby-node">"#{agent_name}.activate_agent"</span>, <span class="ruby-keyword kw">true</span>))
293 149: <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">should_activate</span>
294 150: <span class="ruby-identifier">log_code</span>(<span class="ruby-identifier">:PLMC38</span>, <span class="ruby-value str">"Found plugin configuration '%{agent}.activate_agent' with value '%{should_activate}'"</span>, <span class="ruby-identifier">:debug</span>, <span class="ruby-identifier">:agent</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">agent_name</span>, <span class="ruby-identifier">:should_activate</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">should_activate</span>)
295 151: <span class="ruby-keyword kw">end</span>
297 153: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">should_activate</span>
298 154: <span class="ruby-keyword kw">end</span>
304 <div id="method-M000080" class="method-detail">
305 <a name="M000080"></a>
307 <div class="method-heading">
308 <a href="#M000080" class="method-signature">
309 <span class="method-name">new</span><span class="method-args">()</span>
313 <div class="method-description">
314 <p><a class="source-toggle" href="#"
315 onclick="toggleCode('M000080-source');return false;">[Source]</a></p>
316 <div class="method-source-code" id="M000080-source">
318 <span class="ruby-comment cmt"># File lib/mcollective/rpc/agent.rb, line 40</span>
319 40: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>
320 41: <span class="ruby-ivar">@agent_name</span> = <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">class</span>.<span class="ruby-identifier">to_s</span>.<span class="ruby-identifier">split</span>(<span class="ruby-value str">"::"</span>).<span class="ruby-identifier">last</span>.<span class="ruby-identifier">downcase</span>
322 43: <span class="ruby-identifier">load_ddl</span>
324 45: <span class="ruby-ivar">@logger</span> = <span class="ruby-constant">Log</span>.<span class="ruby-identifier">instance</span>
325 46: <span class="ruby-ivar">@config</span> = <span class="ruby-constant">Config</span>.<span class="ruby-identifier">instance</span>
327 48: <span class="ruby-comment cmt"># if we have a global authorization provider enable it</span>
328 49: <span class="ruby-comment cmt"># plugins can still override it per plugin</span>
329 50: <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">class</span>.<span class="ruby-identifier">authorized_by</span>(<span class="ruby-ivar">@config</span>.<span class="ruby-identifier">rpcauthprovider</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">rpcauthorization</span>
331 52: <span class="ruby-identifier">startup_hook</span>
332 53: <span class="ruby-keyword kw">end</span>
338 <h3 class="section-bar">Public Instance methods</h3>
340 <div id="method-M000082" class="method-detail">
341 <a name="M000082"></a>
343 <div class="method-heading">
344 <a href="#M000082" class="method-signature">
345 <span class="method-name">handlemsg</span><span class="method-args">(msg, connection)</span>
349 <div class="method-description">
350 <p><a class="source-toggle" href="#"
351 onclick="toggleCode('M000082-source');return false;">[Source]</a></p>
352 <div class="method-source-code" id="M000082-source">
354 <span class="ruby-comment cmt"># File lib/mcollective/rpc/agent.rb, line 64</span>
355 64: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">handlemsg</span>(<span class="ruby-identifier">msg</span>, <span class="ruby-identifier">connection</span>)
356 65: <span class="ruby-ivar">@request</span> = <span class="ruby-constant">RPC</span><span class="ruby-operator">::</span><span class="ruby-constant">Request</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">msg</span>, <span class="ruby-ivar">@ddl</span>)
357 66: <span class="ruby-ivar">@reply</span> = <span class="ruby-constant">RPC</span><span class="ruby-operator">::</span><span class="ruby-constant">Reply</span>.<span class="ruby-identifier">new</span>(<span class="ruby-ivar">@request</span>.<span class="ruby-identifier">action</span>, <span class="ruby-ivar">@ddl</span>)
359 68: <span class="ruby-keyword kw">begin</span>
360 69: <span class="ruby-comment cmt"># Incoming requests need to be validated against the DDL thus reusing</span>
361 70: <span class="ruby-comment cmt"># all the work users put into creating DDLs and creating a consistent</span>
362 71: <span class="ruby-comment cmt"># quality of input validation everywhere with the a simple once off</span>
363 72: <span class="ruby-comment cmt"># investment of writing a DDL</span>
364 73: <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">validate!</span>
366 75: <span class="ruby-comment cmt"># Calls the authorization plugin if any is defined</span>
367 76: <span class="ruby-comment cmt"># if this raises an exception we wil just skip processing this</span>
368 77: <span class="ruby-comment cmt"># message</span>
369 78: <span class="ruby-identifier">authorization_hook</span>(<span class="ruby-ivar">@request</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">respond_to?</span>(<span class="ruby-value str">"authorization_hook"</span>)
371 80: <span class="ruby-comment cmt"># Audits the request, currently continues processing the message</span>
372 81: <span class="ruby-comment cmt"># we should make this a configurable so that an audit failure means</span>
373 82: <span class="ruby-comment cmt"># a message wont be processed by this node depending on config</span>
374 83: <span class="ruby-identifier">audit_request</span>(<span class="ruby-ivar">@request</span>, <span class="ruby-identifier">connection</span>)
376 85: <span class="ruby-identifier">before_processing_hook</span>(<span class="ruby-identifier">msg</span>, <span class="ruby-identifier">connection</span>)
378 87: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">respond_to?</span>(<span class="ruby-node">"#{@request.action}_action"</span>)
379 88: <span class="ruby-identifier">send</span>(<span class="ruby-node">"#{@request.action}_action"</span>)
380 89: <span class="ruby-keyword kw">else</span>
381 90: <span class="ruby-identifier">log_code</span>(<span class="ruby-identifier">:PLMC36</span>, <span class="ruby-value str">"Unknown action '%{action}' for agent '%{agent}'"</span>, <span class="ruby-identifier">:warn</span>, <span class="ruby-identifier">:action</span> =<span class="ruby-operator">></span> <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">action</span>, <span class="ruby-identifier">:agent</span> =<span class="ruby-operator">></span> <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">agent</span>)
382 91: <span class="ruby-identifier">raise</span> <span class="ruby-constant">UnknownRPCAction</span>, <span class="ruby-node">"Unknown action '#{@request.action}' for agent '#{@request.agent}'"</span>
383 92: <span class="ruby-keyword kw">end</span>
384 93: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">RPCAborted</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
385 94: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">1</span>
387 96: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">UnknownRPCAction</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
388 97: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">2</span>
390 99: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">MissingRPCData</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
391 100: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">3</span>
393 102: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">InvalidRPCData</span>, <span class="ruby-constant">DDLValidationError</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
394 103: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">4</span>
396 105: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">UnknownRPCError</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
397 106: <span class="ruby-constant">Log</span>.<span class="ruby-identifier">error</span>(<span class="ruby-value str">"%s#%s failed: %s: %s"</span> <span class="ruby-operator">%</span> [<span class="ruby-ivar">@agent_name</span>, <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">action</span>, <span class="ruby-identifier">e</span>.<span class="ruby-identifier">class</span>, <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>])
398 107: <span class="ruby-constant">Log</span>.<span class="ruby-identifier">error</span>(<span class="ruby-identifier">e</span>.<span class="ruby-identifier">backtrace</span>.<span class="ruby-identifier">join</span>(<span class="ruby-value str">"\n\t"</span>))
399 108: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">5</span>
401 110: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">Exception</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
402 111: <span class="ruby-constant">Log</span>.<span class="ruby-identifier">error</span>(<span class="ruby-value str">"%s#%s failed: %s: %s"</span> <span class="ruby-operator">%</span> [<span class="ruby-ivar">@agent_name</span>, <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">action</span>, <span class="ruby-identifier">e</span>.<span class="ruby-identifier">class</span>, <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>])
403 112: <span class="ruby-constant">Log</span>.<span class="ruby-identifier">error</span>(<span class="ruby-identifier">e</span>.<span class="ruby-identifier">backtrace</span>.<span class="ruby-identifier">join</span>(<span class="ruby-value str">"\n\t"</span>))
404 113: <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">fail</span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>, <span class="ruby-value">5</span>
406 115: <span class="ruby-keyword kw">end</span>
408 117: <span class="ruby-identifier">after_processing_hook</span>
410 119: <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">should_respond?</span>
411 120: <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@reply</span>.<span class="ruby-identifier">to_hash</span>
412 121: <span class="ruby-keyword kw">else</span>
413 122: <span class="ruby-identifier">log_code</span>(<span class="ruby-identifier">:PLMC35</span>, <span class="ruby-value str">"Client did not request a response, surpressing reply"</span>, <span class="ruby-identifier">:debug</span>)
414 123: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">nil</span>
415 124: <span class="ruby-keyword kw">end</span>
416 125: <span class="ruby-keyword kw">end</span>
422 <div id="method-M000081" class="method-detail">
423 <a name="M000081"></a>
425 <div class="method-heading">
426 <a href="#M000081" class="method-signature">
427 <span class="method-name">load_ddl</span><span class="method-args">()</span>
431 <div class="method-description">
432 <p><a class="source-toggle" href="#"
433 onclick="toggleCode('M000081-source');return false;">[Source]</a></p>
434 <div class="method-source-code" id="M000081-source">
436 <span class="ruby-comment cmt"># File lib/mcollective/rpc/agent.rb, line 55</span>
437 55: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">load_ddl</span>
438 56: <span class="ruby-ivar">@ddl</span> = <span class="ruby-constant">DDL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-ivar">@agent_name</span>, <span class="ruby-identifier">:agent</span>)
439 57: <span class="ruby-ivar">@meta</span> = <span class="ruby-ivar">@ddl</span>.<span class="ruby-identifier">meta</span>
440 58: <span class="ruby-ivar">@timeout</span> = <span class="ruby-ivar">@meta</span>[<span class="ruby-identifier">:timeout</span>] <span class="ruby-operator">||</span> <span class="ruby-value">10</span>
442 60: <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">Exception</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
443 61: <span class="ruby-constant">DDL</span>.<span class="ruby-identifier">validation_fail!</span>(<span class="ruby-identifier">:PLMC24</span>, <span class="ruby-value str">"Failed to load DDL for the '%{agent}' agent, DDLs are required: %{error_class}: %{error}"</span>, <span class="ruby-identifier">:error</span>, <span class="ruby-identifier">:agent</span> =<span class="ruby-operator">></span> <span class="ruby-ivar">@agent_name</span>, <span class="ruby-identifier">:error_class</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">class</span>, <span class="ruby-identifier">:error</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>.<span class="ruby-identifier">to_s</span>)
444 62: <span class="ruby-keyword kw">end</span>
457 <div id="validator-badges">
458 <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>