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, DiscoveryDDL, ValidatorDDL

Constant Summary collapse

ACTIVATION_DEFAULT =
true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Base.



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

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)

rubocop:disable Lint/DuplicateMethods, Style/TrivialAccessors



64
65
66
# File 'lib/mcollective/ddl/base.rb', line 64

def usage
  @usage
end

Instance Method Details

#client_activated?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/mcollective/ddl/base.rb', line 108

def client_activated?
  ACTIVATION_DEFAULT
end

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



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/mcollective/ddl/base.rb', line 93

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

  @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

  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



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

def help(template=nil)
  template ||= template_for_plugintype
  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



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/mcollective/ddl/base.rb', line 157

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



83
84
85
86
87
88
89
90
91
# File 'lib/mcollective/ddl/base.rb', line 83

def loadddlfile
  raise("%s/%s is disabled, cannot load DDL file" % [@plugintype, @pluginname]) if @config.mode == :client && !client_activated?

  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



219
220
221
222
223
224
225
# File 'lib/mcollective/ddl/base.rb', line 219

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



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

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]}

  @entities[action][:output][argument][:type] = properties[:type] if properties[:type]
end

#requires(requirement) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/mcollective/ddl/base.rb', line 204

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

  valid_requirements = [:mcollective]

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

    @requirements[key] = requirement[key]
  end

  validate_requirements
end

#template_for_plugintypeObject

rubocop:enable Lint/DuplicateMethods, Style/TrivialAccessors



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/mcollective/ddl/base.rb', line 69

def template_for_plugintype
  case @plugintype
  when :agent
    "rpc-help.erb"
  else
    if File.exist?(Util.templatepath("#{@plugintype}-help.erb"))
      "#{@plugintype}-help.erb"
    else
      # Default help template gets loaded if plugintype-help does not exist.
      "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



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/mcollective/ddl/base.rb', line 131

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

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

#validate_requirementsObject



112
113
114
115
116
117
118
119
120
# File 'lib/mcollective/ddl/base.rb', line 112

def validate_requirements
  requirement = @requirements[:mcollective]

  if requirement && (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

  true
end