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.
entities | [R] | |
meta | [R] | |
pluginname | [R] | |
plugintype | [R] | |
requirements | [R] | |
usage | [R] |
# 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
# 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
# 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
# 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: :default => properties[:default], 163: :optional => properties[:optional]} 164: 165: case properties[:type] 166: when :string 167: raise "Input type :string needs a :validation argument" unless properties.include?(:validation) 168: raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength) 169: 170: @entities[entity][:input][argument][:validation] = properties[:validation] 171: @entities[entity][:input][argument][:maxlength] = properties[:maxlength] 172: 173: when :list 174: raise "Input type :list needs a :list argument" unless properties.include?(:list) 175: 176: @entities[entity][:input][argument][:list] = properties[:list] 177: end 178: end
# 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
# File lib/mcollective/ddl/base.rb, line 212 212: def metadata(meta) 213: [:name, :description, :author, :license, :version, :url, :timeout].each do |arg| 214: raise "Metadata needs a :#{arg} property" unless meta.include?(arg) 215: end 216: 217: @meta = meta 218: 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, line 183 183: def output(argument, properties) 184: raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity 185: raise "Output #{argument} needs a description argument" unless properties.include?(:description) 186: raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as) 187: 188: action = @current_entity 189: 190: @entities[action][:output][argument] = {:description => properties[:description], 191: :display_as => properties[:display_as], 192: :default => properties[:default]} 193: end
# File lib/mcollective/ddl/base.rb, line 195 195: def requires(requirement) 196: raise "Requirement should be a hash in the form :item => 'requirement'" unless requirement.is_a?(Hash) 197: 198: valid_requirements = [:mcollective] 199: 200: requirement.keys.each do |key| 201: unless valid_requirements.include?(key) 202: raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")] 203: end 204: 205: @requirements[key] = requirement[key] 206: end 207: 208: validate_requirements 209: end
# 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
# 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
# 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: %s" % [key, e.to_s] 145: end
# 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