» Plugin Development: Commands

This page documents how to add new commands to Vagrant, invocablevia vagrant YOUR-COMMAND. Prior to reading this, you should be familiarwith the plugin development basics.

Warning: Advanced Topic! Developing plugins is anadvanced topic that only experienced Vagrant users who are reasonablycomfortable with Ruby should approach.

» Definition Component

Within the context of a plugin definition, new commands can be definedlike so:

  1. command "foo" do
  2. require_relative "command"
  3. Command
  4. end

Commands are defined with the command method, which takes as an argumentthe name of the command, in this case "foo." This means the command will beinvocable via vagrant foo. Then the block argument returns a class thatimplements the Vagrant.plugin(2, "command") interface.

You can also define non-primary commands. These commands do not showup in the vagrant -h output. They only show up if the user explicitlydoes a vagrant list-commands which shows the full listing of availablecommands. This is useful for highly specific commands or plugins that abeginner to Vagrant would not be using anyways. Vagrant itself uses non-primarycommands to expose some internal functions, as well.

To define a non-primary command:

  1. command("foo", primary: false) do
  2. require_relative "command"
  3. Command
  4. end

» Implementation

Implementations of commands should subclass Vagrant.plugin(2, :command),which is a Vagrant method that will return the proper superclass fora version 2 command. The implementation itself is quite simple, since theclass needs to only implement a single method: execute. Example:

  1. class Command < Vagrant.plugin(2, :command)
  2. def execute
  3. puts "Hello!"
  4. 0
  5. end
  6. end

The execute method is called when the command is invoked, and it shouldreturn the exit status (0 for success, anything else for error).

This is a command at its simplest form. Of course, the command superclassgives you access to the Vagrant environment and provides some helpers todo common tasks such as command line parsing.

» Parsing Command-Line Options

The parse_options method is available which will parse the command linefor you. It takes an OptionParseras an argument, and adds some common elements to it such as the —help flag,automatically showing help if requested. View the API docs directly for moreinformation.

This is recommended over raw parsing/manipulation of command line flags.The following is an example of parsing command line flags pulled directlyfrom the built-in Vagrant destroy command:

  1. options = {}
  2. options[:force] = false
  3. opts = OptionParser.new do |o|
  4. o.banner = "Usage: vagrant destroy [vm-name]"
  5. o.separator ""
  6. o.on("-f", "--force", "Destroy without confirmation.") do |f|
  7. options[:force] = f
  8. end
  9. end
  10. # Parse the options
  11. argv = parse_options(opts)

» Using Vagrant Machines

The with_target_vms method is a helper that helps you interact withthe machines that Vagrant manages in a standard Vagrant way. This methodautomatically does the right thing in the case of multi-machine environments,handling target machines on the command line (vagrant foo my-vm), etc.If you need to do any manipulation of a Vagrant machine, including SSHaccess, this helper should be used.

An example of using the helper, again pulled directly from the built-indestroy command:

  1. with_target_vms(argv, reverse: true) do |machine|
  2. machine.action(:destroy)
  3. end

In this case, it asks for the machines in reverse order and calls thedestroy action on each of them. If a user says vagrant destroy foo, thenthe helper automatically only yields the foo machine. If no parameteris given and it is a multi-machine environment, every machine in the environmentis yielded, and so on. It just does the right thing.

» Using the Raw Vagrant Environment

The raw loaded Vagrant::Environment object is available with the'@env' instance variable.