» 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:
command "foo" do
require_relative "command"
Command
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:
command("foo", primary: false) do
require_relative "command"
Command
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:
class Command < Vagrant.plugin(2, :command)
def execute
puts "Hello!"
0
end
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:
options = {}
options[:force] = false
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant destroy [vm-name]"
o.separator ""
o.on("-f", "--force", "Destroy without confirmation.") do |f|
options[:force] = f
end
end
# Parse the options
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:
with_target_vms(argv, reverse: true) do |machine|
machine.action(:destroy)
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.