X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=doc%2Fclasses%2FMCollective%2FDDL%2FAgentDDL.html;fp=doc%2Fclasses%2FMCollective%2FDDL%2FAgentDDL.html;h=f2bd1efde2362b805ea5914dbdcf44e6850f2dfe;hb=d1f1649ba43c5cbc43c4beb2380096ba051d646a;hp=0000000000000000000000000000000000000000;hpb=8a3fe7daeecccf43dd71c59371c5005400d35101;p=packages%2Fprecise%2Fmcollective.git diff --git a/doc/classes/MCollective/DDL/AgentDDL.html b/doc/classes/MCollective/DDL/AgentDDL.html new file mode 100644 index 0000000..f2bd1ef --- /dev/null +++ b/doc/classes/MCollective/DDL/AgentDDL.html @@ -0,0 +1,627 @@ + + + + +
+Class | +MCollective::DDL::AgentDDL | +
In: | +
+
+ lib/mcollective/ddl/agentddl.rb
+
+ + |
+
Parent: | ++ + Base + + | +
+A DDL class specific to agent plugins. +
++A full DDL can be seen below with all the +possible bells and whistles present. +
++metadata :name => "Utilities and Helpers for SimpleRPC Agents", +
++ :description => "General helpful actions that expose stats and internals to SimpleRPC clients", + :author => "R.I.Pienaar <rip@devco.net>", + :license => "Apache License, Version 2.0", + :version => "1.0", + :url => "http://marionette-collective.org/", + :timeout => 10 ++
+action "get_fact", +:description => "Retrieve a single fact from the fact store" +do +
++ display :always + + input :fact, + :prompt => "The name of the fact", + :description => "The fact to retrieve", + :type => :string, + :validation => '^[\w\-\.]+$', + :optional => false, + :maxlength => 40, + :default => "fqdn" + + output :fact, + :description => "The name of the fact being returned", + :display_as => "Fact" + + output :value, + :description => "The value of the fact", + :display_as => "Value", + :default => "" + + summarize do + aggregate summary(:value) + end ++
+end +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 41 +41: def initialize(plugin, plugintype=:agent, loadddl=true) +42: @process_aggregate_functions = nil +43: +44: super +45: end ++
+Creates the definition for an action, +you can nest input definitions inside +the action to attach inputs and +validation to the actions +
++ action "status", :description => "Restarts a Service" do + display :always + + input "service", + :prompt => "Service Action", + :description => "The action to perform", + :type => :list, + :optional => true, + :list => ["start", "stop", "restart", "status"] + + output "status", + :description => "The status of the service after the action" + + end ++ +
+ # File lib/mcollective/ddl/agentddl.rb, line 112 +112: def action(name, input, &block) +113: raise "Action needs a :description property" unless input.include?(:description) +114: +115: unless @entities.include?(name) +116: @entities[name] = {} +117: @entities[name][:action] = name +118: @entities[name][:input] = {} +119: @entities[name][:output] = {} +120: @entities[name][:display] = :failed +121: @entities[name][:description] = input[:description] +122: end +123: +124: # if a block is passed it might be creating input methods, call it +125: # we set @current_entity so the input block can know what its talking +126: # to, this is probably an epic hack, need to improve. +127: @current_entity = name +128: block.call if block_given? +129: @current_entity = nil +130: end ++
+Sets the aggregate array for the given +action +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 70 +70: def aggregate(function, format = {:format => nil}) +71: DDL.validation_fail!(:PLMC28, "Formats supplied to aggregation functions should be a hash", :error) unless format.is_a?(Hash) +72: DDL.validation_fail!(:PLMC27, "Formats supplied to aggregation functions must have a :format key", :error) unless format.keys.include?(:format) +73: DDL.validation_fail!(:PLMC26, "Functions supplied to aggregate should be a hash", :error) unless function.is_a?(Hash) +74: +75: unless (function.keys.include?(:args)) && function[:args] +76: DDL.validation_fail!(:PLMC25, "aggregate method for action '%{action}' missing a function parameter", :error, :action => entities[@current_entity][:action]) +77: end +78: +79: entities[@current_entity][:aggregate] ||= [] +80: entities[@current_entity][:aggregate] << (format[:format].nil? ? function : function.merge(format)) +81: end ++
+Sets the display preference to either +:ok, :failed, :flatten or :always operates on action level +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 85 +85: def display(pref) +86: # defaults to old behavior, complain if its supplied and invalid +87: unless [:ok, :failed, :flatten, :always].include?(pref) +88: raise "Display preference #{pref} is not valid, should be :ok, :failed, :flatten or :always" +89: end +90: +91: action = @current_entity +92: @entities[action][:display] = pref +93: end ++
+ # File lib/mcollective/ddl/agentddl.rb, line 47 +47: def input(argument, properties) +48: raise "Input needs a :optional property" unless properties.include?(:optional) +49: +50: super +51: end ++
+Checks if a method name matches a aggregate plugin. This is used by method +missing so that we dont greedily assume that every method_missing call in an agent ddl has +hit a aggregate function. +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 146 +146: def is_function?(method_name) +147: PluginManager.find("aggregate").include?(method_name.to_s) +148: end ++
+If the method name matches a # aggregate function, we return the function +with args as a hash. This will only be active if the +@process_aggregate_functions is set to true which only happens in the summarize block +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 135 +135: def method_missing(name, *args, &block) +136: unless @process_aggregate_functions || is_function?(name) +137: raise NoMethodError, "undefined local variable or method `#{name}'", caller +138: end +139: +140: return {:function => name, :args => args} +141: end ++
+For a given action and arguments look +up the DDL interface to that action and if any arguments in the DDL have a :default value assign that to any input that does not have an argument in +the input arguments +
++This is intended to only be called on clients and not on servers as the +clients should never be able to publish non compliant requests and the +servers should really not tamper with incoming requests since doing so +might raise validation errors that were not raised on the client breaking +our fail-fast approach to input +validation +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 159 +159: def set_default_input_arguments(action, arguments) +160: input = action_interface(action)[:input] +161: +162: return unless input +163: +164: input.keys.each do |key| +165: if !arguments.include?(key) && !input[key][:default].nil? && !input[key][:optional] +166: Log.debug("Setting default value for input '%s' to '%s'" % [key, input[key][:default]]) +167: arguments[key] = input[key][:default] +168: end +169: end +170: end ++
+Calls the summarize block defined in +the ddl. Block will not be called if the ddl is getting processed on the +server side. This means that aggregate +plugins only have to be present on the client side. +
++The @process_aggregate_functions variable is used by the method_missing block to determine if it +should kick in, this way we very tightly control where we activate the method_missing behavior turning it into a +noop otherwise to maximise the chance of providing good user feedback +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 61 +61: def summarize(&block) +62: unless @config.mode == :server +63: @process_aggregate_functions = true +64: block.call +65: @process_aggregate_functions = nil +66: end +67: end ++
+Helper to use the DDL to figure out if the remote +call to an agent should be allowed based on action name and inputs. +
+ ++ # File lib/mcollective/ddl/agentddl.rb, line 174 +174: def validate_rpc_request(action, arguments) +175: # is the action known? +176: unless actions.include?(action) +177: DDL.validation_fail!(:PLMC29, "Attempted to call action %{action} for %{plugin} but it's not declared in the DDL", :debug, :action => action, :plugin => @pluginname) +178: end +179: +180: input = action_interface(action)[:input] || {} +181: +182: input.keys.each do |key| +183: unless input[key][:optional] +184: unless arguments.keys.include?(key) +185: DDL.validation_fail!(:PLMC30, "Action '%{action}' needs a '%{key}' argument", :debug, :action => action, :key => key) +186: end +187: end +188: +189: if arguments.keys.include?(key) +190: validate_input_argument(input, key, arguments[key]) +191: end +192: end +193: +194: true +195: end ++