class MCollective::DDL::Base

The base class for all kinds of DDL files. DDL files when run gets parsed and builds up a hash of the basic primitive types, ideally restricted so it can be converted to JSON though today there are some Ruby Symbols in them which might be fixed laster on.

The Hash being built should be stored in @entities, the format is generally not prescribed but there's a definite feel to how DDL files look so study the agent and discovery ones to see how the structure applies to very different use cases.

For every plugin type you should have a single word name - that corresponds to the directory in the libdir where these plugins live. If you need anything above and beyond 'metadata' in your plugin DDL then add a PlugintypeDDL class here and add your specific behaviors to those.

Attributes

entities[R]
meta[R]
pluginname[R]
plugintype[R]
requirements[R]
usage[R]

Public Class Methods

new(plugin, plugintype=:agent, loadddl=true) click to toggle source
   # File lib/mcollective/ddl/base.rb
22 def initialize(plugin, plugintype=:agent, loadddl=true)
23   @entities = {}
24   @meta = {}
25   @usage = ""
26   @config = Config.instance
27   @pluginname = plugin
28   @plugintype = plugintype.to_sym
29   @requirements = {}
30 
31   loadddlfile if loadddl
32 end

Public Instance Methods

findddlfile(ddlname=nil, ddltype=nil) click to toggle source
   # File lib/mcollective/ddl/base.rb
87 def findddlfile(ddlname=nil, ddltype=nil)
88   ddlname = @pluginname unless ddlname
89   ddltype = @plugintype unless ddltype
90 
91   @config.libdir.each do |libdir|
92     ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
93     if File.exist?(ddlfile)
94       Log.debug("Found #{ddlname} ddl at #{ddlfile}")
95       return ddlfile
96     end
97   end
98   return false
99 end
help(template=nil) click to toggle source

Generates help using the template based on the data created with metadata and input.

If no template name is provided one will be chosen based on the plugin type. If the provided template path is not absolute then the template will be loaded either from the config dir and if that does not exist, default to /etc/mcollective

   # File lib/mcollective/ddl/base.rb
42 def help(template=nil)
43   template = template_for_plugintype unless template
44   template = Util.templatepath(template) unless Util.absolute_path?(template)
45 
46   template = File.read(template)
47   meta = @meta
48   entities = @entities
49 
50   unless template == "metadata-help.erb"
51     metadata_template = Util.templatepath("metadata-help.erb")
52     metadata_template = File.read(metadata_template)
53     metastring = ERB.new(metadata_template, 0, '%')
54     metastring = metastring.result(binding)
55   end
56 
57   erb = ERB.new(template, 0, '%')
58   erb.result(binding)
59 end
input(argument, properties) click to toggle source

Registers an input argument for a given action

See the documentation for action for how to use this

    # File lib/mcollective/ddl/base.rb
146 def input(argument, properties)
147   raise "Cannot figure out what entity input #{argument} belongs to" unless @current_entity
148 
149   entity = @current_entity
150 
151   [:prompt, :description, :type].each do |arg|
152     raise "Input needs a :#{arg} property" unless properties.include?(arg)
153   end
154 
155   @entities[entity][:input][argument] = {:prompt => properties[:prompt],
156                                          :description => properties[:description],
157                                          :type => properties[:type],
158                                          :default => properties[:default],
159                                          :optional => properties[:optional]}
160 
161   case properties[:type]
162     when :string
163       raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
164       raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
165 
166       @entities[entity][:input][argument][:validation] = properties[:validation]
167       @entities[entity][:input][argument][:maxlength] = properties[:maxlength]
168 
169     when :list
170       raise "Input type :list needs a :list argument" unless properties.include?(:list)
171 
172       @entities[entity][:input][argument][:list] = properties[:list]
173   end
174 end
loadddlfile() click to toggle source
   # File lib/mcollective/ddl/base.rb
79 def loadddlfile
80   if ddlfile = findddlfile
81     instance_eval(File.read(ddlfile), ddlfile, 1)
82   else
83     raise("Can't find DDL for #{@plugintype} plugin '#{@pluginname}'")
84   end
85 end
metadata(meta) click to toggle source

Registers meta data for the introspection hash

    # File lib/mcollective/ddl/base.rb
208 def metadata(meta)
209   [:name, :description, :author, :license, :version, :url, :timeout].each do |arg|
210     raise "Metadata needs a :#{arg} property" unless meta.include?(arg)
211   end
212 
213   @meta = meta
214 end
output(argument, properties) click to toggle source

Registers an output argument for a given action

See the documentation for action for how to use this

    # File lib/mcollective/ddl/base.rb
179 def output(argument, properties)
180   raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity
181   raise "Output #{argument} needs a description argument" unless properties.include?(:description)
182   raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as)
183 
184   action = @current_entity
185 
186   @entities[action][:output][argument] = {:description => properties[:description],
187                                           :display_as  => properties[:display_as],
188                                           :default     => properties[:default]}
189 end
requires(requirement) click to toggle source
    # File lib/mcollective/ddl/base.rb
191 def requires(requirement)
192   raise "Requirement should be a hash in the form :item => 'requirement'" unless requirement.is_a?(Hash)
193 
194   valid_requirements = [:mcollective]
195 
196   requirement.keys.each do |key|
197     unless valid_requirements.include?(key)
198       raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")]
199     end
200 
201     @requirements[key] = requirement[key]
202   end
203 
204   validate_requirements
205 end
template_for_plugintype() click to toggle source
   # File lib/mcollective/ddl/base.rb
65 def template_for_plugintype
66   case @plugintype
67   when :agent
68     return "rpc-help.erb"
69   else
70     if File.exists?(Util.templatepath("#{@plugintype}-help.erb"))
71       return "#{@plugintype}-help.erb"
72     else
73       # Default help template gets loaded if plugintype-help does not exist.
74       return "metadata-help.erb"
75     end
76   end
77 end
validate_input_argument(input, key, argument) click to toggle source

validate strings, lists and booleans, we'll add more types of validators when all the use cases are clear

only does validation for arguments actually given, since some might be optional. We validate the presense of the argument earlier so this is a safe assumption, just to skip them.

:string can have maxlength and regex. A maxlength of 0 will bypasss checks :list has a array of valid values

    # File lib/mcollective/ddl/base.rb
120 def validate_input_argument(input, key, argument)
121   Validator.load_validators
122 
123   case input[key][:type]
124   when :string
125     Validator.validate(argument, :string)
126 
127     Validator.length(argument, input[key][:maxlength].to_i)
128 
129     Validator.validate(argument, input[key][:validation])
130 
131   when :list
132     Validator.validate(argument, input[key][:list])
133 
134   else
135     Validator.validate(argument, input[key][:type])
136   end
137 
138   return true
139 rescue => e
140   raise DDLValidationError, "Cannot validate input %s: %s" % [key, e.to_s]
141 end
validate_requirements() click to toggle source
    # File lib/mcollective/ddl/base.rb
101 def validate_requirements
102   if requirement = @requirements[:mcollective]
103     if Util.versioncmp(Util.mcollective_version, requirement) < 0
104       raise DDLValidationError, "%s plugin '%s' requires MCollective version %s or newer" % [@plugintype.to_s.capitalize, @pluginname, requirement]
105     end
106   end
107 
108   true
109 end