Class: MCollective::RPC::Agent
- Inherits:
-
Object
- Object
- MCollective::RPC::Agent
- Defined in:
- lib/mcollective/rpc/agent.rb
Overview
A wrapper around the traditional agent, it takes care of a lot of the tedious setup you would do for each agent allowing you to just create methods following a naming standard leaving the heavy lifting up to this clas.
See docs.puppetlabs.com/mcollective/simplerpc/agents.html
It only really makes sense to use this with a Simple RPC client on the other end, basic usage would be:
module MCollective
module Agent
class Helloworld<RPC::Agent
action "hello" do
reply[:msg] = "Hello #{request[:name]}"
end
action "foo" do
implemented_by "/some/script.sh"
end
end
end
end
If you wish to implement the logic for an action using an external script use the implemented_by method that will cause your script to be run with 2 arguments.
The first argument is a file containing JSON with the request and the 2nd argument is where the script should save its output as a JSON hash.
We also currently have the validation code in here, this will be moved to plugins soon.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#agent_name ⇒ Object
Returns the value of attribute agent_name.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#ddl ⇒ Object
readonly
Returns the value of attribute ddl.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#meta ⇒ Object
readonly
Returns the value of attribute meta.
-
#reply ⇒ Object
Returns the value of attribute reply.
-
#request ⇒ Object
Returns the value of attribute request.
-
#timeout ⇒ Object
readonly
Returns the value of attribute timeout.
Class Method Summary collapse
-
.actions ⇒ Object
Returns an array of actions this agent support.
-
.activate? ⇒ Boolean
By default RPC Agents support a toggle in the configuration that can enable and disable them based on the agent name.
Instance Method Summary collapse
- #handlemsg(msg, connection) ⇒ Object
-
#initialize ⇒ Agent
constructor
A new instance of Agent.
- #load_ddl ⇒ Object
Constructor Details
#initialize ⇒ Agent
Returns a new instance of Agent.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/mcollective/rpc/agent.rb', line 37 def initialize @agent_name = self.class.to_s.split("::").last.downcase load_ddl @logger = Log.instance @config = Config.instance # if we have a global authorization provider enable it # plugins can still override it per plugin self.class.(@config.rpcauthprovider) if @config. startup_hook end |
Instance Attribute Details
#agent_name ⇒ Object
Returns the value of attribute agent_name.
34 35 36 |
# File 'lib/mcollective/rpc/agent.rb', line 34 def agent_name @agent_name end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
35 36 37 |
# File 'lib/mcollective/rpc/agent.rb', line 35 def config @config end |
#ddl ⇒ Object (readonly)
Returns the value of attribute ddl.
35 36 37 |
# File 'lib/mcollective/rpc/agent.rb', line 35 def ddl @ddl end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
35 36 37 |
# File 'lib/mcollective/rpc/agent.rb', line 35 def logger @logger end |
#meta ⇒ Object (readonly)
Returns the value of attribute meta.
35 36 37 |
# File 'lib/mcollective/rpc/agent.rb', line 35 def @meta end |
#reply ⇒ Object
Returns the value of attribute reply.
34 35 36 |
# File 'lib/mcollective/rpc/agent.rb', line 34 def reply @reply end |
#request ⇒ Object
Returns the value of attribute request.
34 35 36 |
# File 'lib/mcollective/rpc/agent.rb', line 34 def request @request end |
#timeout ⇒ Object (readonly)
Returns the value of attribute timeout.
35 36 37 |
# File 'lib/mcollective/rpc/agent.rb', line 35 def timeout @timeout end |
Class Method Details
.actions ⇒ Object
Returns an array of actions this agent support
160 161 162 163 164 |
# File 'lib/mcollective/rpc/agent.rb', line 160 def self.actions public_instance_methods.sort.grep(/_action$/).map do |method| $1 if method =~ /(.+)_action$/ end end |
.activate? ⇒ Boolean
By default RPC Agents support a toggle in the configuration that can enable and disable them based on the agent name
Example an agent called Foo can have:
plugin.foo.activate_agent = false
and this will prevent the agent from loading on this particular machine.
Agents can use the activate_when helper to override this for example:
activate_when do
File.exist?("/usr/bin/puppet")
end
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/mcollective/rpc/agent.rb', line 139 def self.activate? agent_name = self.to_s.split("::").last.downcase config = Config.instance Log.debug("Starting default activation checks for #{agent_name}") # Check global state to determine if agent should be loaded should_activate = config.activate_agents # Check agent specific state to determine if agent should be loaded should_activate = Util.str_to_bool(config.pluginconf.fetch("#{agent_name}.activate_agent", should_activate)) unless should_activate Log.debug("Found plugin configuration '#{agent_name}.activate_agent' with value '#{should_activate}'") end return should_activate end |
Instance Method Details
#handlemsg(msg, connection) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/mcollective/rpc/agent.rb', line 62 def handlemsg(msg, connection) @request = RPC::Request.new(msg, @ddl) @reply = RPC::Reply.new(@request.action, @ddl) begin # Incoming requests need to be validated against the DDL thus reusing # all the work users put into creating DDLs and creating a consistent # quality of input validation everywhere with the a simple once off # investment of writing a DDL @request.validate! # Calls the authorization plugin if any is defined # if this raises an exception we wil just skip processing this # message (@request) if respond_to?("authorization_hook") # Audits the request, currently continues processing the message # we should make this a configurable so that an audit failure means # a message wont be processed by this node depending on config audit_request(@request, connection) before_processing_hook(msg, connection) if respond_to?("#{@request.action}_action") send("#{@request.action}_action") else raise UnknownRPCAction, "Unknown action '#{@request.action}' for agent '#{@request.agent}'" end rescue RPCAborted => e @reply.fail e.to_s, 1 rescue UnknownRPCAction => e @reply.fail e.to_s, 2 rescue MissingRPCData => e @reply.fail e.to_s, 3 rescue InvalidRPCData, DDLValidationError => e @reply.fail e.to_s, 4 rescue UnknownRPCError => e Log.error("%s#%s failed: %s: %s" % [@agent_name, @request.action, e.class, e.to_s]) Log.error(e.backtrace.join("\n\t")) @reply.fail e.to_s, 5 rescue Exception => e Log.error("%s#%s failed: %s: %s" % [@agent_name, @request.action, e.class, e.to_s]) Log.error(e.backtrace.join("\n\t")) @reply.fail e.to_s, 5 end after_processing_hook if @request.should_respond? return @reply.to_hash else Log.debug("Client did not request a response, surpressing reply") return nil end end |
#load_ddl ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'lib/mcollective/rpc/agent.rb', line 52 def load_ddl @ddl = DDL.new(@agent_name, :agent) @meta = @ddl. @timeout = @meta[:timeout] || 10 rescue Exception => e Log.error("Failed to load DDL for the '%s' agent, DDLs are required: %s: %s" % [@agent_name, e.class, e.to_s]) raise DDLValidationError end |