Class: MCollective::DDL::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/mcollective/ddl/base.rb

Overview

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.

Direct Known Subclasses

AgentDDL, DataDDL, DiscoveryDDL, ValidatorDDL

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(plugin, plugintype = :agent, loadddl = true) ⇒ Base

Returns a new instance of Base.



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/mcollective/ddl/base.rb', line 22

def initialize(plugin, plugintype=:agent, loadddl=true)
  @entities = {}
  @meta = {}
  @usage = ""
  @config = Config.instance
  @pluginname = plugin
  @plugintype = plugintype.to_sym
  @requirements = {}

  loadddlfile if loadddl
end

Instance Attribute Details

#entitiesObject (readonly)

Returns the value of attribute entities.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def entities
  @entities
end

#metaObject (readonly)

Returns the value of attribute meta.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def meta
  @meta
end

#pluginnameObject (readonly)

Returns the value of attribute pluginname.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def pluginname
  @pluginname
end

#plugintypeObject (readonly)

Returns the value of attribute plugintype.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def plugintype
  @plugintype
end

#requirementsObject (readonly)

Returns the value of attribute requirements.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def requirements
  @requirements
end

#usage(usage_text) ⇒ Object (readonly)

Returns the value of attribute usage.



20
21
22
# File 'lib/mcollective/ddl/base.rb', line 20

def usage
  @usage
end

Instance Method Details

#findddlfile(ddlname = nil, ddltype = nil) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/mcollective/ddl/base.rb', line 87

def findddlfile(ddlname=nil, ddltype=nil)
  ddlname = @pluginname unless ddlname
  ddltype = @plugintype unless ddltype

  @config.libdir.each do |libdir|
    ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
    if File.exist?(ddlfile)
      Log.debug("Found #{ddlname} ddl at #{ddlfile}")
      return ddlfile
    end
  end
  return false
end

#help(template = nil) ⇒ Object

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



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/mcollective/ddl/base.rb', line 42

def help(template=nil)
  template = template_for_plugintype unless template
  template = Util.templatepath(template) unless Util.absolute_path?(template)

  template = File.read(template)
  meta = @meta
  entities = @entities

  unless template == "metadata-help.erb"
     = Util.templatepath("metadata-help.erb")
     = File.read()
    metastring = ERB.new(, 0, '%')
    metastring = metastring.result(binding)
  end

  erb = ERB.new(template, 0, '%')
  erb.result(binding)
end

#input(argument, properties) ⇒ Object

Registers an input argument for a given action

See the documentation for action for how to use this



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/mcollective/ddl/base.rb', line 146

def input(argument, properties)
  raise "Cannot figure out what entity input #{argument} belongs to" unless @current_entity

  entity = @current_entity

  [:prompt, :description, :type].each do |arg|
    raise "Input needs a :#{arg} property" unless properties.include?(arg)
  end

  @entities[entity][:input][argument] = {:prompt => properties[:prompt],
                                         :description => properties[:description],
                                         :type => properties[:type],
                                         :default => properties[:default],
                                         :optional => properties[:optional]}

  case properties[:type]
    when :string
      raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
      raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)

      @entities[entity][:input][argument][:validation] = properties[:validation]
      @entities[entity][:input][argument][:maxlength] = properties[:maxlength]

    when :list
      raise "Input type :list needs a :list argument" unless properties.include?(:list)

      @entities[entity][:input][argument][:list] = properties[:list]
  end
end

#loadddlfileObject



79
80
81
82
83
84
85
# File 'lib/mcollective/ddl/base.rb', line 79

def loadddlfile
  if ddlfile = findddlfile
    instance_eval(File.read(ddlfile), ddlfile, 1)
  else
    raise("Can't find DDL for #{@plugintype} plugin '#{@pluginname}'")
  end
end

#metadata(meta) ⇒ Object

Registers meta data for the introspection hash



208
209
210
211
212
213
214
# File 'lib/mcollective/ddl/base.rb', line 208

def (meta)
  [:name, :description, :author, :license, :version, :url, :timeout].each do |arg|
    raise "Metadata needs a :#{arg} property" unless meta.include?(arg)
  end

  @meta = meta
end

#output(argument, properties) ⇒ Object

Registers an output argument for a given action

See the documentation for action for how to use this



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mcollective/ddl/base.rb', line 179

def output(argument, properties)
  raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity
  raise "Output #{argument} needs a description argument" unless properties.include?(:description)
  raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as)

  action = @current_entity

  @entities[action][:output][argument] = {:description => properties[:description],
                                          :display_as  => properties[:display_as],
                                          :default     => properties[:default]}
end

#requires(requirement) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/mcollective/ddl/base.rb', line 191

def requires(requirement)
  raise "Requirement should be a hash in the form :item => 'requirement'" unless requirement.is_a?(Hash)

  valid_requirements = [:mcollective]

  requirement.keys.each do |key|
    unless valid_requirements.include?(key)
      raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")]
    end

    @requirements[key] = requirement[key]
  end

  validate_requirements
end

#template_for_plugintypeObject



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/mcollective/ddl/base.rb', line 65

def template_for_plugintype
  case @plugintype
  when :agent
    return "rpc-help.erb"
  else
    if File.exists?(Util.templatepath("#{@plugintype}-help.erb"))
      return "#{@plugintype}-help.erb"
    else
      # Default help template gets loaded if plugintype-help does not exist.
      return "metadata-help.erb"
    end
  end
end

#validate_input_argument(input, key, argument) ⇒ Object

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



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/mcollective/ddl/base.rb', line 120

def validate_input_argument(input, key, argument)
  Validator.load_validators

  case input[key][:type]
  when :string
    Validator.validate(argument, :string)

    Validator.length(argument, input[key][:maxlength].to_i)

    Validator.validate(argument, input[key][:validation])

  when :list
    Validator.validate(argument, input[key][:list])

  else
    Validator.validate(argument, input[key][:type])
  end

  return true
rescue => e
  raise DDLValidationError, "Cannot validate input %s: %s" % [key, e.to_s]
end

#validate_requirementsObject



101
102
103
104
105
106
107
108
109
# File 'lib/mcollective/ddl/base.rb', line 101

def validate_requirements
  if requirement = @requirements[:mcollective]
    if Util.versioncmp(Util.mcollective_version, requirement) < 0
      raise DDLValidationError, "%s plugin '%s' requires MCollective version %s or newer" % [@plugintype.to_s.capitalize, @pluginname, requirement]
    end
  end

  true
end