X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;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 + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassMCollective::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 +

+ +
+ + +
+ +
+

Methods

+ + +
+ +
+ + + + +
+ + + + + + + + + +
+

Public Class methods

+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +

Public Instance methods

+ +
+ + + + +
+

+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
+
+

[Source]

+
+
+     # 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
+
+
+
+
+ +
+ + + + +
+

+Returns the interface for a specific action +

+

[Source]

+
+
+     # File lib/mcollective/ddl/agentddl.rb, line 198
+198:       def action_interface(name)
+199:         @entities[name] || {}
+200:       end
+
+
+
+
+ +
+ + + + +
+

+Returns an array of actions this agent +support +

+

[Source]

+
+
+     # File lib/mcollective/ddl/agentddl.rb, line 203
+203:       def actions
+204:         @entities.keys
+205:       end
+
+
+
+
+ +
+ + + + +
+

+Sets the aggregate array for the given +action +

+

[Source]

+
+
+    # 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 +

+

[Source]

+
+
+    # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # 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. +

+

[Source]

+
+
+     # 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 +

+

[Source]

+
+
+     # 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 +

+

[Source]

+
+
+     # 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 +

+

[Source]

+
+
+    # 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. +

+

[Source]

+
+
+     # 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
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file