Move command base class to a plugin component

This commit is contained in:
Mitchell Hashimoto 2012-06-26 16:18:02 -07:00
parent 55528e051c
commit b23dda54b8
26 changed files with 196 additions and 193 deletions

View File

@ -86,8 +86,9 @@ module Vagrant
# These are the various plugin versions and their components in # These are the various plugin versions and their components in
# a lazy loaded Hash-like structure. # a lazy loaded Hash-like structure.
c = PLUGIN_COMPONENTS = Registry.new c = PLUGIN_COMPONENTS = Registry.new
c.register(:"1") { Plugin::V1::Plugin } c.register(:"1") { Plugin::V1::Plugin }
c.register([:"1", :config]) { Plugin::V1::Config } c.register([:"1", :command]) { Plugin::V1::Command }
c.register([:"1", :config]) { Plugin::V1::Config }
c.register([:"1", :provisioner]) { Plugin::V1::Provisioner } c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
# Returns a `Vagrant::Registry` object that contains all the built-in # Returns a `Vagrant::Registry` object that contains all the built-in

View File

@ -3,7 +3,7 @@ require 'optparse'
module Vagrant module Vagrant
# Manages the command line interface to Vagrant. # Manages the command line interface to Vagrant.
class CLI < Command::Base class CLI < Vagrant.plugin("1", :command)
def initialize(argv, env) def initialize(argv, env)
super super

View File

@ -1,169 +0,0 @@
require 'log4r'
require "vagrant/util/safe_puts"
module Vagrant
module Command
# Base class for any CLI commands.
#
# This class provides documentation on the interface as well as helper
# functions that a command has.
class Base
include Util::SafePuts
def initialize(argv, env)
@argv = argv
@env = env
@logger = Log4r::Logger.new("vagrant::command::#{self.class.to_s.downcase}")
end
# This is what is called on the class to actually execute it. Any
# subclasses should implement this method and do any option parsing
# and validation here.
def execute; end
protected
# Parses the options given an OptionParser instance.
#
# This is a convenience method that properly handles duping the
# originally argv array so that it is not destroyed.
#
# This method will also automatically detect "-h" and "--help"
# and print help. And if any invalid options are detected, the help
# will be printed, as well.
#
# If this method returns `nil`, then you should assume that help
# was printed and parsing failed.
def parse_options(opts=nil)
# Creating a shallow copy of the arguments so the OptionParser
# doesn't destroy the originals.
argv = @argv.dup
# Default opts to a blank optionparser if none is given
opts ||= OptionParser.new
# Add the help option, which must be on every command.
opts.on_tail("-h", "--help", "Print this help") do
safe_puts(opts.help)
return nil
end
opts.parse!(argv)
return argv
rescue OptionParser::InvalidOption
raise Errors::CLIInvalidOptions, :help => opts.help.chomp
end
# Yields a VM for each target VM for the command.
#
# This is a convenience method for easily implementing methods that
# take a target VM (in the case of multi-VM) or every VM if no
# specific VM name is specified.
#
# @param [String] name The name of the VM. Nil if every VM.
# @param [Boolean] single_target If true, then an exception will be
# raised if more than one target is found.
def with_target_vms(names=nil, options=nil)
# Using VMs requires a Vagrant environment to be properly setup
raise Errors::NoEnvironmentError if !@env.root_path
# Setup the options hash
options ||= {}
# Require that names be an array
names ||= []
names = [names] if !names.is_a?(Array)
# First determine the proper array of VMs.
vms = []
if names.length > 0
names.each do |name|
if pattern = name[/^\/(.+?)\/$/, 1]
# This is a regular expression name, so we convert to a regular
# expression and allow that sort of matching.
regex = Regexp.new(pattern)
@env.vms.each do |name, vm|
vms << vm if name =~ regex
end
raise Errors::VMNoMatchError if vms.empty?
else
# String name, just look for a specific VM
vms << @env.vms[name.to_sym]
raise Errors::VMNotFoundError, :name => name if !vms[0]
end
end
else
vms = @env.vms_ordered
end
# Make sure we're only working with one VM if single target
if options[:single_target] && vms.length != 1
vm = @env.primary_vm
raise Errors::MultiVMTargetRequired if !vm
vms = [vm]
end
# If we asked for reversed ordering, then reverse it
vms.reverse! if options[:reverse]
# Go through each VM and yield it!
vms.each do |old_vm|
# We get a new VM from the environment here to avoid potentially
# stale VMs (if there was a config reload on the environment
# or something).
vm = @env.vms[old_vm.name]
yield vm
end
end
# This method will split the argv given into three parts: the
# flags to this command, the subcommand, and the flags to the
# subcommand. For example:
#
# -v status -h -v
#
# The above would yield 3 parts:
#
# ["-v"]
# "status"
# ["-h", "-v"]
#
# These parts are useful because the first is a list of arguments
# given to the current command, the second is a subcommand, and the
# third are the commands given to the subcommand.
#
# @return [Array] The three parts.
def split_main_and_subcommand(argv)
# Initialize return variables
main_args = nil
sub_command = nil
sub_args = []
# We split the arguments into two: One set containing any
# flags before a word, and then the rest. The rest are what
# get actually sent on to the subcommand.
argv.each_index do |i|
if !argv[i].start_with?("-")
# We found the beginning of the sub command. Split the
# args up.
main_args = argv[0, i]
sub_command = argv[i]
sub_args = argv[i + 1, argv.length - i + 1]
# Break so we don't find the next non flag and shift our
# main args.
break
end
end
# Handle the case that argv was empty or didn't contain any subcommand
main_args = argv.dup if main_args.nil?
return [main_args, sub_command, sub_args]
end
end
end
end

View File

@ -4,7 +4,7 @@ module Vagrant
module Easy module Easy
# Base class for all easy commands. This contains the basic code # Base class for all easy commands. This contains the basic code
# that knows how to run the easy commands. # that knows how to run the easy commands.
class CommandBase < Vagrant::Command::Base class CommandBase < Vagrant.plugin("1", :command)
# This is the command that this easy command responds to # This is the command that this easy command responds to
attr_reader :command attr_reader :command

View File

@ -5,6 +5,7 @@ require "vagrant/plugin/v1/errors"
module Vagrant module Vagrant
module Plugin module Plugin
module V1 module V1
autoload :Command, "vagrant/plugin/v1/command"
autoload :Config, "vagrant/plugin/v1/config" autoload :Config, "vagrant/plugin/v1/config"
autoload :Plugin, "vagrant/plugin/v1/plugin" autoload :Plugin, "vagrant/plugin/v1/plugin"
autoload :Provisioner, "vagrant/plugin/v1/provisioner" autoload :Provisioner, "vagrant/plugin/v1/provisioner"

View File

@ -0,0 +1,169 @@
require 'log4r'
require "vagrant/util/safe_puts"
module Vagrant
module Plugin
module V1
# This is the base class for a CLI command.
class Command
include Util::SafePuts
def initialize(argv, env)
@argv = argv
@env = env
@logger = Log4r::Logger.new("vagrant::command::#{self.class.to_s.downcase}")
end
# This is what is called on the class to actually execute it. Any
# subclasses should implement this method and do any option parsing
# and validation here.
def execute
end
protected
# Parses the options given an OptionParser instance.
#
# This is a convenience method that properly handles duping the
# originally argv array so that it is not destroyed.
#
# This method will also automatically detect "-h" and "--help"
# and print help. And if any invalid options are detected, the help
# will be printed, as well.
#
# If this method returns `nil`, then you should assume that help
# was printed and parsing failed.
def parse_options(opts=nil)
# Creating a shallow copy of the arguments so the OptionParser
# doesn't destroy the originals.
argv = @argv.dup
# Default opts to a blank optionparser if none is given
opts ||= OptionParser.new
# Add the help option, which must be on every command.
opts.on_tail("-h", "--help", "Print this help") do
safe_puts(opts.help)
return nil
end
opts.parse!(argv)
return argv
rescue OptionParser::InvalidOption
raise Errors::CLIInvalidOptions, :help => opts.help.chomp
end
# Yields a VM for each target VM for the command.
#
# This is a convenience method for easily implementing methods that
# take a target VM (in the case of multi-VM) or every VM if no
# specific VM name is specified.
#
# @param [String] name The name of the VM. Nil if every VM.
# @param [Boolean] single_target If true, then an exception will be
# raised if more than one target is found.
def with_target_vms(names=nil, options=nil)
# Using VMs requires a Vagrant environment to be properly setup
raise Errors::NoEnvironmentError if !@env.root_path
# Setup the options hash
options ||= {}
# Require that names be an array
names ||= []
names = [names] if !names.is_a?(Array)
# First determine the proper array of VMs.
vms = []
if names.length > 0
names.each do |name|
if pattern = name[/^\/(.+?)\/$/, 1]
# This is a regular expression name, so we convert to a regular
# expression and allow that sort of matching.
regex = Regexp.new(pattern)
@env.vms.each do |name, vm|
vms << vm if name =~ regex
end
raise Errors::VMNoMatchError if vms.empty?
else
# String name, just look for a specific VM
vms << @env.vms[name.to_sym]
raise Errors::VMNotFoundError, :name => name if !vms[0]
end
end
else
vms = @env.vms_ordered
end
# Make sure we're only working with one VM if single target
if options[:single_target] && vms.length != 1
vm = @env.primary_vm
raise Errors::MultiVMTargetRequired if !vm
vms = [vm]
end
# If we asked for reversed ordering, then reverse it
vms.reverse! if options[:reverse]
# Go through each VM and yield it!
vms.each do |old_vm|
# We get a new VM from the environment here to avoid potentially
# stale VMs (if there was a config reload on the environment
# or something).
vm = @env.vms[old_vm.name]
yield vm
end
end
# This method will split the argv given into three parts: the
# flags to this command, the subcommand, and the flags to the
# subcommand. For example:
#
# -v status -h -v
#
# The above would yield 3 parts:
#
# ["-v"]
# "status"
# ["-h", "-v"]
#
# These parts are useful because the first is a list of arguments
# given to the current command, the second is a subcommand, and the
# third are the commands given to the subcommand.
#
# @return [Array] The three parts.
def split_main_and_subcommand(argv)
# Initialize return variables
main_args = nil
sub_command = nil
sub_args = []
# We split the arguments into two: One set containing any
# flags before a word, and then the rest. The rest are what
# get actually sent on to the subcommand.
argv.each_index do |i|
if !argv[i].start_with?("-")
# We found the beginning of the sub command. Split the
# args up.
main_args = argv[0, i]
sub_command = argv[i]
sub_args = argv[i + 1, argv.length - i + 1]
# Break so we don't find the next non flag and shift our
# main args.
break
end
end
# Handle the case that argv was empty or didn't contain any subcommand
main_args = argv.dup if main_args.nil?
return [main_args, sub_command, sub_args]
end
end
end
end
end

View File

@ -3,7 +3,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandBox module CommandBox
module Command module Command
class Add < Vagrant::Command::Base class Add < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -3,7 +3,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandBox module CommandBox
module Command module Command
class List < Vagrant::Command::Base class List < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -3,7 +3,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandBox module CommandBox
module Command module Command
class Remove < Vagrant::Command::Base class Remove < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -3,7 +3,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandBox module CommandBox
module Command module Command
class Repackage < Vagrant::Command::Base class Repackage < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -3,7 +3,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandBox module CommandBox
module Command module Command
class Root < Vagrant::Command::Base class Root < Vagrant.plugin("1", :command)
def initialize(argv, env) def initialize(argv, env)
super super

View File

@ -1,6 +1,6 @@
module VagrantPlugins module VagrantPlugins
module CommandDestroy module CommandDestroy
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -5,7 +5,7 @@ require "vagrant/util/safe_puts"
module VagrantPlugins module VagrantPlugins
module CommandGem module CommandGem
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
include Vagrant::Util::SafePuts include Vagrant::Util::SafePuts
def execute def execute

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandHalt module CommandHalt
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -4,7 +4,7 @@ require 'vagrant/util/template_renderer'
module VagrantPlugins module VagrantPlugins
module CommandInit module CommandInit
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandPackage module CommandPackage
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandProvision module CommandProvision
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -6,7 +6,7 @@ require Vagrant.source_root.join("plugins/commands/up/start_mixins")
module VagrantPlugins module VagrantPlugins
module CommandReload module CommandReload
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
# We assume that the `up` plugin exists and that we'll have access # We assume that the `up` plugin exists and that we'll have access
# to this. # to this.
include VagrantPlugins::CommandUp::StartMixins include VagrantPlugins::CommandUp::StartMixins

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandResume module CommandResume
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandSSH module CommandSSH
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -4,7 +4,7 @@ require "vagrant/util/safe_puts"
module VagrantPlugins module VagrantPlugins
module CommandSSHConfig module CommandSSHConfig
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
include Vagrant::Util::SafePuts include Vagrant::Util::SafePuts
def execute def execute

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandStatus module CommandStatus
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -2,7 +2,7 @@ require 'optparse'
module VagrantPlugins module VagrantPlugins
module CommandSuspend module CommandSuspend
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
def execute def execute
options = {} options = {}

View File

@ -6,7 +6,7 @@ require File.expand_path("../start_mixins", __FILE__)
module VagrantPlugins module VagrantPlugins
module CommandUp module CommandUp
class Command < Vagrant::Command::Base class Command < Vagrant.plugin("1", :command)
include StartMixins include StartMixins
def execute def execute

View File

@ -1,7 +1,7 @@
require File.expand_path("../../../base", __FILE__) require File.expand_path("../../../../base", __FILE__)
require 'optparse' require 'optparse'
describe Vagrant::Command::Base do describe Vagrant::Plugin::V1::Command do
describe "parsing options" do describe "parsing options" do
let(:klass) do let(:klass) do
Class.new(described_class) do Class.new(described_class) do

View File

@ -12,6 +12,7 @@ describe Vagrant do
end end
it "returns the proper components for version 1" do it "returns the proper components for version 1" do
described_class.plugin("1", :command).should == Vagrant::Plugin::V1::Command
described_class.plugin("1", :config).should == Vagrant::Plugin::V1::Config described_class.plugin("1", :config).should == Vagrant::Plugin::V1::Config
described_class.plugin("1", :provisioner).should == Vagrant::Plugin::V1::Provisioner described_class.plugin("1", :provisioner).should == Vagrant::Plugin::V1::Provisioner
end end