`vagrant up`
This commit is contained in:
parent
7191a54ed7
commit
43cadfe830
|
@ -46,6 +46,14 @@ module Vagrant
|
|||
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
||||
end
|
||||
|
||||
# Global registry of commands that are available via the CLI.
|
||||
#
|
||||
# This registry is used to look up the sub-commands that are available
|
||||
# to Vagrant.
|
||||
def self.commands
|
||||
@commands ||= Registry.new
|
||||
end
|
||||
|
||||
# Global registry of config keys that are available.
|
||||
#
|
||||
# This registry is used to look up the keys for `config` objects.
|
||||
|
@ -85,7 +93,10 @@ end
|
|||
# # Default I18n to load the en locale
|
||||
I18n.load_path << File.expand_path("templates/locales/en.yml", Vagrant.source_root)
|
||||
|
||||
# Registry the build-in config keys
|
||||
# Register the built-in commands
|
||||
Vagrant.commands.register(:up) { Vagrant::Command::Up }
|
||||
|
||||
# Register the built-in config keys
|
||||
Vagrant.config_keys.register(:vagrant) { Vagrant::Config::VagrantConfig }
|
||||
Vagrant.config_keys.register(:ssh) { Vagrant::Config::SSHConfig }
|
||||
Vagrant.config_keys.register(:nfs) { Vagrant::Config::NFSConfig }
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
require 'log4r'
|
||||
require 'optparse'
|
||||
|
||||
module Vagrant
|
||||
# Manages the command line interface to Vagrant.
|
||||
class CLI < Command::Base
|
||||
def initialize(argv, env)
|
||||
@env = env
|
||||
super
|
||||
|
||||
@logger = Log4r::Logger.new("vagrant::cli")
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
|
||||
@logger.info("CLI: #{@main_args.inspect} #{@sub_command.inspect} #{@sub_args.inspect}")
|
||||
end
|
||||
|
||||
def execute
|
||||
|
@ -22,9 +27,18 @@ module Vagrant
|
|||
# the help and exit.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = Vagrant.commands.get(@sub_command.to_sym)
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class.
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# This prints the help for the CLI out.
|
||||
# This prints out the help for the CLI.
|
||||
def help
|
||||
# We use the optionparser for this. Its just easier. We don't use
|
||||
# an optionparser above because I don't think the performance hits
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
module Vagrant
|
||||
module Command
|
||||
autoload :Base, 'vagrant/command/base'
|
||||
|
||||
autoload :Up, 'vagrant/command/up'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,63 @@
|
|||
require 'log4r'
|
||||
|
||||
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
|
||||
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. That is all.
|
||||
def parse_options(opts)
|
||||
argv = @argv.dup
|
||||
opts.parse!(argv)
|
||||
return argv
|
||||
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.
|
||||
def with_target_vms(name=nil)
|
||||
# First determine the proper array of VMs.
|
||||
vms = []
|
||||
if name
|
||||
raise Errors::MultiVMEnvironmentRequired if !@env.multivm?
|
||||
vms << @env.vms[name.to_sym]
|
||||
raise Errors::VMNotFoundError, :name => name if !vms[0]
|
||||
else
|
||||
vms = @env.vms_ordered
|
||||
end
|
||||
|
||||
# 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:
|
||||
|
@ -36,6 +91,10 @@ module Vagrant
|
|||
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
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
module Vagrant
|
||||
module Command
|
||||
module Helpers
|
||||
# Initializes the environment by pulling the environment out of
|
||||
# the configuration hash and sets up the UI if necessary.
|
||||
def initialize_environment(args, options, config)
|
||||
raise Errors::CLIMissingEnvironment if !config[:env]
|
||||
@env = config[:env]
|
||||
end
|
||||
|
||||
# This returns an array of {VM} objects depending on the arguments
|
||||
# given to the command.
|
||||
def target_vms(name=nil)
|
||||
raise Errors::NoEnvironmentError if !env.root_path
|
||||
|
||||
name ||= self.name rescue nil
|
||||
|
||||
@target_vms ||= begin
|
||||
if env.multivm?
|
||||
return env.vms_ordered if !name
|
||||
vm = env.vms[name.to_sym]
|
||||
raise Errors::VMNotFoundError, :name => name if !vm
|
||||
else
|
||||
raise Errors::MultiVMEnvironmentRequired if name
|
||||
vm = env.vms.values.first
|
||||
end
|
||||
|
||||
[vm]
|
||||
end
|
||||
end
|
||||
|
||||
# This will yield for each target VM to the command. The VM is guaranteed
|
||||
# to be loaded on each iteration.
|
||||
def with_target_vms
|
||||
target_vms.each do |old_vm|
|
||||
# We get a new VM here to avoid potentially stale VMs
|
||||
vm = env.vms[old_vm.name]
|
||||
yield vm
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,15 +1,38 @@
|
|||
require 'optparse'
|
||||
|
||||
module Vagrant
|
||||
module Command
|
||||
class UpCommand < NamedBase
|
||||
class_option :provision, :type => :boolean, :default => true
|
||||
register "up", "Creates the Vagrant environment"
|
||||
|
||||
class Up < Base
|
||||
def execute
|
||||
with_target_vms do |vm|
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant up [vm-name] [--[no-]provision] [-h]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("--[no-]provision", "Enable or disable provisioning") do |p|
|
||||
options[:provision] = p
|
||||
end
|
||||
|
||||
opts.on("-h", "--help", "Print this help") do
|
||||
puts opts.help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
|
||||
# Go over each VM and bring it up
|
||||
@logger.debug("'Up' each target VM...")
|
||||
with_target_vms(argv[0]) do |vm|
|
||||
if vm.created?
|
||||
vm.env.ui.info I18n.t("vagrant.commands.up.vm_created")
|
||||
@logger.info("Booting: #{vm.name}")
|
||||
vm.ui.info I18n.t("vagrant.commands.up.vm_created")
|
||||
vm.start("provision.enabled" => options[:provision])
|
||||
else
|
||||
@logger.info("Creating: #{vm.name}")
|
||||
vm.up("provision.enabled" => options[:provision])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -139,6 +139,7 @@ module Vagrant
|
|||
#
|
||||
# @return [Array<VM>]
|
||||
def vms_ordered
|
||||
return @vms.values if !multivm?
|
||||
@vms_enum ||= config.global.vm.defined_vm_keys.map { |name| @vms[name] }
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,94 @@
|
|||
require File.expand_path("../../../base", __FILE__)
|
||||
require 'optparse'
|
||||
|
||||
describe Vagrant::Command::Base do
|
||||
describe "parsing options" do
|
||||
let(:klass) do
|
||||
Class.new(described_class) do
|
||||
# Make the method public since it is normally protected
|
||||
public :parse_options
|
||||
end
|
||||
end
|
||||
|
||||
it "returns the remaining arguments" do
|
||||
options = {}
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.on("-f") do |f|
|
||||
options[:f] = f
|
||||
end
|
||||
end
|
||||
|
||||
result = klass.new(["-f", "foo"], nil).parse_options(opts)
|
||||
|
||||
# Check the results
|
||||
options[:f].should be
|
||||
result.should == ["foo"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "target VMs" do
|
||||
let(:klass) do
|
||||
Class.new(described_class) do
|
||||
# Make the method public since it is normally protected
|
||||
public :with_target_vms
|
||||
end
|
||||
end
|
||||
|
||||
let(:environment) { double("environment") }
|
||||
let(:instance) { klass.new([], environment) }
|
||||
|
||||
it "should raise an exception if a name is given in a non-multivm environment" do
|
||||
environment.stub(:multivm?).and_return(false)
|
||||
|
||||
expect { instance.with_target_vms("foo") }.
|
||||
to raise_error(Vagrant::Errors::MultiVMEnvironmentRequired)
|
||||
end
|
||||
|
||||
it "should yield every VM in order is no name is given" do
|
||||
foo_vm = double("foo")
|
||||
foo_vm.stub(:name).and_return("foo")
|
||||
|
||||
bar_vm = double("bar")
|
||||
bar_vm.stub(:name).and_return("bar")
|
||||
|
||||
environment.stub(:multivm? => true,
|
||||
:vms => { "foo" => foo_vm, "bar" => bar_vm },
|
||||
:vms_ordered => [foo_vm, bar_vm])
|
||||
|
||||
vms = []
|
||||
instance.with_target_vms do |vm|
|
||||
vms << vm
|
||||
end
|
||||
|
||||
vms.should == [foo_vm, bar_vm]
|
||||
end
|
||||
|
||||
it "raises an exception if the named VM doesn't exist" do
|
||||
environment.stub(:multivm? => true, :vms => {})
|
||||
|
||||
expect { instance.with_target_vms("foo") }.
|
||||
to raise_error(Vagrant::Errors::VMNotFoundError)
|
||||
end
|
||||
|
||||
it "yields the given VM if a name is given" do
|
||||
foo_vm = double("foo")
|
||||
foo_vm.stub(:name).and_return(:foo)
|
||||
|
||||
environment.stub(:multivm? => true,
|
||||
:vms => { :foo => foo_vm, :bar => nil })
|
||||
|
||||
vms = []
|
||||
instance.with_target_vms("foo") { |vm| vms << vm }
|
||||
vms.should == [foo_vm]
|
||||
end
|
||||
end
|
||||
|
||||
describe "splitting the main and subcommand args" do
|
||||
let(:instance) do
|
||||
Class.new(described_class) do
|
||||
# Make the method public since it is normal protected
|
||||
# Make the method public since it is normally protected
|
||||
public :split_main_and_subcommand
|
||||
end.new
|
||||
end.new(nil, nil)
|
||||
end
|
||||
|
||||
it "should work when given all 3 parts" do
|
||||
|
@ -28,5 +110,10 @@ describe Vagrant::Command::Base do
|
|||
result = instance.split_main_and_subcommand(["status"])
|
||||
result.should == [[], "status", []]
|
||||
end
|
||||
|
||||
it "works when there are other non-flag args after the subcommand" do
|
||||
result = instance.split_main_and_subcommand(["-v", "box", "add", "-h"])
|
||||
result.should == [["-v"], "box", ["add", "-h"]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,10 @@ describe Vagrant do
|
|||
described_class.source_root.should == Pathname.new(File.expand_path("../../../", __FILE__))
|
||||
end
|
||||
|
||||
it "has a registry for commands" do
|
||||
described_class.commands.should be_a(Vagrant::Registry)
|
||||
end
|
||||
|
||||
it "has a registry for config keys" do
|
||||
described_class.config_keys.should be_a(Vagrant::Registry)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue