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 marionette-collective.org/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 matadata :name => "Test SimpleRPC Agent", :description => "A simple test", :author => "You", :license => "1.1", :url => "http://your.com/, :timeout => 60 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.
Returns an array of actions this agent support
# File lib/mcollective/rpc/agent.rb, line 143 def self.actions public_instance_methods.sort.grep(%r_action$/).map do |method| $1 if method =~ %r(.+)_action$/ end end
Generates help using the template based on the data created with metadata and input
# File lib/mcollective/rpc/agent.rb, line 129 def self.help(template) if @ddl @ddl.help(template) else "No DDL defined" end end
# File lib/mcollective/rpc/agent.rb, line 44 def initialize # Default meta data unset @meta = {:timeout => 10, :name => "Unknown", :description => "Unknown", :author => "Unknown", :license => "Unknown", :version => "Unknown", :url => "Unknown"} @timeout = meta[:timeout] || 10 @logger = Log.instance @config = Config.instance @agent_name = self.class.to_s.split("::").last.downcase # Loads the DDL so we can later use it for validation # and help generation begin @ddl = DDL.new(@agent_name) rescue @ddl = nil end # if we have a global authorization provider enable it # plugins can still override it per plugin self.class.authorized_by(@config.rpcauthprovider) if @config.rpcauthorization startup_hook end
# File lib/mcollective/rpc/agent.rb, line 74 def handlemsg(msg, connection) @request = RPC.request(msg) @reply = RPC.reply begin # Calls the authorization plugin if any is defined # if this raises an exception we wil just skip processing this # message authorization_hook(@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}" 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 => e @reply.fail e.to_s, 4 rescue UnknownRPCError => e @reply.fail e.to_s, 5 rescue Exception => e @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
to auto generate help
# File lib/mcollective/rpc/agent.rb, line 138 def help self.help("#{@config[:configdir]}/rpc-help.erb") end