Class: MCollective::Application::Plugin

Inherits:
MCollective::Application show all
Defined in:
lib/mcollective/application/plugin.rb

Instance Method Summary collapse

Methods inherited from MCollective::Application

[], []=, #application_cli_arguments, #application_description, #application_failure, #application_options, application_options, #application_parse_options, #application_usage, #clioptions, #configuration, description, #disconnect, exclude_argument_sections, #halt, #halt_code, #help, intialize_application_options, option, #options, #rpcclient, #run, usage, #validate_cli_options, #validate_option

Methods included from RPC

const_missing, discovered, #empty_filter?, #printrpc, #printrpcstats, #rpcclient, #rpcoptions, stats

Instance Method Details

#doc_commandObject

Show application list and plugin help



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/mcollective/application/plugin.rb', line 226

def doc_command
  known_plugin_types = [["Agents", :agent], ["Aggregate", :aggregate],
                        ["Connectors", :connector], ["Data Queries", :data],
                        ["Discovery Methods", :discovery], ["Validator Plugins", :validator]]

  if configuration.include?(:target) && configuration[:target] != "."
    if configuration[:target] =~ /^(.+?)\/(.+)$/
      ddl = load_plugin_ddl($2.to_sym, $1)
    else
      found_plugin_type = nil

      known_plugin_types.each do |plugin_type|
        PluginManager.find(plugin_type[1], "ddl").each do |ddl|
          pluginname = ddl.gsub(/_#{plugin_type[1]}$/, "")
          if pluginname == configuration[:target]
            abort "Duplicate plugin name found, please specify a full path like agent/rpcutil" if found_plugin_type
            found_plugin_type = plugin_type[1]
          end
        end
      end

      abort "Could not find a plugin named '%s' in any supported plugin type" % configuration[:target] unless found_plugin_type
      ddl = load_plugin_ddl(configuration[:target], found_plugin_type)
    end

    if ddl
      puts ddl.help(configuration[:rpctemplate])
    else
      abort "Could not find a '%s' plugin named '%s'" % configuration[:target].split('/')
    end

  else
    puts "Please specify a plugin. Available plugins are:"
    puts

    load_errors = []

    known_plugin_types.each do |plugin_type|
      puts "%s:" % plugin_type[0]

      PluginManager.find(plugin_type[1], "ddl").each do |ddl|
        begin
          help = DDL.new(ddl, plugin_type[1])
          pluginname = ddl.gsub(/_#{plugin_type[1]}$/, "")
          puts "  %-25s %s" % [pluginname, help.meta[:description]]
        rescue => e
          load_errors << [plugin_type[1], ddl, e]
        end
      end

      puts
    end

    unless load_errors.empty?
      puts "Plugin Load Errors:"

      load_errors.each do |e|
        puts "  %-25s %s" % ["#{e[0]}/#{e[1]}", Util.colorize(:yellow, e[2])]
      end
    end
  end
end

#generate_commandObject

Generate a plugin skeleton



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/mcollective/application/plugin.rb', line 170

def generate_command
  raise "undefined plugin type. cannot generate plugin. valid types are 'agent' and 'data'" if configuration["target"] == '.'

  unless configuration[:pluginname]
    puts "No plugin name specified. Using 'new_plugin'"
    configuration[:pluginname] = "new_plugin"
  end

  load_plugin_config_values

  case configuration[:target].downcase
  when 'agent'
    Generators::AgentGenerator.new(configuration[:pluginname], configuration[:actions], configuration[:pluginname],
                                   configuration[:description], configuration[:author], configuration[:license],
                                   configuration[:version], configuration[:url], configuration[:timeout])
  when 'data'
    raise "data plugin must have at least one output" unless configuration[:outputs]
    Generators::DataGenerator.new(configuration[:pluginname], configuration[:outputs], configuration[:pluginname],
                                   configuration[:description], configuration[:author], configuration[:license],
                                   configuration[:version], configuration[:url], configuration[:timeout])
  else
    raise "invalid plugin type. cannot generate plugin '#{configuration[:target]}'"
  end
end

#identify_pluginObject

If plugintype is StandardDefinition, identify which of the special plugin types we are dealing with based on directory structure. To keep it simple we limit it to one type per target directory. Return the name of the type of plugin as a string

Raises:

  • (RuntimeError)


334
335
336
337
338
339
340
341
342
343
# File 'lib/mcollective/application/plugin.rb', line 334

def identify_plugin
  plugintype = Dir.glob(File.join(configuration[:target], "*")).select do |file|
    File.directory?(file) && file.match(/(connector|facts|registration|security|audit|pluginpackager|data|discovery|validator)/)
  end

  raise RuntimeError, "more than one plugin type detected in directory" if plugintype.size > 1
  raise RuntimeError, "no plugins detected in directory" if plugintype.size < 1

  File.basename(plugintype[0])
end

#info_commandObject

Display info about plugin



163
164
165
166
167
# File 'lib/mcollective/application/plugin.rb', line 163

def info_command
  plugin = prepare_plugin
  packager = PluginPackager["#{configuration[:format].capitalize}Packager"]
  packager.new(plugin).package_information
end

#load_plugin_config_valuesObject

Load preset metadata values from config if they are present This makes it possible to override metadata values in a local client config file.

Example : plugin.metadata.license = Apache 2



350
351
352
353
354
355
# File 'lib/mcollective/application/plugin.rb', line 350

def load_plugin_config_values
  config = Config.instance
  [:pluginname, :description, :author, :license, :version, :url, :timeout].each do |confoption|
    configuration[confoption] = config.pluginconf["metadata.#{confoption}"] unless configuration[confoption]
  end
end

#load_plugin_ddl(plugin, type) ⇒ Object

Agents are just called ‘agent’ but newer plugin types are called plugin_plugintype for example facter_facts etc so this will first try the old way then the new way.



213
214
215
216
217
218
219
220
221
222
223
# File 'lib/mcollective/application/plugin.rb', line 213

def load_plugin_ddl(plugin, type)
  [plugin, "#{plugin}_#{type}"].each do |p|
    ddl = DDL.new(p, type, false)
    if ddl.findddlfile(p, type)
      ddl.loadddlfile
      return ddl
    end
  end

  return nil
end

#mainObject



357
358
359
360
361
362
363
364
365
366
367
# File 'lib/mcollective/application/plugin.rb', line 357

def main
    abort "No action specified, please run 'mco help plugin' for help" unless configuration.include?(:action)

    cmd = "#{configuration[:action]}_command"

    if respond_to? cmd
      send cmd
    else
      abort "Invalid action #{configuration[:action]}, please run 'mco help plugin' for help."
    end
end

#package_commandObject

Package plugin



196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/mcollective/application/plugin.rb', line 196

def package_command
  if configuration[:sign] && Config.instance.pluginconf.include?("debian_packager.keyname")
    configuration[:sign] = Config.instance.pluginconf["debian_packager.keyname"]
    configuration[:sign] = "\"#{configuration[:sign]}\"" unless configuration[:sign].match(/\".*\"/)
  end

  plugin = prepare_plugin
  (configuration[:pluginpath] = configuration[:pluginpath] + "/") if (configuration[:pluginpath] && !configuration[:pluginpath].match(/^.*\/$/))
  packager = PluginPackager["#{configuration[:format].capitalize}Packager"]
  packager.new(plugin, configuration[:pluginpath], configuration[:sign],
               options[:verbose], configuration[:keep_artifacts],
               configuration[:module_template]).create_packages
end

#plugin_directory_exists?(plugin_type) ⇒ Boolean

Returns:

  • (Boolean)


313
314
315
# File 'lib/mcollective/application/plugin.rb', line 313

def plugin_directory_exists?(plugin_type)
  File.directory?(File.join(PluginPackager.get_plugin_path(configuration[:target]), plugin_type))
end

#post_option_parser(configuration) ⇒ Object

Handle alternative format that optparser can’t parse.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/mcollective/application/plugin.rb', line 136

def post_option_parser(configuration)
  if ARGV.length >= 1
    configuration[:action] = ARGV.delete_at(0)

    configuration[:target] = ARGV.delete_at(0) || "."

    if configuration[:action] == "generate"
      unless ARGV[0] && ARGV[0].match(/(actions|outputs)=(.+)/i)
        unless configuration[:pluginname]
          configuration[:pluginname] = ARGV.delete_at(0)
        else
          ARGV.delete_at(0)
        end
      end

      ARGV.each do |argument|
        if argument.match(/(actions|outputs)=(.+)/i)
          configuration[$1.downcase.to_sym]= $2.split(",")
        else
          raise "Could not parse --arg '#{argument}'"
        end
      end
    end
  end
end

#prepare_pluginObject

Creates the correct package plugin object.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/mcollective/application/plugin.rb', line 290

def prepare_plugin
  plugintype = set_plugin_type unless configuration[:plugintype]
  configuration[:format] = "ospackage" unless configuration[:format]
  PluginPackager.load_packagers
  plugin_class = PluginPackager[configuration[:plugintype]]

  if configuration[:dependency] && configuration[:dependency].size == 1
    configuration[:dependency] = configuration[:dependency][0].split(" ")
  elsif configuration[:dependency]
    configuration[:dependency].map!{|dep| {:name => dep, :version => nil}}
  end

  mcdependency = {:mcname => configuration[:mcname], :mcversion => configuration[:mcversion]}

  # Deprecation warning for --iteration
  if configuration[:iteration]
    puts 'Warning. The --iteration flag has been deprecated. Please use --revision instead.'
    configuration[:revision] = configuration[:iteration] unless configuration[:revision]
  end

  plugin_class.new(configuration, mcdependency, plugintype)
end

#set_plugin_typeObject

Identify plugin type if not provided.



318
319
320
321
322
323
324
325
326
327
328
# File 'lib/mcollective/application/plugin.rb', line 318

def set_plugin_type
  if plugin_directory_exists?("agent") || plugin_directory_exists?("application")
    configuration[:plugintype] = "AgentDefinition"
    return "Agent"
  elsif plugin_directory_exists?(plugintype = identify_plugin)
    configuration[:plugintype] = "StandardDefinition"
    return plugintype
  else
    raise RuntimeError, "target directory is not a valid mcollective plugin"
  end
end