Merge branch 'multivm'

This commit is contained in:
Mitchell Hashimoto 2010-05-17 14:15:43 -07:00
commit 9111ad9e5e
55 changed files with 1404 additions and 520 deletions

View File

@ -14,4 +14,5 @@ group :test do
gem "contest", ">= 0.1.2" gem "contest", ">= 0.1.2"
gem "mocha" gem "mocha"
gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9' gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9'
gem "jeweler", "~> 1.4.0"
end end

View File

@ -1 +1 @@
0.3.3.dev 0.3.4.dev

View File

@ -30,7 +30,7 @@ module Vagrant
@runner.env.config.ssh.max_tries.to_i.times do |i| @runner.env.config.ssh.max_tries.to_i.times do |i|
logger.info "Trying to connect (attempt ##{i+1} of #{@runner.env.config[:ssh][:max_tries]})..." logger.info "Trying to connect (attempt ##{i+1} of #{@runner.env.config[:ssh][:max_tries]})..."
if @runner.env.ssh.up? if @runner.ssh.up?
logger.info "VM booted and ready for use!" logger.info "VM booted and ready for use!"
return true return true
end end

View File

@ -5,17 +5,18 @@ module Vagrant
def execute! def execute!
@runner.invoke_around_callback(:destroy) do @runner.invoke_around_callback(:destroy) do
destroy_vm destroy_vm
depersist update_dotfile
end end
end end
def destroy_vm def destroy_vm
logger.info "Destroying VM and associated drives..." logger.info "Destroying VM and associated drives..."
@runner.vm.destroy(:destroy_medium => :delete) @runner.vm.destroy(:destroy_medium => :delete)
@runner.vm = nil
end end
def depersist def update_dotfile
@runner.env.depersist_vm @runner.env.update_dotfile
end end
end end
end end

View File

@ -26,7 +26,7 @@ module Vagrant
def clone_and_attach def clone_and_attach
logger.info "Cloning current VM Disk to new location (#{new_image_path})..." logger.info "Cloning current VM Disk to new location (#{new_image_path})..."
hard_drive.image = hard_drive.image.clone(new_image_path, Vagrant.config.vm.disk_image_format, true) hard_drive.image = hard_drive.image.clone(new_image_path, @runner.env.config.vm.disk_image_format, true)
logger.info "Attaching new disk to VM ..." logger.info "Attaching new disk to VM ..."
@runner.vm.save @runner.vm.save
@ -43,7 +43,7 @@ module Vagrant
# Returns the path to the new location for the hard drive # Returns the path to the new location for the hard drive
def new_image_path def new_image_path
File.join(Vagrant.config.vm.hd_location, hard_drive.image.filename) File.join(@runner.env.config.vm.hd_location, hard_drive.image.filename)
end end
end end
end end

View File

@ -17,7 +17,7 @@ module Vagrant
def after_boot def after_boot
logger.info "Mounting shared folders..." logger.info "Mounting shared folders..."
@runner.env.ssh.execute do |ssh| @runner.ssh.execute do |ssh|
shared_folders.each do |name, hostpath, guestpath| shared_folders.each do |name, hostpath, guestpath|
logger.info "-- #{name}: #{guestpath}" logger.info "-- #{name}: #{guestpath}"
@runner.system.mount_shared_folder(ssh, name, guestpath) @runner.system.mount_shared_folder(ssh, name, guestpath)

View File

@ -19,13 +19,13 @@ module Vagrant
end end
def after_import def after_import
persist update_dotfile
setup_mac_address setup_mac_address
end end
def persist def update_dotfile
logger.info "Persisting the VM UUID (#{@runner.uuid})..." logger.info "Persisting the VM UUID (#{@runner.uuid})..."
@runner.env.persist_vm @runner.env.update_dotfile
end end
def setup_mac_address def setup_mac_address

View File

@ -5,7 +5,7 @@ module Vagrant
class Command class Command
attr_reader :env attr_reader :env
class <<self class << self
# Executes a given subcommand within the current environment (from the # Executes a given subcommand within the current environment (from the
# current working directory). # current working directory).
def execute(*args) def execute(*args)

View File

@ -12,7 +12,7 @@ module Vagrant
attr_reader :env attr_reader :env
class <<self class << self
# Contains the list of registered subcommands. The registered commands are # Contains the list of registered subcommands. The registered commands are
# stored in a hash table and are therefore unordered. # stored in a hash table and are therefore unordered.
# #
@ -126,7 +126,6 @@ module Vagrant
# to parse command line options. # to parse command line options.
def parse_options(args) def parse_options(args)
option_parser.parse!(args) option_parser.parse!(args)
options
rescue OptionParser::InvalidOption rescue OptionParser::InvalidOption
show_help show_help
end end

View File

@ -11,8 +11,35 @@ module Vagrant
description "Destroys the vagrant environment" description "Destroys the vagrant environment"
def execute(args=[]) def execute(args=[])
env.require_persisted_vm args = parse_options(args)
env.vm.destroy
if args[0]
destroy_single(args[0])
else
destroy_all
end
end
# Destroys a single VM by name.
def destroy_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
vm.destroy
else
logger.info "VM '#{name}' not created. Ignoring."
end
end
# Destroys all VMs represented by the current environment.
def destroy_all
env.vms.each do |name, vm|
destroy_single(name)
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -11,10 +11,33 @@ module Vagrant
description "Halts the currently running vagrant environment" description "Halts the currently running vagrant environment"
def execute(args=[]) def execute(args=[])
parse_options(args) args = parse_options(args)
env.require_persisted_vm if args[0]
env.vm.execute!(Actions::VM::Halt, options[:force]) halt_single(args[0])
else
halt_all
end
end
def halt_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
vm.halt(options[:force])
else
logger.info "VM '#{name}' not created. Ignoring."
end
end
def halt_all
env.vms.keys.each do |name|
halt_single(name)
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -8,23 +8,58 @@ module Vagrant
description "Packages a vagrant environment for distribution" description "Packages a vagrant environment for distribution"
def execute(args=[]) def execute(args=[])
parse_options(args) args = parse_options(args)
if !options[:base] if options[:base]
# Packaging a pre-existing environment package_base
env.require_persisted_vm
else else
package_single(args[0])
end
end
def package_base
# Packaging a base box; that is a VM not tied to a specific # Packaging a base box; that is a VM not tied to a specific
# vagrant environment # vagrant environment
vm = VM.find(options[:base]) vm = VM.find(options[:base])
vm.env = env if vm if !vm
env.vm = vm error_and_exit(:vm_base_not_found, :name => options[:base])
return # for tests
error_and_exit(:vm_base_not_found, :name => options[:base]) unless vm
end end
error_and_exit(:vm_power_off_to_package) unless env.vm.powered_off? vm.env = env
env.vm.package(args[0], options[:include]) package_vm(vm)
end
def package_single(name)
if name.nil? && env.multivm?
error_and_exit(:package_multivm)
return
end
vm = if name.nil?
env.vms.values.first
else
env.vms[name.to_sym]
end
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return
elsif !vm.created?
error_and_exit(:environment_not_created)
return
end
package_vm(vm)
end
def package_vm(vm)
if !vm.powered_off?
error_and_exit(:vm_power_off_to_package)
return # for tests
end
vm.package(options[:output], options[:include])
end end
def options_spec(opts) def options_spec(opts)
@ -32,14 +67,20 @@ module Vagrant
# Defaults # Defaults
options[:include] = [] options[:include] = []
options[:base] = nil
options[:output] = nil
opts.on("--base [BASE]", "Name or UUID of VM to create a base box from") do |v| opts.on("--base BASE", "Name or UUID of VM to create a base box from") do |v|
options[:base] = v options[:base] = v
end end
opts.on("--include x,y,z", Array, "List of files to include in the package") do |v| opts.on("--include x,y,z", Array, "List of files to include in the package") do |v|
options[:include] = v options[:include] = v
end end
opts.on("-o", "--output FILE", "File to save the package as.") do |v|
options[:output] = v
end
end end
end end
end end

View File

@ -10,8 +10,33 @@ module Vagrant
description "Reload the vagrant environment" description "Reload the vagrant environment"
def execute(args=[]) def execute(args=[])
env.require_persisted_vm args = parse_options(args)
env.vm.execute!(Actions::VM::Reload)
if args[0]
reload_single(args[0])
else
reload_all
end
end
def reload_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
vm.reload
else
logger.info "VM '#{name}' not created. Ignoring."
end
end
def reload_all
env.vms.keys.each do |name|
reload_single(name)
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -10,8 +10,33 @@ module Vagrant
description "Resumes a suspend vagrant environment" description "Resumes a suspend vagrant environment"
def execute(args=[]) def execute(args=[])
env.require_persisted_vm args = parse_options(args)
env.vm.resume
if args[0]
resume_single(args[0])
else
resume_all
end
end
def resume_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
vm.resume
else
logger.info "VM '#{name}' not created. Ignoring."
end
end
def resume_all
env.vms.keys.each do |name|
resume_single(name)
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -10,8 +10,28 @@ module Vagrant
description "SSH into the currently running environment" description "SSH into the currently running environment"
def execute(args=[]) def execute(args=[])
env.require_persisted_vm args = parse_options(args)
env.ssh.connect ssh_connect(args[0])
end
def ssh_connect(name)
if name.nil? && env.multivm?
error_and_exit(:ssh_multivm)
return # for tests
end
vm = name.nil? ? env.vms.values.first : env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if !vm.created?
error_and_exit(:environment_not_created)
return
else
vm.ssh.connect
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -9,12 +9,27 @@ module Vagrant
def execute(args=[]) def execute(args=[])
env.require_root_path env.require_root_path
parse_options(args) args = parse_options(args)
show_single(args[0])
end
def show_single(name)
if name.nil? && env.multivm?
error_and_exit(:ssh_config_multivm)
return # for tests
end
vm = name.nil? ? env.vms.values.first : env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
puts TemplateRenderer.render("ssh_config", { puts TemplateRenderer.render("ssh_config", {
:host_key => options[:host] || "vagrant", :host_key => options[:host] || "vagrant",
:ssh_user => env.config.ssh.username, :ssh_user => vm.env.config.ssh.username,
:ssh_port => env.ssh.port, :ssh_port => vm.ssh.port,
:private_key_path => env.config.ssh.private_key_path :private_key_path => vm.env.config.ssh.private_key_path
}) })
end end

View File

@ -8,43 +8,87 @@ module Vagrant
description "Shows the status of the Vagrant environment." description "Shows the status of the Vagrant environment."
def execute(args=[]) def execute(args=[])
parse_options(args) args = parse_options(args)
if args.length > 1
# There should never be more than 1 arg
show_help
return
end
if !options[:global] if !options[:global]
show_local_status show_local_status(*args)
else else
show_global_status show_global_status
end end
end end
# Shows the status of the CURRENT environment (the current working # Shows the status of the CURRENT environment (the current working
# directory). This prints out a human friendly sentence or paragraph # directory). If a specific VM was given, it will print out
# describing the state of the Vagrant environment represented by the # detailed information regarding that VM. If no single VM was
# current working directory. # specified and it is a multi-VM environment, it will simply
def show_local_status # show a listing of all the VMs and their short one word
# statuses.
def show_local_status(vm=nil)
if !env.root_path
wrap_output { puts Translator.t(:status_no_environment) }
return
end
if vm.nil?
if env.multivm?
# No specific VM was specified in a multi-vm environment,
# so show short info for each VM
show_list
return
else
# Set the VM to just be the root VM
vm = env.vms.values.first
end
else
# Try to get the vm based on the name. If the specified VM
# doesn't exist, then error saying so
vm = env.vms[vm.to_sym] || error_and_exit(:unknown_vm, :vm => vm)
end
show_single(vm)
end
# Lists the available VMs and brief statuses about each.
def show_list
wrap_output do
puts Translator.t(:status_listing)
puts ""
env.vms.each do |name, vm|
state = vm.created? ? vm.vm.state : "not created"
puts "#{name.to_s.ljust(30)}#{state}"
end
end
end
# Shows a paragraph of information based on the current state of
# a single, specified VM.
def show_single(vm)
string_key = nil string_key = nil
if !env.root_path if !vm.created?
string_key = :status_no_environment
elsif !env.vm
string_key = :status_not_created string_key = :status_not_created
else else
additional_key = nil additional_key = nil
if env.vm.vm.running? if vm.vm.running?
additional_key = :status_created_running additional_key = :status_created_running
elsif env.vm.vm.saved? elsif vm.vm.saved?
additional_key = :status_created_saved additional_key = :status_created_saved
elsif env.vm.vm.powered_off? elsif vm.vm.powered_off?
additional_key = :status_created_powered_off additional_key = :status_created_powered_off
end end
string_key = [:status_created, { string_key = [:status_created, {
:vm_state => env.vm.vm.state, :vm_state => vm.vm.state,
:additional_message => additional_key ? Translator.t(additional_key) : "" :additional_message => additional_key ? Translator.t(additional_key) : ""
}] }]
end end
string_key = [string_key, {}] unless string_key.is_a?(Array)
wrap_output { puts Translator.t(*string_key) } wrap_output { puts Translator.t(*string_key) }
end end
@ -70,6 +114,7 @@ module Vagrant
# Defaults # Defaults
options[:global] = false options[:global] = false
options[:vm] = nil
opts.on("-g", "--global", "Show global status of Vagrant (running VMs managed by Vagrant)") do |v| opts.on("-g", "--global", "Show global status of Vagrant (running VMs managed by Vagrant)") do |v|
options[:global] = true options[:global] = true

View File

@ -11,8 +11,33 @@ module Vagrant
description "Suspends the currently running vagrant environment" description "Suspends the currently running vagrant environment"
def execute(args=[]) def execute(args=[])
env.require_persisted_vm args = parse_options(args)
env.vm.suspend
if args[0]
suspend_single(args[0])
else
suspend_all
end
end
def suspend_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
vm.suspend
else
logger.info "VM '#{name}' not created. Ignoring."
end
end
def suspend_all
env.vms.keys.each do |name|
suspend_single(name)
end
end end
def options_spec(opts) def options_spec(opts)

View File

@ -9,12 +9,40 @@ module Vagrant
description "Creates the vagrant environment" description "Creates the vagrant environment"
def execute(args=[]) def execute(args=[])
if env.vm args = parse_options(args)
logger.info "VM already created. Starting VM if its not already running..."
env.vm.start if args[0]
up_single(args[0])
else else
env.require_box up_all
env.create_vm.execute!(Actions::VM::Up) end
end
def up_single(name)
vm = env.vms[name.to_sym]
if vm.nil?
error_and_exit(:unknown_vm, :vm => name)
return # for tests
end
if vm.created?
logger.info "VM '#{name}' already created. Booting if its not already running..."
vm.start
else
vm.env.require_box
logger.info "Creating VM '#{name}'"
vm.up
end
end
def up_all
# First verify that all VMs have valid boxes
env.vms.each { |name, vm| vm.env.require_box unless vm.created? }
# Next, handle each VM
env.vms.keys.each do |name|
up_single(name)
end end
end end

View File

@ -29,10 +29,12 @@ module Vagrant
push_proc(&block) push_proc(&block)
end end
def execute! def execute!(config_object=nil)
run_procs!(config) config_object ||= config
config.loaded!
config run_procs!(config_object)
config_object.loaded!
config_object
end end
end end
end end
@ -125,6 +127,18 @@ module Vagrant
def customize(&block) def customize(&block)
push_proc(&block) push_proc(&block)
end end
def has_multi_vms?
!defined_vms.empty?
end
def defined_vms
@defined_vms ||= {}
end
def define(name, &block)
defined_vms[name.to_sym] = block
end
end end
class PackageConfig < Base class PackageConfig < Base

View File

@ -5,27 +5,31 @@ module Vagrant
class Environment class Environment
ROOTFILE_NAME = "Vagrantfile" ROOTFILE_NAME = "Vagrantfile"
HOME_SUBDIRS = ["tmp", "boxes"] HOME_SUBDIRS = ["tmp", "boxes"]
DEFAULT_VM = :default
include Util include Util
attr_reader :parent # Parent environment (in the case of multi-VMs)
attr_reader :vm_name # The name of the VM (internal name) which this environment represents
attr_accessor :cwd attr_accessor :cwd
attr_reader :root_path attr_reader :root_path
attr_reader :config attr_reader :config
attr_reader :box attr_reader :box
attr_accessor :vm attr_accessor :vm
attr_reader :ssh attr_reader :vms
attr_reader :active_list attr_reader :active_list
attr_reader :commands attr_reader :commands
#--------------------------------------------------------------- #---------------------------------------------------------------
# Class Methods # Class Methods
#--------------------------------------------------------------- #---------------------------------------------------------------
class <<self class << self
# Loads and returns an environment given a specific working # Loads and returns an environment given a specific working
# directory. If a working directory is not given, it will default # directory. If a working directory is not given, it will default
# to the pwd. # to the pwd.
def load!(cwd=nil) def load!(cwd=nil)
Environment.new(cwd).load! Environment.new(:cwd => cwd).load!
end end
# Verifies that VirtualBox is installed and that the version of # Verifies that VirtualBox is installed and that the version of
@ -43,12 +47,23 @@ module Vagrant
end end
end end
def initialize(cwd=nil) def initialize(opts=nil)
@cwd = cwd defaults = {
:parent => nil,
:vm_name => nil,
:vm => nil,
:cwd => nil
}
opts = defaults.merge(opts || {})
defaults.each do |key, value|
instance_variable_set("@#{key}".to_sym, opts[key])
end
end end
#--------------------------------------------------------------- #---------------------------------------------------------------
# Path Helpers # Helpers
#--------------------------------------------------------------- #---------------------------------------------------------------
# Specifies the "current working directory" for this environment. # Specifies the "current working directory" for this environment.
@ -62,7 +77,7 @@ module Vagrant
# The path to the `dotfile`, which contains the persisted UUID of # The path to the `dotfile`, which contains the persisted UUID of
# the VM if it exists. # the VM if it exists.
def dotfile_path def dotfile_path
File.join(root_path, config.vagrant.dotfile_name) root_path ? File.join(root_path, config.vagrant.dotfile_name) : nil
end end
# The path to the home directory, which is usually in `~/.vagrant/~ # The path to the home directory, which is usually in `~/.vagrant/~
@ -80,6 +95,22 @@ module Vagrant
File.join(home_path, "boxes") File.join(home_path, "boxes")
end end
# Returns the VMs associated with this environment.
def vms
@vms ||= {}
end
# Returns a boolean whether this environment represents a multi-VM
# environment or not. This will work even when called on child
# environments.
def multivm?
if parent
parent.multivm?
else
vms.length > 1
end
end
#--------------------------------------------------------------- #---------------------------------------------------------------
# Load Methods # Load Methods
#--------------------------------------------------------------- #---------------------------------------------------------------
@ -95,7 +126,6 @@ module Vagrant
load_config! load_config!
self.class.check_virtualbox! self.class.check_virtualbox!
load_vm! load_vm!
load_ssh!
load_active_list! load_active_list!
load_commands! load_commands!
self self
@ -125,20 +155,30 @@ module Vagrant
# this environment, meaning that it will use the given root directory # this environment, meaning that it will use the given root directory
# to load the Vagrantfile into that context. # to load the Vagrantfile into that context.
def load_config! def load_config!
# Prepare load paths for config files # Prepare load paths for config files and append to config queue
load_paths = [File.join(PROJECT_ROOT, "config", "default.rb")] config_queue = [File.join(PROJECT_ROOT, "config", "default.rb")]
load_paths << File.join(box.directory, ROOTFILE_NAME) if box config_queue << File.join(box.directory, ROOTFILE_NAME) if box
load_paths << File.join(home_path, ROOTFILE_NAME) if home_path config_queue << File.join(home_path, ROOTFILE_NAME) if home_path
load_paths << File.join(root_path, ROOTFILE_NAME) if root_path config_queue << File.join(root_path, ROOTFILE_NAME) if root_path
# If this environment represents some VM in a multi-VM environment,
# we push that VM's configuration onto the config_queue.
config_queue << parent.config.vm.defined_vms[vm_name] if vm_name
# Clear out the old data # Clear out the old data
Config.reset!(self) Config.reset!(self)
# Load each of the config files in order # Load each of the config files in order
load_paths.each do |path| config_queue.each do |item|
if File.exist?(path) if item.is_a?(String) && File.exist?(item)
logger.info "Loading config from #{path}..." logger.info "Loading config from #{item}..."
load path load item
next
end
if item.is_a?(Proc)
# Just push the proc straight onto the config runnable stack
Config.run(&item)
end end
end end
@ -171,18 +211,49 @@ module Vagrant
# Loads the persisted VM (if it exists) for this environment. # Loads the persisted VM (if it exists) for this environment.
def load_vm! def load_vm!
return if !root_path || !File.file?(dotfile_path) # This environment represents a single sub VM. The VM is then
# probably (read: should be) set on the VM attribute, so we do
# nothing.
return if vm_name
# First load the defaults (blank, noncreated VMs)
load_blank_vms!
# If we have no dotfile, then return
return if !dotfile_path || !File.file?(dotfile_path)
# Open and parse the dotfile
File.open(dotfile_path) do |f| File.open(dotfile_path) do |f|
@vm = Vagrant::VM.find(f.read, self) data = { DEFAULT_VM => f.read }
begin
data = JSON.parse(data[DEFAULT_VM])
rescue JSON::ParserError
# Most likely an older (<= 0.3.x) dotfile. Try to load it
# as the :__vagrant VM.
end
data.each do |key, value|
key = key.to_sym
vms[key] = Vagrant::VM.find(value, self, key)
end
end end
rescue Errno::ENOENT rescue Errno::ENOENT
@vm = nil # Just rescue it.
end end
# Loads/initializes the SSH object # Loads blank VMs into the `vms` attribute.
def load_ssh! def load_blank_vms!
@ssh = SSH.new(self) # Clear existing vms
vms.clear
# Load up the blank VMs
defined_vms = config.vm.defined_vms.keys
defined_vms = [DEFAULT_VM] if defined_vms.empty?
defined_vms.each do |name|
vms[name] = Vagrant::VM.new(:vm_name => name, :env => self)
end
end end
# Loads the activelist for this environment # Loads the activelist for this environment
@ -201,32 +272,27 @@ module Vagrant
# Methods to manage VM # Methods to manage VM
#--------------------------------------------------------------- #---------------------------------------------------------------
# Sets the VM to a new VM. This is not too useful but is used
# in {Command.up}. This will very likely be refactored at a later
# time.
def create_vm
@vm = VM.new(self)
end
# Persists this environment's VM to the dotfile so it can be # Persists this environment's VM to the dotfile so it can be
# re-loaded at a later time. # re-loaded at a later time.
def persist_vm def update_dotfile
# Save to the dotfile for this project if parent
parent.update_dotfile
return
end
# Generate and save the persisted VM info
data = vms.inject({}) do |acc, data|
key, value = data
acc[key] = value.uuid if value.created?
acc
end
File.open(dotfile_path, 'w+') do |f| File.open(dotfile_path, 'w+') do |f|
f.write(vm.uuid) f.write(data.to_json)
end end
# Also add to the global store # Also add to the global store
active_list.add(vm) # active_list.add(vm)
end
# Removes this environment's VM from the dotfile.
def depersist_vm
# Delete the dotfile if it exists
File.delete(dotfile_path) if File.exist?(dotfile_path)
# Remove from the global store
active_list.remove(vm)
end end
#--------------------------------------------------------------- #---------------------------------------------------------------

View File

@ -7,11 +7,19 @@ module Vagrant
class Base class Base
include Vagrant::Util include Vagrant::Util
# The environment which this is being provisioned in # The VM which this is being provisioned for
attr_reader :env attr_reader :vm
def initialize(env) def initialize(vm)
@env = env @vm = vm
end
# This method returns the environment which the provisioner is working
# on. This is also the environment of the VM. This method is provided
# as a simple helper since the environment is often used throughout the
# provisioner.
def env
@vm.env
end end
# This is the method called to "prepare" the provisioner. This is called # This is the method called to "prepare" the provisioner. This is called

View File

@ -77,7 +77,7 @@ module Vagrant
def chown_provisioning_folder def chown_provisioning_folder
logger.info "Setting permissions on chef provisioning folder..." logger.info "Setting permissions on chef provisioning folder..."
env.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("sudo mkdir -p #{env.config.chef.provisioning_path}") ssh.exec!("sudo mkdir -p #{env.config.chef.provisioning_path}")
ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.chef.provisioning_path}") ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.chef.provisioning_path}")
end end
@ -89,7 +89,7 @@ module Vagrant
}.merge(template_vars)) }.merge(template_vars))
logger.info "Uploading chef configuration script..." logger.info "Uploading chef configuration script..."
env.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename)) vm.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename))
end end
def setup_json def setup_json
@ -110,7 +110,7 @@ module Vagrant
json = data.to_json json = data.to_json
env.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json")) vm.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json"))
end end
end end
end end

View File

@ -28,14 +28,14 @@ module Vagrant
logger.info "Creating folder to hold client key..." logger.info "Creating folder to hold client key..."
path = Pathname.new(env.config.chef.client_key_path) path = Pathname.new(env.config.chef.client_key_path)
env.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("sudo mkdir -p #{path.dirname}") ssh.exec!("sudo mkdir -p #{path.dirname}")
end end
end end
def upload_validation_key def upload_validation_key
logger.info "Uploading chef client validation key..." logger.info "Uploading chef client validation key..."
env.ssh.upload!(validation_key_path, guest_validation_key_path) vm.ssh.upload!(validation_key_path, guest_validation_key_path)
end end
def setup_server_config def setup_server_config
@ -50,7 +50,7 @@ module Vagrant
def run_chef_client def run_chef_client
logger.info "Running chef-client..." logger.info "Running chef-client..."
env.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json") do |channel, data, stream| ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json") do |channel, data, stream|
# TODO: Very verbose. It would be easier to save the data and only show it during # TODO: Very verbose. It would be easier to save the data and only show it during
# an error, or when verbosity level is set high # an error, or when verbosity level is set high
@ -64,7 +64,7 @@ module Vagrant
end end
def guest_validation_key_path def guest_validation_key_path
File.join(@env.config.chef.provisioning_path, "validation.pem") File.join(env.config.chef.provisioning_path, "validation.pem")
end end
end end
end end

View File

@ -36,7 +36,7 @@ module Vagrant
def run_chef_solo def run_chef_solo
logger.info "Running chef-solo..." logger.info "Running chef-solo..."
env.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream| ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
# TODO: Very verbose. It would be easier to save the data and only show it during # TODO: Very verbose. It would be easier to save the data and only show it during
# an error, or when verbosity level is set high # an error, or when verbosity level is set high

View File

@ -30,7 +30,7 @@ module Vagrant
#------------------------------------------------------------------- #-------------------------------------------------------------------
def halt def halt
logger.info "Attempting graceful shutdown of linux..." logger.info "Attempting graceful shutdown of linux..."
vm.env.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("sudo halt") ssh.exec!("sudo halt")
end end

View File

@ -4,25 +4,51 @@ module Vagrant
attr_reader :env attr_reader :env
attr_reader :system attr_reader :system
attr_reader :name
attr_accessor :vm attr_accessor :vm
class << self class << self
# Finds a virtual machine by a given UUID and either returns # Finds a virtual machine by a given UUID and either returns
# a Vagrant::VM object or returns nil. # a Vagrant::VM object or returns nil.
def find(uuid, env=nil) def find(uuid, env=nil, vm_name=nil)
vm = VirtualBox::VM.find(uuid) vm = VirtualBox::VM.find(uuid)
return nil if vm.nil? new(:vm => vm, :env => env, :vm_name => vm_name)
new(env, vm)
end end
end end
def initialize(env, vm=nil) def initialize(opts=nil)
@env = env defaults = {
@vm = vm :vm => nil,
:env => nil,
:vm_name => nil
}
load_system! unless @env.nil? opts = defaults.merge(opts || {})
@vm = opts[:vm]
@name = opts[:vm_name]
if !opts[:env].nil?
# We have an environment, so we create a new child environment
# specifically for this VM. This step will load any custom
# config and such.
@env = Vagrant::Environment.new({
:cwd => opts[:env].cwd,
:parent => opts[:env],
:vm_name => opts[:vm_name],
:vm => self
}).load!
# Load the associated system.
load_system!
end
end end
# Loads the system associated with the VM. The system class is
# responsible for OS-specific functionality. More information
# can be found by reading the documentation on {Vagrant::Systems::Base}.
#
# **This method should never be called manually.**
def load_system! def load_system!
system = env.config.vm.system system = env.config.vm.system
@ -31,9 +57,7 @@ module Vagrant
error_and_exit(:system_invalid_class, :system => system.to_s) unless @system.is_a?(Systems::Base) error_and_exit(:system_invalid_class, :system => system.to_s) unless @system.is_a?(Systems::Base)
elsif system.is_a?(Symbol) elsif system.is_a?(Symbol)
# Hard-coded internal systems # Hard-coded internal systems
mapping = { mapping = { :linux => Systems::Linux }
:linux => Systems::Linux
}
if !mapping.has_key?(system) if !mapping.has_key?(system)
error_and_exit(:system_unknown_type, :system => system.to_s) error_and_exit(:system_unknown_type, :system => system.to_s)
@ -46,6 +70,21 @@ module Vagrant
end end
end end
# Access the {Vagrant::SSH} object associated with this VM.
# On the initial call, this will initialize the object. On
# subsequent calls it will reuse the existing object.
def ssh
@ssh ||= SSH.new(env)
end
# Returns a boolean true if the VM has been created, otherwise
# returns false.
#
# @return [Boolean]
def created?
!vm.nil?
end
def uuid def uuid
vm ? vm.uuid : nil vm ? vm.uuid : nil
end end
@ -60,12 +99,24 @@ module Vagrant
execute! execute!
end end
def up
execute!(Actions::VM::Up)
end
def start def start
return if @vm.running? return if @vm.running?
execute!(Actions::VM::Start) execute!(Actions::VM::Start)
end end
def halt(force=false)
execute!(Actions::VM::Halt, force)
end
def reload
execute!(Actions::VM::Reload)
end
def destroy def destroy
execute!(Actions::VM::Down) execute!(Actions::VM::Down)
end end

View File

@ -6,6 +6,10 @@
#--------------------------------------------------------------------- #---------------------------------------------------------------------
# CATEGORY: Status Messages # CATEGORY: Status Messages
#--------------------------------------------------------------------- #---------------------------------------------------------------------
:status_listing: |-
This environment represents multiple VMs. The VMs will be listed
below with a short status. For more detailed information about a
VM, run `vagrant status NAME`.
:status_no_environment: |- :status_no_environment: |-
No vagrant environment detected. Run `vagrant init` to setup a Vagrantfile No vagrant environment detected. Run `vagrant init` to setup a Vagrantfile
in the current directory to get started with Vagrant. in the current directory to get started with Vagrant.
@ -104,6 +108,11 @@
<%= Vagrant::Environment::ROOTFILE_NAME %> and running `vagrant up` <%= Vagrant::Environment::ROOTFILE_NAME %> and running `vagrant up`
:package_include_file_doesnt_exist: |- :package_include_file_doesnt_exist: |-
File specified to include: '<%= filename %>' does not exist! File specified to include: '<%= filename %>' does not exist!
:package_multivm: |-
Because this Vagrant environment represents multiple VMs, a
specific VM must be specified. This can be done by calling
`vagrant package NAME` where NAME is a valid VM represented by
your Vagrantfile.
:package_requires_export: |- :package_requires_export: |-
Package must be used in conjunction with export. Package must be used in conjunction with export.
:provisioner_invalid_class: |- :provisioner_invalid_class: |-
@ -139,6 +148,16 @@
For a more detailed guide please consult: For a more detailed guide please consult:
http://vagrantup.com/docs/getting-started/windows.html http://vagrantup.com/docs/getting-started/windows.html
:ssh_multivm: |-
Because this Vagrant environment represents multiple VMs, a
specific VM must be specified. This can be done by calling
`vagrant ssh NAME` where NAME is a valid VM represented by
your Vagrantfile.
:ssh_config_multivm: |-
Because this Vagrant environment represents multiple VMs, a
specific VM must be specified. This can be done by calling
`vagrant ssh-config NAME` where NAME is a valid VM represented by
your Vagrantfile.
:system_invalid_class: |- :system_invalid_class: |-
The specified system does not inherit from `Vagrant::Systems::Base`. The The specified system does not inherit from `Vagrant::Systems::Base`. The
specified system class must inherit from this class. specified system class must inherit from this class.
@ -150,6 +169,8 @@
:system_unspecified: |- :system_unspecified: |-
A VM system type must be specified! This is done via the `config.vm.system` A VM system type must be specified! This is done via the `config.vm.system`
configuration value. Please read the documentation online for more information. configuration value. Please read the documentation online for more information.
:unknown_vm: |-
The specified VM could not be found: <%= vm %>
:virtualbox_import_failure: |- :virtualbox_import_failure: |-
The VM import failed! Try running `VBoxManage import` on the box file The VM import failed! Try running `VBoxManage import` on the box file
manually for more verbose error output. manually for more verbose error output.

View File

@ -73,6 +73,15 @@ class Test::Unit::TestCase
environment environment
end end
# Sets up the mocks for a VM
def mock_vm(env=nil)
env ||= mock_environment
vm = Vagrant::VM.new
vm.stubs(:env).returns(env)
vm.stubs(:ssh).returns(Vagrant::SSH.new(vm.env))
vm
end
# Sets up the mocks and instantiates an action for testing # Sets up the mocks and instantiates an action for testing
def mock_action(action_klass, *args) def mock_action(action_klass, *args)
vm = mock("vboxvm") vm = mock("vboxvm")
@ -87,6 +96,11 @@ class Test::Unit::TestCase
mock_vm.stubs(:actions).returns([action]) mock_vm.stubs(:actions).returns([action])
mock_vm.stubs(:env).returns(mock_environment) mock_vm.stubs(:env).returns(mock_environment)
mock_ssh = Vagrant::SSH.new(mock_vm.env)
mock_ssh.stubs(:execute)
mock_vm.stubs(:ssh).returns(mock_ssh)
vm.stubs(:env).returns(mock_vm.env) vm.stubs(:env).returns(mock_vm.env)
[mock_vm, vm, action] [mock_vm, vm, action]

View File

@ -43,13 +43,13 @@ class BootActionTest < Test::Unit::TestCase
context "waiting for boot" do context "waiting for boot" do
should "repeatedly ping the SSH port and return false with no response" do should "repeatedly ping the SSH port and return false with no response" do
seq = sequence('pings') seq = sequence('pings')
@runner.env.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i - 1).returns(false).in_sequence(seq) @runner.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i - 1).returns(false).in_sequence(seq)
@runner.env.ssh.expects(:up?).once.returns(true).in_sequence(seq) @runner.ssh.expects(:up?).once.returns(true).in_sequence(seq)
assert @action.wait_for_boot(0) assert @action.wait_for_boot(0)
end end
should "ping the max number of times then just return" do should "ping the max number of times then just return" do
@runner.env.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i).returns(false) @runner.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i).returns(false)
assert !@action.wait_for_boot(0) assert !@action.wait_for_boot(0)
end end
end end

View File

@ -15,7 +15,7 @@ class DestroyActionTest < Test::Unit::TestCase
@runner.stubs(:invoke_around_callback).yields @runner.stubs(:invoke_around_callback).yields
clear_seq = sequence("clear") clear_seq = sequence("clear")
@action.expects(:destroy_vm).in_sequence(clear_seq) @action.expects(:destroy_vm).in_sequence(clear_seq)
@action.expects(:depersist).in_sequence(clear_seq) @action.expects(:update_dotfile).in_sequence(clear_seq)
@action.execute! @action.execute!
end end
end end
@ -23,14 +23,15 @@ class DestroyActionTest < Test::Unit::TestCase
context "destroying the VM" do context "destroying the VM" do
should "destroy VM and attached images" do should "destroy VM and attached images" do
@vm.expects(:destroy).with(:destroy_medium => :delete).once @vm.expects(:destroy).with(:destroy_medium => :delete).once
@runner.expects(:vm=).with(nil).once
@action.destroy_vm @action.destroy_vm
end end
end end
context "depersisting" do context "updating the dotfile" do
should "call depersist_vm on Env" do should "update the environment dotfile" do
@runner.env.expects(:depersist_vm).once @runner.env.expects(:update_dotfile).once
@action.depersist @action.update_dotfile
end end
end end
end end

View File

@ -3,6 +3,7 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
class ExportActionTest < Test::Unit::TestCase class ExportActionTest < Test::Unit::TestCase
setup do setup do
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Export) @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Export)
@action.stubs(:complete_progress)
end end
context "executing" do context "executing" do

View File

@ -10,6 +10,8 @@ class ImportActionTest < Test::Unit::TestCase
@runner.env.stubs(:box).returns(@box) @runner.env.stubs(:box).returns(@box)
VirtualBox::VM.stubs(:import) VirtualBox::VM.stubs(:import)
@import.stubs(:complete_progress)
end end
should "run in a busy block" do should "run in a busy block" do

View File

@ -99,7 +99,7 @@ class SharedFoldersActionTest < Test::Unit::TestCase
@folders.each do |name, hostpath, guestpath| @folders.each do |name, hostpath, guestpath|
@runner.system.expects(:mount_shared_folder).with(ssh, name, guestpath).in_sequence(mount_seq) @runner.system.expects(:mount_shared_folder).with(ssh, name, guestpath).in_sequence(mount_seq)
end end
@runner.env.ssh.expects(:execute).yields(ssh) @runner.ssh.expects(:execute).yields(ssh)
@action.after_boot @action.after_boot
end end

View File

@ -63,19 +63,19 @@ class UpActionTest < Test::Unit::TestCase
end end
context "callbacks" do context "callbacks" do
should "call persist and mac address setup after import" do should "call update dotfile and mac address setup after import" do
boot_seq = sequence("boot") boot_seq = sequence("boot")
@action.expects(:persist).once.in_sequence(boot_seq) @action.expects(:update_dotfile).once.in_sequence(boot_seq)
@action.expects(:setup_mac_address).once.in_sequence(boot_seq) @action.expects(:setup_mac_address).once.in_sequence(boot_seq)
@action.after_import @action.after_import
end end
end end
context "persisting" do context "updating the dotfile" do
should "persist the VM with Env" do should "call update dotfile on the VM's environment" do
@runner.stubs(:uuid) @runner.stubs(:uuid)
@runner.env.expects(:persist_vm).once @runner.env.expects(:update_dotfile).once
@action.persist @action.update_dotfile
end end
end end

View File

@ -112,8 +112,9 @@ class CommandsBaseTest < Test::Unit::TestCase
end end
should "parse the options with the args" do should "parse the options with the args" do
@option_parser.expects(:parse!).with(@args).once result = mock("result")
assert_equal @options, @instance.parse_options(@args) @option_parser.expects(:parse!).with(@args).once.returns(result)
assert_equal result, @instance.parse_options(@args)
end end
end end
end end

View File

@ -4,29 +4,58 @@ class CommandsDestroyTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Destroy @klass = Vagrant::Commands::Destroy
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "call destroy_all if no name is given" do
@instance.expects(:destroy_all).once
@instance.execute
end
should "call destroy_single if a name is given" do
@instance.expects(:destroy_single).with("foo").once
@instance.execute(["foo"])
end
end
context "destroying all" do
should "destroy each VM" do
vms = { :foo => nil, :bar => nil, :baz => nil }
@env.stubs(:vms).returns(vms)
vms.each do |name, value|
@instance.expects(:destroy_single).with(name).once
end
@instance.destroy_all
end
end
context "destroying a single VM" do
setup do setup do
@persisted_vm.stubs(:destroy) @foo_vm = mock("vm")
vms = { :foo => @foo_vm }
@env.stubs(:vms).returns(vms)
end
should "error and exit if the VM doesn't exist" do
@env.stubs(:vms).returns({})
@instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.destroy_single(:foo)
end end
should "require a persisted VM" do should "destroy if its created" do
@env.expects(:require_persisted_vm).once @foo_vm.stubs(:created?).returns(true)
@instance.execute @foo_vm.expects(:destroy).once
@instance.destroy_single(:foo)
end end
should "destroy the persisted VM and the VM image" do should "do nothing if its not created" do
@persisted_vm.expects(:destroy).once @foo_vm.stubs(:created?).returns(false)
@instance.execute @foo_vm.expects(:destroy).never
@instance.destroy_single(:foo)
end end
end end
end end

View File

@ -4,32 +4,64 @@ class CommandsHaltTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Halt @klass = Vagrant::Commands::Halt
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "require a persisted VM" do should "call halt_all if no name is given" do
@env.expects(:require_persisted_vm).once @instance.expects(:halt_all).once
@instance.execute @instance.execute
end end
should "call the `halt` action on the VM" do should "call halt_single if a name is given" do
@persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, false).once @instance.expects(:halt_single).with("foo").once
@instance.execute @instance.execute(["foo"])
end
end end
should "be forceful if -f flag is sent" do context "halting all" do
%w{--force -f}.each do |flag| should "halt each VM" do
@persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, true).once vms = { :foo => nil, :bar => nil, :baz => nil }
@instance.execute([flag]) @env.stubs(:vms).returns(vms)
vms.each do |name, value|
@instance.expects(:halt_single).with(name).once
end end
@instance.halt_all
end
end
context "halting a single VM" do
setup do
@foo_vm = mock("vm")
vms = { :foo => @foo_vm }
@env.stubs(:vms).returns(vms)
end
should "error and exit if the VM doesn't exist" do
@env.stubs(:vms).returns({})
@instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.halt_single(:foo)
end
should "halt if its created" do
@foo_vm.stubs(:created?).returns(true)
@foo_vm.expects(:halt).with(false).once
@instance.execute(["foo"])
end
should "halt and force if specified" do
@foo_vm.stubs(:created?).returns(true)
@foo_vm.expects(:halt).with(true).once
@instance.execute(["foo", "--force"])
end
should "do nothing if its not created" do
@foo_vm.stubs(:created?).returns(false)
@foo_vm.expects(:halt).never
@instance.halt_single(:foo)
end end
end end
end end

View File

@ -4,81 +4,102 @@ class CommandsPackageTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Package @klass = Vagrant::Commands::Package
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
setup do should "package base if a base is given" do
@persisted_vm.stubs(:package) @instance.expects(:package_base).once
@persisted_vm.stubs(:powered_off?).returns(true) @instance.execute(["--base","foo"])
end end
context "with no base specified" do should "package single if no name is given" do
should "require a persisted vm" do @instance.expects(:package_single).with(nil).once
@env.expects(:require_persisted_vm).once
@instance.execute @instance.execute
end end
should "package single if a name is given" do
@instance.expects(:package_single).with("foo").once
@instance.execute(["foo"])
end
end end
context "with base specified" do context "packaging base" do
should "error and exit if no VM is found" do
Vagrant::VM.expects(:find).with("foo").returns(nil)
@instance.expects(:error_and_exit).with(:vm_base_not_found, :name => "foo").once
@instance.execute(["--base", "foo"])
end
should "package the VM like any other VM" do
vm = mock("vm")
Vagrant::VM.expects(:find).with("foo").returns(vm)
vm.expects(:env=).with(@env).once
@instance.expects(:package_vm).with(vm).once
@instance.execute(["--base", "foo"])
end
end
context "packaging a single VM" do
setup do setup do
@vm = mock("vm") @vm = mock("vm")
@vm.stubs(:created?).returns(true)
Vagrant::VM.stubs(:find).with(@name).returns(@vm) @vms = {:bar => @vm}
@vm.stubs(:env=).with(@env) @env.stubs(:vms).returns(@vms)
@env.stubs(:vm=) @env.stubs(:multivm?).returns(false)
@name = "bar"
end end
should "find the given base and set it on the env" do should "error and exit if no name is given in a multi-vm env" do
Vagrant::VM.expects(:find).with(@name).returns(@vm) @env.stubs(:multivm?).returns(true)
@vm.expects(:env=).with(@env) @instance.expects(:error_and_exit).with(:package_multivm).once
@env.expects(:vm=).with(@vm) @instance.package_single(nil)
@instance.execute(["foo", "--base", @name])
end end
should "error if the VM is not found" do should "error and exit if the VM doesn't exist" do
Vagrant::VM.expects(:find).with(@name).returns(nil) @instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.expects(:error_and_exit).with(:vm_base_not_found, :name => @name).once @instance.package_single(:foo)
end
@instance.execute(["foo", "--base", @name]) should "error and exit if the VM is not created" do
@vm.stubs(:created?).returns(false)
@instance.expects(:error_and_exit).with(:environment_not_created).once
@instance.package_single(:bar)
end
should "use the first VM is no name is given in a single VM environment" do
@instance.expects(:package_vm).with(@vm).once
@instance.package_single(nil)
end
should "package the VM" do
@instance.expects(:package_vm).with(@vm).once
@instance.package_single(:bar)
end end
end end
context "shared (with and without base specified)" do context "packaging a VM" do
should "error and exit if the VM is not powered off" do setup do
@persisted_vm.stubs(:powered_off?).returns(false) @vm = mock("vm")
@vm.stubs(:powered_off?).returns(true)
@options = {}
@instance.stubs(:options).returns(@options)
end
should "error and exit if VM is not powered off" do
@vm.stubs(:powered_off?).returns(false)
@instance.expects(:error_and_exit).with(:vm_power_off_to_package).once @instance.expects(:error_and_exit).with(:vm_power_off_to_package).once
@persisted_vm.expects(:package).never @instance.package_vm(@vm)
@instance.execute
end end
should "call package on the persisted VM" do should "package the VM with the proper arguments" do
@persisted_vm.expects(:package).once @options[:output] = "foo.box"
@instance.execute @options[:include] = :bar
end
should "pass the out path and include_files to the package method" do @vm.expects(:package).with(@options[:output], @options[:include]).once
out_path = mock("out_path") @instance.package_vm(@vm)
include_files = "foo"
@persisted_vm.expects(:package).with(out_path, [include_files]).once
@instance.execute([out_path, "--include", include_files])
end
should "default to an empty array when not include_files are specified" do
out_path = mock("out_path")
@persisted_vm.expects(:package).with(out_path, []).once
@instance.execute([out_path])
end
end end
end end
end end

View File

@ -4,25 +4,58 @@ class CommandsReloadTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Reload @klass = Vagrant::Commands::Reload
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "require a persisted VM" do should "call on all if no name is given" do
@env.expects(:require_persisted_vm).once @instance.expects(:reload_all).once
@instance.execute @instance.execute
end end
should "call the `reload` action on the VM" do should "call on single if a name is given" do
@persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Reload).once @instance.expects(:reload_single).with("foo").once
@instance.execute @instance.execute(["foo"])
end
end
context "reloading all" do
should "reload each VM" do
vms = { :foo => nil, :bar => nil, :baz => nil }
@env.stubs(:vms).returns(vms)
vms.each do |name, value|
@instance.expects(:reload_single).with(name).once
end
@instance.reload_all
end
end
context "reloading a single VM" do
setup do
@foo_vm = mock("vm")
vms = { :foo => @foo_vm }
@env.stubs(:vms).returns(vms)
end
should "error and exit if the VM doesn't exist" do
@env.stubs(:vms).returns({})
@instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.reload_single(:foo)
end
should "reload if its created" do
@foo_vm.stubs(:created?).returns(true)
@foo_vm.expects(:reload).once
@instance.execute(["foo"])
end
should "do nothing if its not created" do
@foo_vm.stubs(:created?).returns(false)
@foo_vm.expects(:reload).never
@instance.reload_single(:foo)
end end
end end
end end

View File

@ -4,30 +4,58 @@ class CommandsResumeTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Resume @klass = Vagrant::Commands::Resume
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "call on all if no name is given" do
@instance.expects(:resume_all).once
@instance.execute
end
should "call on single if a name is given" do
@instance.expects(:resume_single).with("foo").once
@instance.execute(["foo"])
end
end
context "resume all" do
should "resume each VM" do
vms = { :foo => nil, :bar => nil, :baz => nil }
@env.stubs(:vms).returns(vms)
vms.each do |name, value|
@instance.expects(:resume_single).with(name).once
end
@instance.resume_all
end
end
context "resuming a single VM" do
setup do setup do
@persisted_vm.stubs(:resume) @foo_vm = mock("vm")
@persisted_vm.stubs(:saved?).returns(true) vms = { :foo => @foo_vm }
@env.stubs(:vms).returns(vms)
end end
should "require a persisted VM" do should "error and exit if the VM doesn't exist" do
@env.expects(:require_persisted_vm).once @env.stubs(:vms).returns({})
@instance.execute @instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.resume_single(:foo)
end end
should "save the state of the VM" do should "resume if its created" do
@persisted_vm.expects(:resume).once @foo_vm.stubs(:created?).returns(true)
@instance.execute @foo_vm.expects(:resume).once
@instance.execute(["foo"])
end
should "do nothing if its not created" do
@foo_vm.stubs(:created?).returns(false)
@foo_vm.expects(:resume).never
@instance.resume_single(:foo)
end end
end end
end end

View File

@ -4,31 +4,14 @@ class CommandsSSHConfigTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::SSHConfig @klass = Vagrant::Commands::SSHConfig
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm) @env.stubs(:require_root_path)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
setup do setup do
@ssh = mock("ssh") @instance.stubs(:show_single)
@ssh.stubs(:port).returns(2197)
@env.stubs(:ssh).returns(@ssh)
@env.stubs(:require_root_path)
@instance.stubs(:puts)
@data = {
:host_key => "vagrant",
:ssh_user => @env.config.ssh.username,
:ssh_port => @env.ssh.port,
:private_key_path => @env.config.ssh.private_key_path
}
end end
should "require root path" do should "require root path" do
@ -36,19 +19,59 @@ class CommandsSSHConfigTest < Test::Unit::TestCase
@instance.execute @instance.execute
end end
should "call show_single with given argument" do
@instance.expects(:show_single).with("foo").once
@instance.execute(["foo"])
end
end
context "showing a single entry" do
setup do
@ssh = mock("ssh")
@ssh.stubs(:port).returns(2197)
@bar = mock("vm")
@bar.stubs(:env).returns(mock_environment)
@bar.stubs(:ssh).returns(@ssh)
@vms = {:bar => @bar}
@env.stubs(:multivm?).returns(true)
@env.stubs(:vms).returns(@vms)
@data = {
:host_key => "vagrant",
:ssh_user => @bar.env.config.ssh.username,
:ssh_port => @bar.ssh.port,
:private_key_path => @bar.env.config.ssh.private_key_path
}
@instance.stubs(:puts)
end
should "error if name is nil and multivm" do
@env.stubs(:multivm?).returns(true)
@instance.expects(:error_and_exit).with(:ssh_config_multivm).once
@instance.show_single(nil)
end
should "error if the VM is not found" do
@instance.expects(:error_and_exit).with(:unknown_vm, :vm => "foo").once
@instance.show_single("foo")
end
should "output rendered template" do should "output rendered template" do
result = mock("result") result = mock("result")
Vagrant::Util::TemplateRenderer.expects(:render).with("ssh_config", @data).returns(result) Vagrant::Util::TemplateRenderer.expects(:render).with("ssh_config", @data).returns(result)
@instance.expects(:puts).with(result).once @instance.expects(:puts).with(result).once
@instance.execute @instance.show_single(:bar)
end end
should "render with the given host name if given" do should "render with the given host name if given" do
host = "foo" host = "foo"
@data[:host_key] = host @data[:host_key] = host
Vagrant::Util::TemplateRenderer.expects(:render).with("ssh_config", @data) Vagrant::Util::TemplateRenderer.expects(:render).with("ssh_config", @data)
@instance.execute(["--host", host]) @instance.execute(["bar", "--host", host])
end end
end end
end end

View File

@ -4,29 +4,55 @@ class CommandsSSHTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::SSH @klass = Vagrant::Commands::SSH
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "connect to the given argument" do
@instance.expects(:ssh_connect).with("foo").once
@instance.execute(["foo"])
end
should "connect with nil name if none is given" do
@instance.expects(:ssh_connect).with(nil).once
@instance.execute
end
end
context "ssh connecting" do
setup do setup do
@env.ssh.stubs(:connect) @vm = mock("vm")
@vm.stubs(:created?).returns(true)
@vms = {:bar => @vm}
@env.stubs(:vms).returns(@vms)
@env.stubs(:multivm?).returns(false)
end end
should "require a persisted VM" do should "error and exit if no VM is specified and multivm" do
@env.expects(:require_persisted_vm).once @env.stubs(:multivm?).returns(true)
@instance.execute @instance.expects(:error_and_exit).with(:ssh_multivm).once
@instance.ssh_connect(nil)
end end
should "connect to SSH" do should "error and exit if VM is nil" do
@env.ssh.expects(:connect).once @instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.execute @instance.ssh_connect(:foo)
end
should "error and exit if VM isn't created" do
@vm.stubs(:created?).returns(false)
@instance.expects(:error_and_exit).with(:environment_not_created).once
@instance.ssh_connect(:bar)
end
should "ssh connect" do
ssh = mock("ssh")
@vm.stubs(:ssh).returns(ssh)
ssh.expects(:connect)
@instance.ssh_connect(:bar)
end end
end end
end end

View File

@ -26,5 +26,15 @@ class CommandsStatusTest < Test::Unit::TestCase
@instance.expects(:show_global_status).once @instance.expects(:show_global_status).once
@instance.execute(["--global"]) @instance.execute(["--global"])
end end
should "show help if too many args are given" do
@instance.expects(:show_help).once
@instance.execute(["1","2","3"])
end
should "pass the VM name to local status if given" do
@instance.expects(:show_local_status).with("foo").once
@instance.execute(["foo"])
end
end end
end end

View File

@ -4,30 +4,58 @@ class CommandsSuspendTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Commands::Suspend @klass = Vagrant::Commands::Suspend
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
@env = mock_environment @env = mock_environment
@env.stubs(:require_persisted_vm)
@env.stubs(:vm).returns(@persisted_vm)
@instance = @klass.new(@env) @instance = @klass.new(@env)
end end
context "executing" do context "executing" do
should "call on all if no name is given" do
@instance.expects(:suspend_all).once
@instance.execute
end
should "call on single if a name is given" do
@instance.expects(:suspend_single).with("foo").once
@instance.execute(["foo"])
end
end
context "suspending all" do
should "suspend each VM" do
vms = { :foo => nil, :bar => nil, :baz => nil }
@env.stubs(:vms).returns(vms)
vms.each do |name, value|
@instance.expects(:suspend_single).with(name).once
end
@instance.suspend_all
end
end
context "suspending a single VM" do
setup do setup do
@persisted_vm.stubs(:suspend) @foo_vm = mock("vm")
@persisted_vm.stubs(:saved?).returns(false) vms = { :foo => @foo_vm }
@env.stubs(:vms).returns(vms)
end end
should "require a persisted VM" do should "error and exit if the VM doesn't exist" do
@env.expects(:require_persisted_vm).once @env.stubs(:vms).returns({})
@instance.execute @instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.suspend_single(:foo)
end end
should "suspend the VM" do should "suspend if its created" do
@persisted_vm.expects(:suspend).once @foo_vm.stubs(:created?).returns(true)
@instance.execute @foo_vm.expects(:suspend).once
@instance.execute(["foo"])
end
should "do nothing if its not created" do
@foo_vm.stubs(:created?).returns(false)
@foo_vm.expects(:suspend).never
@instance.suspend_single(:foo)
end end
end end
end end

View File

@ -6,36 +6,73 @@ class CommandsUpTest < Test::Unit::TestCase
@env = mock_environment @env = mock_environment
@instance = @klass.new(@env) @instance = @klass.new(@env)
@persisted_vm = mock("persisted_vm")
@persisted_vm.stubs(:execute!)
end end
context "executing" do context "executing" do
should "call up_all if no name is given" do
@instance.expects(:up_all).once
@instance.execute
end
should "call up_single if a name is given" do
@instance.expects(:up_single).with("foo").once
@instance.execute(["foo"])
end
end
context "upping a single VM" do
setup do setup do
@new_vm = mock("vm") @vm = mock("vm")
@new_vm.stubs(:execute!) @vm.stubs(:env).returns(@env)
@env.stubs(:vm).returns(nil) @vms = {:foo => @vm}
@env.stubs(:require_box) @env.stubs(:vms).returns(@vms)
@env.stubs(:create_vm).returns(@new_vm)
end end
should "require a box" do should "error and exit if the VM doesn't exist" do
@env.expects(:require_box).once @env.stubs(:vms).returns({})
@instance.execute @instance.expects(:error_and_exit).with(:unknown_vm, :vm => :foo).once
@instance.up_single(:foo)
end end
should "call the up action on VM if it doesn't exist" do should "start created VMs" do
@new_vm.expects(:execute!).with(Vagrant::Actions::VM::Up).once @vm.stubs(:created?).returns(true)
@instance.execute @vm.expects(:start).once
@instance.up_single(:foo)
end end
should "call start on the persisted vm if it exists" do should "up non-created VMs" do
@env.stubs(:vm).returns(@persisted_vm) @vm.stubs(:created?).returns(false)
@persisted_vm.expects(:start).once @vm.env.expects(:require_box).once
@env.expects(:create_vm).never @vm.expects(:up).once
@instance.execute @vm.expects(:start).never
@instance.up_single(:foo)
end
end
context "upping all VMs" do
setup do
@vms = {}
@env.stubs(:vms).returns(@vms)
end
def create_vm
vm = mock("vm")
vm.stubs(:env).returns(mock_environment)
vm.stubs(:created?).returns(false)
vm
end
should "require a box for all VMs" do
@vms[:foo] = create_vm
@vms[:bar] = create_vm
@vms.each do |name, vm|
vm.env.expects(:require_box).once
@instance.expects(:up_single).with(name).once
end
@instance.up_all
end end
end end
end end

View File

@ -52,17 +52,6 @@ class ConfigTest < Test::Unit::TestCase
end end
end end
context "accessing configuration" do
setup do
Vagrant::Config.run { |config| }
Vagrant::Config.execute!
end
should "forward config to the class method" do
assert_equal Vagrant.config, Vagrant::Config.config
end
end
context "initializing" do context "initializing" do
setup do setup do
Vagrant::Config.reset! Vagrant::Config.reset!
@ -92,7 +81,14 @@ class ConfigTest < Test::Unit::TestCase
should "return the configuration on execute!" do should "return the configuration on execute!" do
Vagrant::Config.run {} Vagrant::Config.run {}
result = Vagrant::Config.execute! result = Vagrant::Config.execute!
assert result.equal?(Vagrant.config) assert result.is_a?(Vagrant::Config::Top)
end
should "use given configuration object if given" do
fake_env = mock("env")
config = Vagrant::Config::Top.new(fake_env)
result = Vagrant::Config.execute!(config)
assert_equal config.env, result.env
end end
end end
@ -229,6 +225,27 @@ class ConfigTest < Test::Unit::TestCase
@env.config.ssh.username = @username @env.config.ssh.username = @username
end end
context "defining VMs" do
should "store the proc by name but not run it" do
foo = mock("proc")
foo.expects(:call).never
proc = Proc.new { foo.call }
@config.define(:name, &proc)
assert_equal proc, @config.defined_vms[:name]
end
should "not have multi-VMs by default" do
assert !@config.has_multi_vms?
end
should "have multi-VMs once one is specified" do
@config.define(:foo) {}
assert @config.has_multi_vms?
end
end
context "customizing" do
should "include the stacked proc runner module" do should "include the stacked proc runner module" do
assert @config.class.included_modules.include?(Vagrant::Util::StackedProcRunner) assert @config.class.included_modules.include?(Vagrant::Util::StackedProcRunner)
end end
@ -238,6 +255,7 @@ class ConfigTest < Test::Unit::TestCase
@config.customize(&proc) @config.customize(&proc)
assert_equal [proc], @config.proc_stack assert_equal [proc], @config.proc_stack
end end
end
context "uid/gid" do context "uid/gid" do
should "return the shared folder UID if set" do should "return the shared folder UID if set" do

View File

@ -42,13 +42,13 @@ class EnvironmentTest < Test::Unit::TestCase
end end
should "create the environment with given cwd, load it, and return it" do should "create the environment with given cwd, load it, and return it" do
Vagrant::Environment.expects(:new).with(@cwd).once.returns(@env) Vagrant::Environment.expects(:new).with(:cwd => @cwd).once.returns(@env)
@env.expects(:load!).returns(@env) @env.expects(:load!).returns(@env)
assert_equal @env, Vagrant::Environment.load!(@cwd) assert_equal @env, Vagrant::Environment.load!(@cwd)
end end
should "work without a given cwd" do should "work without a given cwd" do
Vagrant::Environment.expects(:new).with(nil).returns(@env) Vagrant::Environment.expects(:new).with(:cwd => nil).returns(@env)
assert_nothing_raised { assert_nothing_raised {
env = Vagrant::Environment.load! env = Vagrant::Environment.load!
@ -60,7 +60,7 @@ class EnvironmentTest < Test::Unit::TestCase
context "initialization" do context "initialization" do
should "set the cwd if given" do should "set the cwd if given" do
cwd = "foobarbaz" cwd = "foobarbaz"
env = Vagrant::Environment.new(cwd) env = Vagrant::Environment.new(:cwd => cwd)
assert_equal cwd, env.cwd assert_equal cwd, env.cwd
end end
@ -124,6 +124,41 @@ class EnvironmentTest < Test::Unit::TestCase
end end
end end
context "multivm? helper" do
setup do
@env = mock_environment
end
context "with a parent" do
setup do
@parent = mock('parent')
@env.stubs(:parent).returns(@parent)
end
should "return the value of multivm? from the parent" do
result = mock("result")
@parent.stubs(:multivm?).returns(result)
assert_equal result, @env.multivm?
end
end
context "without a parent" do
setup do
@env.stubs(:parent).returns(nil)
end
should "return true if VM length greater than 1" do
@env.stubs(:vms).returns([1,2,3])
assert @env.multivm?
end
should "return false if VM length is 1" do
@env.stubs(:vms).returns([1])
assert !@env.multivm?
end
end
end
context "loading" do context "loading" do
setup do setup do
@env = mock_environment @env = mock_environment
@ -139,7 +174,6 @@ class EnvironmentTest < Test::Unit::TestCase
@env.expects(:load_config!).once.in_sequence(call_seq) @env.expects(:load_config!).once.in_sequence(call_seq)
Vagrant::Environment.expects(:check_virtualbox!).once.in_sequence(call_seq) Vagrant::Environment.expects(:check_virtualbox!).once.in_sequence(call_seq)
@env.expects(:load_vm!).once.in_sequence(call_seq) @env.expects(:load_vm!).once.in_sequence(call_seq)
@env.expects(:load_ssh!).once.in_sequence(call_seq)
@env.expects(:load_active_list!).once.in_sequence(call_seq) @env.expects(:load_active_list!).once.in_sequence(call_seq)
@env.expects(:load_commands!).once.in_sequence(call_seq) @env.expects(:load_commands!).once.in_sequence(call_seq)
assert_equal @env, @env.load! assert_equal @env, @env.load!
@ -216,9 +250,9 @@ class EnvironmentTest < Test::Unit::TestCase
@env.stubs(:root_path).returns(@root_path) @env.stubs(:root_path).returns(@root_path)
@env.stubs(:home_path).returns(@home_path) @env.stubs(:home_path).returns(@home_path)
@parent_env = mock_environment
File.stubs(:exist?).returns(false) File.stubs(:exist?).returns(false)
Vagrant::Config.stubs(:execute!)
Vagrant::Config.stubs(:reset!)
end end
should "reset the configuration object" do should "reset the configuration object" do
@ -268,6 +302,25 @@ class EnvironmentTest < Test::Unit::TestCase
@env.load_config! @env.load_config!
end end
should "load a sub-VM configuration if specified" do
vm_name = :foo
sub_box = :YO
@parent_env.config.vm.box = :NO
@parent_env.config.vm.define(vm_name) do |config|
config.vm.box = sub_box
end
# Sanity
assert_equal :NO, @parent_env.config.vm.box
@env.stubs(:vm_name).returns(vm_name)
@env.stubs(:parent).returns(@parent_env)
@env.load_config!
assert_equal sub_box, @env.config.vm.box
end
should "load the files only if exist? returns true" do should "load the files only if exist? returns true" do
File.expects(:exist?).once.returns(true) File.expects(:exist?).once.returns(true)
@env.expects(:load).once @env.expects(:load).once
@ -354,34 +407,62 @@ class EnvironmentTest < Test::Unit::TestCase
File.stubs(:file?).returns(true) File.stubs(:file?).returns(true)
end end
should "loading of the uuid from the dotfile" do should "blank the VMs" do
load_seq = sequence("load_seq")
@env.stubs(:root_path).returns("foo")
@env.expects(:load_blank_vms!).in_sequence(load_seq)
File.expects(:open).in_sequence(load_seq)
@env.load_vm!
end
should "load the UUID if the JSON parsing fails" do
vm = mock("vm") vm = mock("vm")
filemock = mock("filemock") filemock = mock("filemock")
filemock.expects(:read).returns("foo") filemock.expects(:read).returns("foo")
Vagrant::VM.expects(:find).with("foo", @env).returns(vm) Vagrant::VM.expects(:find).with("foo", @env, Vagrant::Environment::DEFAULT_VM).returns(vm)
File.expects(:open).with(@env.dotfile_path).once.yields(filemock) File.expects(:open).with(@env.dotfile_path).once.yields(filemock)
File.expects(:file?).with(@env.dotfile_path).once.returns(true) File.expects(:file?).with(@env.dotfile_path).once.returns(true)
@env.load_vm! @env.load_vm!
assert_equal vm, @env.vm assert_equal vm, @env.vms.values.first
end end
should "not set the environment if the VM is nil" do should "load all the VMs from the dotfile" do
vms = { :foo => "bar", :bar => "baz" }
results = {}
filemock = mock("filemock") filemock = mock("filemock")
filemock.expects(:read).returns("foo") filemock.expects(:read).returns(vms.to_json)
Vagrant::VM.expects(:find).with("foo", @env).returns(nil)
File.expects(:open).with(@env.dotfile_path).once.yields(filemock) File.expects(:open).with(@env.dotfile_path).once.yields(filemock)
File.expects(:file?).with(@env.dotfile_path).once.returns(true) File.expects(:file?).with(@env.dotfile_path).once.returns(true)
assert_nothing_raised { @env.load_vm! } vms.each do |key, value|
assert_nil @env.vm vm = mock("vm#{key}")
Vagrant::VM.expects(:find).with(value, @env, key.to_sym).returns(vm)
results[key] = vm
end end
should "do nothing if the root path is nil" do
File.expects(:open).never
@env.stubs(:root_path).returns(nil)
@env.load_vm! @env.load_vm!
results.each do |key, value|
assert_equal value, @env.vms[key]
end
end
should "do nothing if the vm_name is set" do
@env.stubs(:vm_name).returns(:foo)
File.expects(:open).never
@env.load_vm!
end
should "do nothing if the dotfile is nil" do
@env.stubs(:dotfile_path).returns(nil)
File.expects(:open).never
assert_nothing_raised {
@env.load_vm!
}
end end
should "do nothing if dotfile is not a file" do should "do nothing if dotfile is not a file" do
@ -397,16 +478,36 @@ class EnvironmentTest < Test::Unit::TestCase
end end
end end
context "loading SSH" do context "loading blank VMs" do
setup do setup do
@env = mock_environment @env = mock_environment
end end
should "initialize the SSH object with the given environment" do should "blank the VMs" do
ssh = mock("ssh") @env = mock_environment do |config|
Vagrant::SSH.expects(:new).with(@env).returns(ssh) config.vm.define :foo do |config|
@env.load_ssh! end
assert_equal ssh, @env.ssh
config.vm.define :bar do |config|
end
end
@env.load_blank_vms!
assert_equal 2, @env.vms.length
assert(@env.vms.all? { |name, vm| !vm.created? })
sorted_vms = @env.vms.keys.sort { |a,b| a.to_s <=> b.to_s }
assert_equal [:bar, :foo], sorted_vms
end
should "load the default VM blank if no multi-VMs are specified" do
assert @env.config.vm.defined_vms.empty? # sanity
@env.load_blank_vms!
assert_equal 1, @env.vms.length
assert !@env.vms.values.first.created?
end end
end end
@ -529,73 +630,53 @@ class EnvironmentTest < Test::Unit::TestCase
@vm.stubs(:uuid).returns("foo") @vm.stubs(:uuid).returns("foo")
@env.stubs(:vm).returns(@vm) @env.stubs(:vm).returns(@vm)
end end
context "creating a new VM" do
should "create a new VM" do
assert_nil @env.vm
@env.create_vm
assert !@env.vm.nil?
assert @env.vm.is_a?(Vagrant::VM)
end end
should "set the new VM's environment to the env" do context "updating the dotfile" do
@env.create_vm
assert_equal @env, @env.vm.env
end
should "return the new VM" do
result = @env.create_vm
assert result.is_a?(Vagrant::VM)
end
end
context "persisting the VM into a file" do
setup do setup do
mock_vm @env = mock_environment
@env.stubs(:parent).returns(nil)
@env.stubs(:dotfile_path).returns("foo")
File.stubs(:open) File.stubs(:open)
@env.active_list.stubs(:add)
end end
should "should save it to the dotfile path" do def create_vm(created)
filemock = mock("filemock") vm = mock("vm")
filemock.expects(:write).with(@vm.uuid) vm.stubs(:created?).returns(created)
File.expects(:open).with(@env.dotfile_path, 'w+').once.yields(filemock) vm.stubs(:uuid).returns("foo")
@env.persist_vm vm
end end
should "add the VM to the activelist" do should "call parent if exists" do
@env.active_list.expects(:add).with(@vm) parent = mock("parent")
@env.persist_vm @env.stubs(:parent).returns(parent)
end parent.expects(:update_dotfile).once
@env.update_dotfile
end end
context "depersisting the VM" do should "write the proper data to dotfile" do
setup do vms = {
mock_vm :foo => create_vm(false),
:bar => create_vm(true),
:baz => create_vm(true)
}
File.stubs(:exist?).returns(false) f = mock("f")
File.stubs(:delete) @env.stubs(:vms).returns(vms)
File.expects(:open).with(@env.dotfile_path, 'w+').yields(f)
f.expects(:write).with() do |json|
assert_nothing_raised {
data = JSON.parse(json)
assert_equal 2, data.length
assert_equal vms[:bar].uuid, data["bar"]
assert_equal vms[:baz].uuid, data["baz"]
}
@env.active_list.stubs(:remove) true
end end
should "remove the dotfile if it exists" do @env.update_dotfile
File.expects(:exist?).with(@env.dotfile_path).returns(true)
File.expects(:delete).with(@env.dotfile_path).once
@env.depersist_vm
end
should "not remove the dotfile if it doesn't exist" do
File.expects(:exist?).returns(false)
File.expects(:delete).never
@env.depersist_vm
end
should "remove from the active list" do
@env.active_list.expects(:remove).with(@vm)
@env.depersist_vm
end
end end
end end
end end

View File

@ -7,13 +7,13 @@ class BaseProvisionerTest < Test::Unit::TestCase
context "base instance" do context "base instance" do
setup do setup do
@env = mock_environment @vm = mock("vm")
@base = Vagrant::Provisioners::Base.new(@env) @base = Vagrant::Provisioners::Base.new(@vm)
end end
should "set the environment" do should "set the environment" do
base = Vagrant::Provisioners::Base.new(@env) base = Vagrant::Provisioners::Base.new(@vm)
assert_equal @env, base.env assert_equal @vm, base.vm
end end
should "implement provision! which does nothing" do should "implement provision! which does nothing" do

View File

@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ChefServerProvisionerTest < Test::Unit::TestCase class ChefServerProvisionerTest < Test::Unit::TestCase
setup do setup do
@env = mock_environment @vm = mock_vm
@action = Vagrant::Provisioners::ChefServer.new(@env) @env = @vm.env
@action = Vagrant::Provisioners::ChefServer.new(@vm)
end end
context "provisioning" do context "provisioning" do
@ -106,7 +107,7 @@ class ChefServerProvisionerTest < Test::Unit::TestCase
should "create the folder using the dirname of the path" do should "create the folder using the dirname of the path" do
ssh = mock("ssh") ssh = mock("ssh")
ssh.expects(:exec!).with("sudo mkdir -p #{@path.dirname}").once ssh.expects(:exec!).with("sudo mkdir -p #{@path.dirname}").once
@env.ssh.expects(:execute).yields(ssh) @vm.ssh.expects(:execute).yields(ssh)
@action.create_client_key_folder @action.create_client_key_folder
end end
end end
@ -115,7 +116,7 @@ class ChefServerProvisionerTest < Test::Unit::TestCase
should "upload the validation key to the provisioning path" do should "upload the validation key to the provisioning path" do
@action.expects(:validation_key_path).once.returns("foo") @action.expects(:validation_key_path).once.returns("foo")
@action.expects(:guest_validation_key_path).once.returns("bar") @action.expects(:guest_validation_key_path).once.returns("bar")
@env.ssh.expects(:upload!).with("foo", "bar").once @vm.ssh.expects(:upload!).with("foo", "bar").once
@action.upload_validation_key @action.upload_validation_key
end end
end end
@ -158,7 +159,7 @@ class ChefServerProvisionerTest < Test::Unit::TestCase
should "cd into the provisioning directory and run chef client" do should "cd into the provisioning directory and run chef client" do
ssh = mock("ssh") ssh = mock("ssh")
ssh.expects(:exec!).with("cd #{@env.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json").once ssh.expects(:exec!).with("cd #{@env.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json").once
@env.ssh.expects(:execute).yields(ssh) @vm.ssh.expects(:execute).yields(ssh)
@action.run_chef_client @action.run_chef_client
end end
end end

View File

@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ChefSoloProvisionerTest < Test::Unit::TestCase class ChefSoloProvisionerTest < Test::Unit::TestCase
setup do setup do
@env = mock_environment @vm = mock_vm
@action = Vagrant::Provisioners::ChefSolo.new(@env) @env = @vm.env
@action = Vagrant::Provisioners::ChefSolo.new(@vm)
end end
context "preparing" do context "preparing" do
@ -148,7 +149,7 @@ class ChefSoloProvisionerTest < Test::Unit::TestCase
context "generating and uploading chef solo configuration file" do context "generating and uploading chef solo configuration file" do
setup do setup do
@env.ssh.stubs(:upload!) @vm.ssh.stubs(:upload!)
end end
should "call setup_config with proper variables" do should "call setup_config with proper variables" do
@ -166,7 +167,7 @@ class ChefSoloProvisionerTest < Test::Unit::TestCase
should "cd into the provisioning directory and run chef solo" do should "cd into the provisioning directory and run chef solo" do
ssh = mock("ssh") ssh = mock("ssh")
ssh.expects(:exec!).with("cd #{@env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json").once ssh.expects(:exec!).with("cd #{@env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json").once
@env.ssh.expects(:execute).yields(ssh) @vm.ssh.expects(:execute).yields(ssh)
@action.run_chef_solo @action.run_chef_solo
end end
end end

View File

@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ChefProvisionerTest < Test::Unit::TestCase class ChefProvisionerTest < Test::Unit::TestCase
setup do setup do
@env = mock_environment @vm = mock_vm
@action = Vagrant::Provisioners::Chef.new(@env) @env = @vm.env
@action = Vagrant::Provisioners::Chef.new(@vm)
end end
context "preparing" do context "preparing" do
@ -67,14 +68,14 @@ class ChefProvisionerTest < Test::Unit::TestCase
ssh = mock("ssh") ssh = mock("ssh")
ssh.expects(:exec!).with("sudo mkdir -p #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq) ssh.expects(:exec!).with("sudo mkdir -p #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq)
ssh.expects(:exec!).with("sudo chown #{@env.config.ssh.username} #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq) ssh.expects(:exec!).with("sudo chown #{@env.config.ssh.username} #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq)
@env.ssh.expects(:execute).yields(ssh) @vm.ssh.expects(:execute).yields(ssh)
@action.chown_provisioning_folder @action.chown_provisioning_folder
end end
end end
context "generating and uploading chef configuration file" do context "generating and uploading chef configuration file" do
setup do setup do
@env.ssh.stubs(:upload!) @vm.ssh.stubs(:upload!)
@template = "template" @template = "template"
@filename = "foo.rb" @filename = "foo.rb"
@ -88,7 +89,7 @@ class ChefProvisionerTest < Test::Unit::TestCase
Vagrant::Util::TemplateRenderer.expects(:render).with(@template, anything).returns(template_data) Vagrant::Util::TemplateRenderer.expects(:render).with(@template, anything).returns(template_data)
StringIO.expects(:new).with(template_data).returns(string_io) StringIO.expects(:new).with(template_data).returns(string_io)
File.expects(:join).with(@env.config.chef.provisioning_path, @filename).once.returns("bar") File.expects(:join).with(@env.config.chef.provisioning_path, @filename).once.returns("bar")
@env.ssh.expects(:upload!).with(string_io, "bar") @vm.ssh.expects(:upload!).with(string_io, "bar")
@action.setup_config(@template, @filename, {}) @action.setup_config(@template, @filename, {})
end end
@ -124,7 +125,7 @@ class ChefProvisionerTest < Test::Unit::TestCase
context "generating and uploading json" do context "generating and uploading json" do
def assert_json def assert_json
@env.ssh.expects(:upload!).with do |json, path| @vm.ssh.expects(:upload!).with do |json, path|
data = JSON.parse(json.read) data = JSON.parse(json.read)
yield data yield data
true true
@ -155,7 +156,7 @@ class ChefProvisionerTest < Test::Unit::TestCase
should "upload a StringIO to dna.json" do should "upload a StringIO to dna.json" do
StringIO.expects(:new).with(anything).returns("bar") StringIO.expects(:new).with(anything).returns("bar")
File.expects(:join).with(@env.config.chef.provisioning_path, "dna.json").once.returns("baz") File.expects(:join).with(@env.config.chef.provisioning_path, "dna.json").once.returns("baz")
@env.ssh.expects(:upload!).with("bar", "baz").once @vm.ssh.expects(:upload!).with("bar", "baz").once
@action.setup_json @action.setup_json
end end
end end

View File

@ -4,8 +4,7 @@ class LinuxSystemTest < Test::Unit::TestCase
setup do setup do
@klass = Vagrant::Systems::Linux @klass = Vagrant::Systems::Linux
@vm = mock("vm") @vm = mock_vm
@vm.stubs(:env).returns(mock_environment)
@instance = @klass.new(@vm) @instance = @klass.new(@vm)
end end
@ -14,7 +13,7 @@ class LinuxSystemTest < Test::Unit::TestCase
@ssh_session = mock("ssh_session") @ssh_session = mock("ssh_session")
@ssh = mock("ssh") @ssh = mock("ssh")
@ssh.stubs(:execute).yields(@ssh_session) @ssh.stubs(:execute).yields(@ssh_session)
@vm.env.stubs(:ssh).returns(@ssh) @vm.stubs(:ssh).returns(@ssh)
@real_vm = mock("real_vm") @real_vm = mock("real_vm")
@real_vm.stubs(:state).returns(:powered_off) @real_vm.stubs(:state).returns(:powered_off)

View File

@ -14,18 +14,20 @@ class VMTest < Test::Unit::TestCase
context "being an action runner" do context "being an action runner" do
should "be an action runner" do should "be an action runner" do
vm = Vagrant::VM.new(@env) vm = Vagrant::VM.new(:env => @env)
assert vm.is_a?(Vagrant::Actions::Runner) assert vm.is_a?(Vagrant::Actions::Runner)
end end
end end
context "finding a VM" do context "finding a VM" do
should "return nil if the VM is not found" do should "return return an uncreated VM object if the VM is not found" do
VirtualBox::VM.expects(:find).returns(nil) VirtualBox::VM.expects(:find).returns(nil)
assert_nil Vagrant::VM.find("foo") result = Vagrant::VM.find("foo")
assert result.is_a?(Vagrant::VM)
assert !result.created?
end end
should "return a Vagrant::VM object for that VM otherwise" do should "return a Vagrant::VM object for that VM if found" do
VirtualBox::VM.expects(:find).with("foo").returns("bar") VirtualBox::VM.expects(:find).with("foo").returns("bar")
result = Vagrant::VM.find("foo", mock_environment) result = Vagrant::VM.find("foo", mock_environment)
assert result.is_a?(Vagrant::VM) assert result.is_a?(Vagrant::VM)
@ -35,10 +37,44 @@ class VMTest < Test::Unit::TestCase
context "vagrant VM instance" do context "vagrant VM instance" do
setup do setup do
@vm = Vagrant::VM.new(@env, @mock_vm) @vm = Vagrant::VM.new(:env => @env, :vm => @mock_vm)
@mock_vm.stubs(:uuid).returns("foo") @mock_vm.stubs(:uuid).returns("foo")
end end
context "checking if created" do
should "return true if the VM object is not nil" do
@vm.stubs(:vm).returns(:foo)
assert @vm.created?
end
should "return false if the VM object is nil" do
@vm.stubs(:vm).returns(nil)
assert !@vm.created?
end
end
context "accessing the SSH object" do
setup do
# Reset this to nil to force the reload
@vm.instance_variable_set(:@ssh, nil)
@ssh = mock("ssh")
Vagrant::SSH.stubs(:new).returns(@ssh)
end
should "load it the first time" do
Vagrant::SSH.expects(:new).with(@vm.env).once.returns(@ssh)
@vm.ssh
@vm.ssh
@vm.ssh
end
should "use the same value once its loaded" do
result = @vm.ssh
assert_equal result, @vm.ssh
end
end
context "loading associated system" do context "loading associated system" do
should "error and exit if system is not specified" do should "error and exit if system is not specified" do
@vm.env.config.vm.system = nil @vm.env.config.vm.system = nil
@ -125,6 +161,32 @@ class VMTest < Test::Unit::TestCase
end end
end end
context "upping" do
should "execute the up action" do
@vm.expects(:execute!).with(Vagrant::Actions::VM::Up).once
@vm.up
end
end
context "halting" do
should "execute the halt action" do
@vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, false).once
@vm.halt
end
should "force if specified" do
@vm.expects(:execute!).with(Vagrant::Actions::VM::Halt, true).once
@vm.halt(true)
end
end
context "reloading" do
should "execute the reload action" do
@vm.expects(:execute!).with(Vagrant::Actions::VM::Reload).once
@vm.reload
end
end
context "destroying" do context "destroying" do
should "execute the down action" do should "execute the down action" do
@vm.expects(:execute!).with(Vagrant::Actions::VM::Down).once @vm.expects(:execute!).with(Vagrant::Actions::VM::Down).once

View File

@ -5,11 +5,11 @@
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = %q{vagrant} s.name = %q{vagrant}
s.version = "0.3.3.dev" s.version = "0.3.4.dev"
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Mitchell Hashimoto", "John Bender"] s.authors = ["Mitchell Hashimoto", "John Bender"]
s.date = %q{2010-05-01} s.date = %q{2010-05-17}
s.default_executable = %q{vagrant} s.default_executable = %q{vagrant}
s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.}
s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"] s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"]
@ -175,67 +175,67 @@ Gem::Specification.new do |s|
s.summary = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.summary = %q{Vagrant is a tool for building and distributing virtualized development environments.}
s.test_files = [ s.test_files = [
"test/test_helper.rb", "test/test_helper.rb",
"test/vagrant/actions/base_test.rb", "test/vagrant/vm_test.rb",
"test/vagrant/actions/box/add_test.rb", "test/vagrant/command_test.rb",
"test/vagrant/actions/box/destroy_test.rb", "test/vagrant/environment_test.rb",
"test/vagrant/actions/box/download_test.rb", "test/vagrant/util_test.rb",
"test/vagrant/actions/box/unpackage_test.rb",
"test/vagrant/actions/box/verify_test.rb",
"test/vagrant/actions/collection_test.rb",
"test/vagrant/actions/runner_test.rb",
"test/vagrant/actions/vm/boot_test.rb",
"test/vagrant/actions/vm/customize_test.rb",
"test/vagrant/actions/vm/destroy_test.rb",
"test/vagrant/actions/vm/down_test.rb",
"test/vagrant/actions/vm/export_test.rb",
"test/vagrant/actions/vm/forward_ports_test.rb",
"test/vagrant/actions/vm/halt_test.rb",
"test/vagrant/actions/vm/import_test.rb",
"test/vagrant/actions/vm/move_hard_drive_test.rb",
"test/vagrant/actions/vm/package_test.rb",
"test/vagrant/actions/vm/provision_test.rb",
"test/vagrant/actions/vm/reload_test.rb",
"test/vagrant/actions/vm/resume_test.rb",
"test/vagrant/actions/vm/shared_folders_test.rb",
"test/vagrant/actions/vm/start_test.rb",
"test/vagrant/actions/vm/suspend_test.rb",
"test/vagrant/actions/vm/up_test.rb",
"test/vagrant/active_list_test.rb",
"test/vagrant/box_test.rb", "test/vagrant/box_test.rb",
"test/vagrant/busy_test.rb", "test/vagrant/busy_test.rb",
"test/vagrant/command_test.rb", "test/vagrant/provisioners/base_test.rb",
"test/vagrant/provisioners/chef_test.rb",
"test/vagrant/provisioners/chef_server_test.rb",
"test/vagrant/provisioners/chef_solo_test.rb",
"test/vagrant/systems/linux_test.rb",
"test/vagrant/config_test.rb",
"test/vagrant/actions/base_test.rb",
"test/vagrant/actions/runner_test.rb",
"test/vagrant/actions/box/verify_test.rb",
"test/vagrant/actions/box/destroy_test.rb",
"test/vagrant/actions/box/add_test.rb",
"test/vagrant/actions/box/unpackage_test.rb",
"test/vagrant/actions/box/download_test.rb",
"test/vagrant/actions/collection_test.rb",
"test/vagrant/actions/vm/reload_test.rb",
"test/vagrant/actions/vm/suspend_test.rb",
"test/vagrant/actions/vm/boot_test.rb",
"test/vagrant/actions/vm/package_test.rb",
"test/vagrant/actions/vm/down_test.rb",
"test/vagrant/actions/vm/shared_folders_test.rb",
"test/vagrant/actions/vm/destroy_test.rb",
"test/vagrant/actions/vm/halt_test.rb",
"test/vagrant/actions/vm/import_test.rb",
"test/vagrant/actions/vm/customize_test.rb",
"test/vagrant/actions/vm/start_test.rb",
"test/vagrant/actions/vm/move_hard_drive_test.rb",
"test/vagrant/actions/vm/up_test.rb",
"test/vagrant/actions/vm/export_test.rb",
"test/vagrant/actions/vm/provision_test.rb",
"test/vagrant/actions/vm/resume_test.rb",
"test/vagrant/actions/vm/forward_ports_test.rb",
"test/vagrant/active_list_test.rb",
"test/vagrant/commands/base_test.rb", "test/vagrant/commands/base_test.rb",
"test/vagrant/commands/box/add_test.rb", "test/vagrant/commands/reload_test.rb",
"test/vagrant/commands/box/list_test.rb", "test/vagrant/commands/ssh_config_test.rb",
"test/vagrant/commands/box/remove_test.rb", "test/vagrant/commands/suspend_test.rb",
"test/vagrant/commands/package_test.rb",
"test/vagrant/commands/status_test.rb",
"test/vagrant/commands/init_test.rb",
"test/vagrant/commands/destroy_test.rb", "test/vagrant/commands/destroy_test.rb",
"test/vagrant/commands/halt_test.rb", "test/vagrant/commands/halt_test.rb",
"test/vagrant/commands/init_test.rb", "test/vagrant/commands/box/remove_test.rb",
"test/vagrant/commands/package_test.rb", "test/vagrant/commands/box/add_test.rb",
"test/vagrant/commands/reload_test.rb", "test/vagrant/commands/box/list_test.rb",
"test/vagrant/commands/resume_test.rb",
"test/vagrant/commands/ssh_config_test.rb",
"test/vagrant/commands/ssh_test.rb",
"test/vagrant/commands/status_test.rb",
"test/vagrant/commands/suspend_test.rb",
"test/vagrant/commands/up_test.rb", "test/vagrant/commands/up_test.rb",
"test/vagrant/config_test.rb", "test/vagrant/commands/resume_test.rb",
"test/vagrant/commands/ssh_test.rb",
"test/vagrant/downloaders/base_test.rb", "test/vagrant/downloaders/base_test.rb",
"test/vagrant/downloaders/file_test.rb", "test/vagrant/downloaders/file_test.rb",
"test/vagrant/downloaders/http_test.rb", "test/vagrant/downloaders/http_test.rb",
"test/vagrant/environment_test.rb",
"test/vagrant/provisioners/base_test.rb",
"test/vagrant/provisioners/chef_server_test.rb",
"test/vagrant/provisioners/chef_solo_test.rb",
"test/vagrant/provisioners/chef_test.rb",
"test/vagrant/ssh_test.rb",
"test/vagrant/systems/linux_test.rb",
"test/vagrant/util/progress_meter_test.rb",
"test/vagrant/util/stacked_proc_runner_test.rb", "test/vagrant/util/stacked_proc_runner_test.rb",
"test/vagrant/util/progress_meter_test.rb",
"test/vagrant/util/template_renderer_test.rb", "test/vagrant/util/template_renderer_test.rb",
"test/vagrant/util/translator_test.rb", "test/vagrant/util/translator_test.rb",
"test/vagrant/util_test.rb", "test/vagrant/ssh_test.rb"
"test/vagrant/vm_test.rb"
] ]
if s.respond_to? :specification_version then if s.respond_to? :specification_version then