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

Attributes

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

Public Class methods

[Source]

    # File lib/mcollective/ddl/base.rb, line 22
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

[Source]

    # File lib/mcollective/ddl/base.rb, line 86
86:       def findddlfile(ddlname=nil, ddltype=nil)
87:         ddlname = @pluginname unless ddlname
88:         ddltype = @plugintype unless ddltype
89: 
90:         @config.libdir.each do |libdir|
91:           ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
92:           if File.exist?(ddlfile)
93:             Log.debug("Found #{ddlname} ddl at #{ddlfile}")
94:             return ddlfile
95:           end
96:         end
97:         return false
98:       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 41
41:       def help(template=nil)
42:         template = template_for_plugintype unless template
43:         template = File.join(@config.helptemplatedir, template) unless template.start_with?(File::SEPARATOR)
44: 
45:         template = File.read(template)
46:         meta = @meta
47:         entities = @entities
48: 
49:         unless template == "metadata-help.erb"
50:           metadata_template = File.join(@config.helptemplatedir, "metadata-help.erb")
51:           metadata_template = File.read(metadata_template)
52:           metastring = ERB.new(metadata_template, 0, '%')
53:           metastring = metastring.result(binding)
54:         end
55: 
56:         erb = ERB.new(template, 0, '%')
57:         erb.result(binding)
58:       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 150
150:       def input(argument, properties)
151:         raise "Cannot figure out what entity input #{argument} belongs to" unless @current_entity
152: 
153:         entity = @current_entity
154: 
155:         [:prompt, :description, :type].each do |arg|
156:           raise "Input needs a :#{arg} property" unless properties.include?(arg)
157:         end
158: 
159:         @entities[entity][:input][argument] = {:prompt => properties[:prompt],
160:                                                :description => properties[:description],
161:                                                :type => properties[:type],
162:                                                :optional => properties[:optional]}
163: 
164:         case properties[:type]
165:           when :string
166:             raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
167:             raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
168: 
169:             @entities[entity][:input][argument][:validation] = properties[:validation]
170:             @entities[entity][:input][argument][:maxlength] = properties[:maxlength]
171: 
172:           when :list
173:             raise "Input type :list needs a :list argument" unless properties.include?(:list)
174: 
175:             @entities[entity][:input][argument][:list] = properties[:list]
176:         end
177:       end

[Source]

    # File lib/mcollective/ddl/base.rb, line 78
78:       def loadddlfile
79:         if ddlfile = findddlfile
80:           instance_eval(File.read(ddlfile), ddlfile, 1)
81:         else
82:           raise("Can't find DDL for #{@plugintype} plugin '#{@pluginname}'")
83:         end
84:       end

Registers meta data for the introspection hash

[Source]

     # File lib/mcollective/ddl/base.rb, line 211
211:       def metadata(meta)
212:         [:name, :description, :author, :license, :version, :url, :timeout].each do |arg|
213:           raise "Metadata needs a :#{arg} property" unless meta.include?(arg)
214:         end
215: 
216:         @meta = meta
217:       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 182
182:       def output(argument, properties)
183:         raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity
184:         raise "Output #{argument} needs a description argument" unless properties.include?(:description)
185:         raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as)
186: 
187:         action = @current_entity
188: 
189:         @entities[action][:output][argument] = {:description => properties[:description],
190:                                                 :display_as  => properties[:display_as],
191:                                                 :default     => properties[:default]}
192:       end

[Source]

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

[Source]

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

[Source]

    # File lib/mcollective/ddl/base.rb, line 60
60:       def usage(usage_text)
61:         @usage = usage_text
62:       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 124
124:       def validate_input_argument(input, key, argument)
125:         Validator.load_validators
126: 
127:         case input[key][:type]
128:         when :string
129:           Validator.validate(argument, :string)
130: 
131:           Validator.length(argument, input[key][:maxlength].to_i)
132: 
133:           Validator.validate(argument, input[key][:validation])
134: 
135:         when :list
136:           Validator.validate(argument, input[key][:list])
137: 
138:         else
139:           Validator.validate(argument, input[key][:type])
140:         end
141: 
142:         return true
143:       rescue => e
144:         raise DDLValidationError, "Cannot validate input: %s" % e.to_s
145:       end

[Source]

     # File lib/mcollective/ddl/base.rb, line 100
100:       def validate_requirements
101:         if requirement = @requirements[:mcollective]
102:           if Util.mcollective_version == "@DEVELOPMENT_VERSION@"
103:             Log.warn("DDL requirements validation being skipped in development")
104:             return true
105:           end
106: 
107:           if Util.versioncmp(Util.mcollective_version, requirement) < 0
108:             raise DDLValidationError, "%s plugin '%s' requires MCollective version %s or newer" % [@plugintype.to_s.capitalize, @pluginname, requirement]
109:           end
110:         end
111: 
112:         true
113:       end

[Validate]