Class MCollective::DDL::Base
In: lib/mcollective/ddl/base.rb
Parent: Object

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.

Methods

Included Modules

Translatable

Attributes

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

Public Class methods

[Source]

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

Public Instance methods

[Source]

     # File lib/mcollective/ddl/base.rb, line 88
 88:       def findddlfile(ddlname=nil, ddltype=nil)
 89:         ddlname = @pluginname unless ddlname
 90:         ddltype = @plugintype unless ddltype
 91: 
 92:         @config.libdir.each do |libdir|
 93:           ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
 94:           if File.exist?(ddlfile)
 95:             log_code(:PLMC18, "Found %{ddlname} ddl at %{ddlfile}", :debug, :ddlname => ddlname, :ddlfile => ddlfile)
 96:             return ddlfile
 97:           end
 98:         end
 99:         return false
100:       end

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 relative to helptemplatedir configuration parameter

[Source]

    # File lib/mcollective/ddl/base.rb, line 43
43:       def help(template=nil)
44:         template = template_for_plugintype unless template
45:         template = File.join(@config.helptemplatedir, template) unless template.start_with?(File::SEPARATOR)
46: 
47:         template = File.read(template)
48:         meta = @meta
49:         entities = @entities
50: 
51:         unless template == "metadata-help.erb"
52:           metadata_template = File.join(@config.helptemplatedir, "metadata-help.erb")
53:           metadata_template = File.read(metadata_template)
54:           metastring = ERB.new(metadata_template, 0, '%')
55:           metastring = metastring.result(binding)
56:         end
57: 
58:         erb = ERB.new(template, 0, '%')
59:         erb.result(binding)
60:       end

Registers an input argument for a given action

See the documentation for action for how to use this

[Source]

     # File lib/mcollective/ddl/base.rb, line 152
152:       def input(argument, properties)
153:         raise_code(:PLMC22, "Cannot determine what entity input '%{entity}' belongs to", :error, :entity => @current_entity) unless @current_entity
154: 
155:         entity = @current_entity
156: 
157:         [:prompt, :description, :type].each do |arg|
158:           raise_code(:PLMC23, "Input needs a :%{property} property", :debug, :property => arg) unless properties.include?(arg)
159:         end
160: 
161:         @entities[entity][:input][argument] = {:prompt => properties[:prompt],
162:                                                :description => properties[:description],
163:                                                :type => properties[:type],
164:                                                :default => properties[:default],
165:                                                :optional => properties[:optional]}
166: 
167:         case properties[:type]
168:           when :string
169:             raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
170:             raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
171: 
172:             @entities[entity][:input][argument][:validation] = properties[:validation]
173:             @entities[entity][:input][argument][:maxlength] = properties[:maxlength]
174: 
175:           when :list
176:             raise "Input type :list needs a :list argument" unless properties.include?(:list)
177: 
178:             @entities[entity][:input][argument][:list] = properties[:list]
179:         end
180:       end

[Source]

    # File lib/mcollective/ddl/base.rb, line 80
80:       def loadddlfile
81:         if ddlfile = findddlfile
82:           instance_eval(File.read(ddlfile), ddlfile, 1)
83:         else
84:           raise_code(:PLMC18, "Can't find DDL for %{type} plugin '%{name}'", :debug, :type => @plugintype, :name => @pluginname)
85:         end
86:       end

Registers meta data for the introspection hash

[Source]

     # File lib/mcollective/ddl/base.rb, line 214
214:       def metadata(meta)
215:         [:name, :description, :author, :license, :version, :url, :timeout].each do |arg|
216:           raise "Metadata needs a :#{arg} property" unless meta.include?(arg)
217:         end
218: 
219:         @meta = meta
220:       end

Registers an output argument for a given action

See the documentation for action for how to use this

[Source]

     # File lib/mcollective/ddl/base.rb, line 185
185:       def output(argument, properties)
186:         raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity
187:         raise "Output #{argument} needs a description argument" unless properties.include?(:description)
188:         raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as)
189: 
190:         action = @current_entity
191: 
192:         @entities[action][:output][argument] = {:description => properties[:description],
193:                                                 :display_as  => properties[:display_as],
194:                                                 :default     => properties[:default]}
195:       end

[Source]

     # File lib/mcollective/ddl/base.rb, line 197
197:       def requires(requirement)
198:         raise "Requirement should be a hash in the form :item => 'requirement'" unless requirement.is_a?(Hash)
199: 
200:         valid_requirements = [:mcollective]
201: 
202:         requirement.keys.each do |key|
203:           unless valid_requirements.include?(key)
204:             raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")]
205:           end
206: 
207:           @requirements[key] = requirement[key]
208:         end
209: 
210:         validate_requirements
211:       end

[Source]

    # File lib/mcollective/ddl/base.rb, line 66
66:       def template_for_plugintype
67:         case @plugintype
68:         when :agent
69:           return "rpc-help.erb"
70:         else
71:           if File.exists?(File.join(@config.helptemplatedir,"#{@plugintype}-help.erb"))
72:             return "#{@plugintype}-help.erb"
73:           else
74:             # Default help template gets loaded if plugintype-help does not exist.
75:             return "metadata-help.erb"
76:           end
77:         end
78:       end

[Source]

    # File lib/mcollective/ddl/base.rb, line 62
62:       def usage(usage_text)
63:         @usage = usage_text
64:       end

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

[Source]

     # File lib/mcollective/ddl/base.rb, line 126
126:       def validate_input_argument(input, key, argument)
127:         Validator.load_validators
128: 
129:         case input[key][:type]
130:         when :string
131:           Validator.validate(argument, :string)
132: 
133:           Validator.length(argument, input[key][:maxlength].to_i)
134: 
135:           Validator.validate(argument, input[key][:validation])
136: 
137:         when :list
138:           Validator.validate(argument, input[key][:list])
139: 
140:         else
141:           Validator.validate(argument, input[key][:type])
142:         end
143: 
144:         return true
145:       rescue => e
146:         DDL.validation_fail!(:PLMC21, "Cannot validate input '%{input}': %{error}", :debug, :input => key, :error => e.to_s)
147:       end

[Source]

     # File lib/mcollective/ddl/base.rb, line 102
102:       def validate_requirements
103:         if requirement = @requirements[:mcollective]
104:           if Util.mcollective_version == "@DEVELOPMENT_VERSION@"
105:             log_code(:PLMC19, "DDL requirements validation being skipped in development", :warn)
106:             return true
107:           end
108: 
109:           if Util.versioncmp(Util.mcollective_version, requirement) < 0
110:             DDL.validation_fail!(:PLMC20, "%{type} plugin '%{name}' requires MCollective version %{requirement} or newer", :debug, :type => @plugintype.to_s.capitalize, :name => @pluginname, :requirement => requirement)
111:           end
112:         end
113: 
114:         true
115:       end

[Validate]