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
Public Class Methods
# 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
# 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
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
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
# 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
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
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
# 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
# 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 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
# 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