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 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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