Merge remote branch 'remotes/upstream/master'

Refactored redhat distribution to fit new model

Conflicts:
	lib/vagrant/systems/linux.rb
	templates/debian_network_entry.erb
	templates/locales/en.yml
	templates/network_entry.erb
	templates/network_entry_debian.erb
This commit is contained in:
Michael Bearne 2011-01-10 14:21:52 +00:00
commit 8b6d63ab58
56 changed files with 917 additions and 603 deletions

View File

@ -1,5 +1,6 @@
## 0.7.0.beta2 (unreleased)
- Puppet server provisioner. [GH-262]
- Use numeric uid/gid in mounting shared folders to increase portability. [GH-252]
- HTTP downloading follows redirects. [GH-163]
- Downloaders have clearer output to note what they're doing.
@ -7,6 +8,16 @@
- Boxes downloaded during `vagrant up` reload the Vagrantfile config, which
fixes a problem with box settings not being properly loaded. [GH-231]
- `config.ssh.forward_x11` to enable the ForwardX11 SSH option. [GH-255]
- Vagrant source now has a `contrib` directory where contributions of miscellaneous
addons for Vagrant will be added.
- Vagrantfiles are now loaded only once (instead of 4+ times) [GH-238]
- Ability to move home vagrant dir (~/.vagrant) by setting VAGRANT_HOME
environmental variable.
- Removed check and error for the "OSE" version of VirtualBox, since with
VirtualBox 4 this distinction no longer exists.
- Ability to specify proxy settings for chef. [GH-169]
- Helpful error message shown if NFS mounting fails. [GH-135]
- Gentoo guests now support host only networks. [GH-240]
## 0.7.0.beta (December 24, 2010)

View File

@ -16,12 +16,4 @@ group :test do
# For documentation
gem "yard", "~> 0.6.1"
gem "bluecloth"
platforms :mri_18 do
gem "ruby-debug"
end
platforms :mri_19 do
gem "ruby-debug19"
end
end

View File

@ -1,7 +1,6 @@
Vagrant::Config.run do |config|
# default config goes here
config.vagrant.dotfile_name = ".vagrant"
config.vagrant.home = "~/.vagrant"
config.vagrant.host = :detect
config.ssh.username = "vagrant"

12
contrib/README.md Normal file
View File

@ -0,0 +1,12 @@
# Vagrant Contrib
Miscellaneous contributions which assist people in using Vagrant will
make their way into this directory. An up-to-date list of short descriptions
for each item will be kept below.
## List of Contrib Items
* `emacs` - Contains a file showing how to associate `Vagrantfile` with
Ruby syntax highlighting.
* `vim` - Contains a `.vim` file for enabling Ruby syntax highlighting
for `Vagrantfile`s.

8
contrib/emacs/vagrant.el Normal file
View File

@ -0,0 +1,8 @@
;;--------------------------------------------------------------------
;; Teach emacs to syntax highlight Vagrantfile as Ruby.
;;
;; Installation: Copy the line below into your emacs configuration,
;; or drop this file anywhere in your "~/.emacs.d" directory and be
;; sure to "load" it.
;;--------------------------------------------------------------------
(add-to-list 'auto-mode-alist '("Vagrantfile$" . ruby-mode))

View File

@ -0,0 +1,9 @@
" Teach vim to syntax highlight Vagrantfile as ruby
"
" Install: $HOME/.vim/plugin/vagrant.vim
" Author: Brandon Philips <brandon@ifup.org>
augroup vagrant
au!
au BufRead,BufNewFile Vagrantfile set filetype=ruby
augroup END

View File

@ -4,25 +4,21 @@ require 'i18n'
require 'virtualbox'
module Vagrant
# TODO: Move more classes over to the autoload model. We'll
# start small, but slowly move everything over.
autoload :Action, 'vagrant/action'
autoload :Box, 'vagrant/box'
autoload :BoxCollection, 'vagrant/box_collection'
autoload :CLI, 'vagrant/cli'
autoload :Config, 'vagrant/config'
autoload :DataStore, 'vagrant/data_store'
autoload :Downloaders, 'vagrant/downloaders'
autoload :Environment, 'vagrant/environment'
autoload :Errors, 'vagrant/errors'
autoload :Hosts, 'vagrant/hosts'
autoload :Plugin, 'vagrant/plugin'
autoload :TestHelpers, 'vagrant/test_helpers'
autoload :UI, 'vagrant/ui'
autoload :Util, 'vagrant/util'
module Command
autoload :Base, 'vagrant/command/base'
autoload :GroupBase, 'vagrant/command/group_base'
autoload :Helpers, 'vagrant/command/helpers'
autoload :NamedBase, 'vagrant/command/named_base'
end
autoload :VM, 'vagrant/vm'
# The source root is the path to the root directory of
# the Vagrant gem.
@ -34,13 +30,13 @@ end
# Default I18n to load the en locale
I18n.load_path << File.expand_path("templates/locales/en.yml", Vagrant.source_root)
# Load them up. One day we'll convert this to autoloads. Today
# is not that day. Low hanging fruit for anyone wishing to do it.
libdir = File.expand_path("lib/vagrant", Vagrant.source_root)
Vagrant::Util::GlobLoader.glob_require(libdir, %w{
downloaders/base provisioners/base provisioners/chef systems/base
hosts/base})
# Initialize the built-in actions and load the plugins.
# Load the things which must be loaded before anything else. Note that
# I'm not sure why 'vagrant/ssh' must be loaded. But if I don't, I get
# a very scary "unsupported cipher" error from net-ssh for no apparent reason.
require 'vagrant/command'
require 'vagrant/provisioners'
require 'vagrant/systems'
require 'vagrant/ssh'
require 'vagrant/version'
Vagrant::Action.builtin!
Vagrant::Plugin.load!

View File

@ -1,3 +1,12 @@
require 'vagrant/action/builder'
require 'vagrant/action/builtin'
# The builtin middlewares
require 'vagrant/action/box'
require 'vagrant/action/env'
require 'vagrant/action/general'
require 'vagrant/action/vm'
module Vagrant
# Manages action running and registration. Every Vagrant environment
# has an instance of {Action} to allow for running in the context of
@ -44,6 +53,9 @@ module Vagrant
# Where `:name` is the name of the registered action.
#
class Action
autoload :Environment, 'vagrant/action/environment'
autoload :Warden, 'vagrant/action/warden'
include Util
@@reported_interrupt = false

11
lib/vagrant/action/box.rb Normal file
View File

@ -0,0 +1,11 @@
module Vagrant
class Action
module Box
autoload :Destroy, 'vagrant/action/box/destroy'
autoload :Download, 'vagrant/action/box/download'
autoload :Package, 'vagrant/action/box/package'
autoload :Unpackage, 'vagrant/action/box/unpackage'
autoload :Verify, 'vagrant/action/box/verify'
end
end
end

View File

@ -0,0 +1,7 @@
module Vagrant
class Action
module Env
autoload :Set, 'vagrant/action/env/set'
end
end
end

View File

@ -0,0 +1,8 @@
module Vagrant
class Action
module General
autoload :Package, 'vagrant/action/general/package'
autoload :Validate, 'vagrant/action/general/validate'
end
end
end

30
lib/vagrant/action/vm.rb Normal file
View File

@ -0,0 +1,30 @@
module Vagrant
class Action
module VM
autoload :Boot, 'vagrant/action/vm/boot'
autoload :CheckBox, 'vagrant/action/vm/check_box'
autoload :CheckGuestAdditions, 'vagrant/action/vm/check_guest_additions'
autoload :CleanMachineFolder, 'vagrant/action/vm/clean_machine_folder'
autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports'
autoload :ClearNFSExports, 'vagrant/action/vm/clear_nfs_exports'
autoload :ClearSharedFolders, 'vagrant/action/vm/clear_shared_folders'
autoload :Customize, 'vagrant/action/vm/customize'
autoload :Destroy, 'vagrant/action/vm/destroy'
autoload :DestroyUnusedNetworkInterfaces, 'vagrant/action/vm/destroy_unused_network_interfaces'
autoload :DiscardState, 'vagrant/action/vm/discard_state'
autoload :Export, 'vagrant/action/vm/export'
autoload :ForwardPorts, 'vagrant/action/vm/forward_ports'
autoload :Halt, 'vagrant/action/vm/halt'
autoload :Import, 'vagrant/action/vm/import'
autoload :MatchMACAddress, 'vagrant/action/vm/match_mac_address'
autoload :Network, 'vagrant/action/vm/network'
autoload :NFS, 'vagrant/action/vm/nfs'
autoload :Package, 'vagrant/action/vm/package'
autoload :PackageVagrantfile, 'vagrant/action/vm/package_vagrantfile'
autoload :Provision, 'vagrant/action/vm/provision'
autoload :Resume, 'vagrant/action/vm/resume'
autoload :ShareFolders, 'vagrant/action/vm/share_folders'
autoload :Suspend, 'vagrant/action/vm/suspend'
end
end
end

View File

@ -13,6 +13,7 @@ module Vagrant
# Start up the VM and wait for it to boot.
boot
raise Errors::VMFailedToBoot if !wait_for_boot
@app.call(env)
end
@ -24,7 +25,7 @@ module Vagrant
def wait_for_boot
@env.ui.info I18n.t("vagrant.actions.vm.boot.waiting")
@env.env.config.ssh.max_tries.to_i.times do |i|
@env["config"].ssh.max_tries.to_i.times do |i|
if @env["vm"].ssh.up?
@env.ui.info I18n.t("vagrant.actions.vm.boot.ready")
return true
@ -34,7 +35,7 @@ module Vagrant
# get shown
return true if @env.interrupted?
sleep 5 if !@env["vagrant.test"]
sleep 2 if !@env["vagrant.test"]
end
@env.ui.error I18n.t("vagrant.actions.vm.boot.failed")

View File

@ -25,8 +25,8 @@ module Vagrant
if enable_network?
@env.ui.info I18n.t("vagrant.actions.vm.network.enabling")
@env["vm"].system.prepare_host_only_network
@env.env.config.vm.network_options.compact.each do |network_options|
@env["vm"].system.prepare_host_only_network(network_options)
@env["vm"].system.enable_host_only_network(network_options)
end
end

View File

@ -115,7 +115,7 @@ module Vagrant
# Only mount the folders which have a guest path specified
am_folders = folders.select { |name, folder| folder[:guestpath] }
@env["vm"].system.mount_nfs(host_ip, am_folders)
@env["vm"].system.mount_nfs(host_ip, Hash[am_folders])
end
# Returns the IP address of the first host only network adapter

View File

@ -34,7 +34,8 @@ module Vagrant
mapping = {
:chef_solo => Provisioners::ChefSolo,
:chef_server => Provisioners::ChefServer,
:puppet => Provisioners::Puppet
:puppet => Provisioners::Puppet,
:puppet_server => Provisioners::PuppetServer
}
provisioner_klass = mapping[provisioner]

25
lib/vagrant/command.rb Normal file
View File

@ -0,0 +1,25 @@
module Vagrant
module Command
autoload :Base, 'vagrant/command/base'
autoload :GroupBase, 'vagrant/command/group_base'
autoload :Helpers, 'vagrant/command/helpers'
autoload :NamedBase, 'vagrant/command/named_base'
end
end
# The built-in commands must always be loaded
require 'vagrant/command/box'
require 'vagrant/command/destroy'
require 'vagrant/command/halt'
require 'vagrant/command/init'
require 'vagrant/command/package'
require 'vagrant/command/provision'
require 'vagrant/command/reload'
require 'vagrant/command/resume'
require 'vagrant/command/ssh'
require 'vagrant/command/ssh_config'
require 'vagrant/command/status'
require 'vagrant/command/suspend'
require 'vagrant/command/up'
require 'vagrant/command/upgrade_to_060'
require 'vagrant/command/version'

View File

@ -1,5 +1,13 @@
require 'vagrant/config/base'
require 'vagrant/config/error_recorder'
require 'vagrant/config/top'
# The built-in configuration classes
require 'vagrant/config/vagrant'
require 'vagrant/config/ssh'
require 'vagrant/config/nfs'
require 'vagrant/config/vm'
require 'vagrant/config/package'
module Vagrant
# The config class is responsible for loading Vagrant configurations, which
@ -17,157 +25,99 @@ module Vagrant
# class you are looking for. Loading configuration is quite easy. The following
# example assumes `env` is already a loaded instance of {Environment}:
#
# config = Vagrant::Config.new(env)
# config.queue << "/path/to/some/Vagrantfile"
# result = config.load!
# config = Vagrant::Config.new
# config.set(:first, "/path/to/some/Vagrantfile")
# config.set(:second, "/path/to/another/Vagrantfile")
# config.load_order = [:first, :second]
# result = config.load(env)
#
# p "Your box is: #{result.vm.box}"
#
# The load order determines what order the config files specified are loaded.
# If a key is not mentioned (for example if above the load order was set to
# `[:first]`, therefore `:second` was not mentioned), then that config file
# won't be loaded.
class Config
extend Util::StackedProcRunner
# An array of symbols specifying the load order for the procs.
attr_accessor :load_order
attr_reader :procs
@@config = nil
# This is the method which is called by all Vagrantfiles to configure Vagrant.
# This method expects a block which accepts a single argument representing
# an instance of the {Config::Top} class.
#
# Note that the block is not run immediately. Instead, it's proc is stored
# away for execution later.
def self.run(&block)
# Store it for later
@last_procs ||= []
@last_procs << block
end
attr_reader :queue
# Returns the last proc which was activated for the class via {run}. This
# also sets the last proc to `nil` so that calling this method multiple times
# will not return duplicates.
#
# @return [Proc]
def self.last_proc
value = @last_procs
@last_procs = nil
value
end
class << self
# Resets the current loaded config object to the specified environment.
# This clears the proc stack and initializes a new {Top} for loading.
# This method shouldn't be called directly, instead use an instance of this
# class for config loading.
def initialize(parent=nil)
@procs = {}
@load_order = []
if parent
# Shallow copy the procs and load order from parent if given
@procs = parent.procs.dup
@load_order = parent.load_order.dup
end
end
# Adds a Vagrantfile to be loaded to the queue of config procs. Note
# that this causes the Vagrantfile file to be loaded at this point,
# and it will never be loaded again.
def set(key, path)
return if @procs.has_key?(key)
@procs[key] = [path].flatten.map(&method(:proc_for)).flatten
end
# Loads the added procs using the set `load_order` attribute and returns
# the {Config::Top} object result. The configuration is loaded for the
# given {Environment} object.
#
# @param [Environment] env
def reset!(env=nil)
@@config = nil
proc_stack.clear
def load(env)
config = Top.new(env)
# Reset the configuration to the specified environment
config(env)
# Only run the procs specified in the load order, in the order
# specified.
load_order.each do |key|
if @procs[key]
@procs[key].each do |proc|
proc.call(config) if proc
end
# Returns the current {Top} configuration object. While this is still
# here for implementation purposes, it shouldn't be called directly. Instead,
# use an instance of this class.
def config(env=nil)
@@config ||= Config::Top.new(env)
end
# Adds the given proc/block to the stack of config procs which are all
# run later on a single config object. This is the main way to configure
# Vagrant, and is how all Vagrantfiles are formatted:
#
# Vagrant::Config.run do |config|
# # ...
# end
#
def run(&block)
push_proc(&block)
end
# Executes all the config procs onto the currently loaded {Top} object,
# and returns the final configured object. This also validates the
# configuration by calling {Top#validate!} on every configuration
# class.
def execute!
config_object ||= config
run_procs!(config_object)
config_object
end
end
# Initialize a {Config} object for the given {Environment}.
#
# @param [Environment] env Environment which config object will be part
# of.
def initialize(env)
@env = env
@queue = []
config
end
# Loads the queue of files/procs, executes them in the proper
# sequence, and returns the resulting configuration object.
def load!
self.class.reset!(@env)
protected
def proc_for(path)
return nil if !path
return path if path.is_a?(Proc)
queue.flatten.each do |item|
if item.is_a?(String) && File.exist?(item)
begin
load item
Kernel.load path if File.exist?(path)
return self.class.last_proc
rescue SyntaxError => e
# Report syntax errors in a nice way for Vagrantfiles
raise Errors::VagrantfileSyntaxError, :file => e.message
end
elsif item.is_a?(Proc)
self.class.run(&item)
end
end
return self.class.execute!
end
end
class Config
# This class is the "top" configure class, which handles registering
# other configuration classes as well as validation of all configured
# classes. This is the object which is returned by {Environment#config}
# and has accessors to all other configuration classes.
#
# If you're looking to create your own configuration class, see {Base}.
class Top < Base
@@configures = {} if !defined?(@@configures)
class << self
# The list of registered configuration classes as well as the key
# they're registered under.
def configures_list
@@configures ||= {}
end
# Registers a configuration class with the given key. This method shouldn't
# be called. Instead, inherit from {Base} and call {Base.configures}.
def configures(key, klass)
configures_list[key] = klass
attr_reader key.to_sym
end
end
def initialize(env=nil)
self.class.configures_list.each do |key, klass|
config = klass.new
config.env = env
config.top = self
instance_variable_set("@#{key}".to_sym, config)
end
@env = env
end
# Validates the configuration classes of this instance and raises an
# exception if they are invalid. If you are implementing a custom configuration
# class, the method you want to implement is {Base#validate}. This is
# the method that checks all the validation, not one which defines
# validation rules.
def validate!
# Validate each of the configured classes and store the results into
# a hash.
errors = self.class.configures_list.inject({}) do |container, data|
key, _ = data
recorder = ErrorRecorder.new
send(key.to_sym).validate(recorder)
container[key.to_sym] = recorder if !recorder.errors.empty?
container
end
return if errors.empty?
raise Errors::ConfigValidationFailed, :messages => Util::TemplateRenderer.render("config/validation_failed", :errors => errors)
end
end
end
end
# The built-in configuration classes
require 'vagrant/config/vagrant'
require 'vagrant/config/ssh'
require 'vagrant/config/nfs'
require 'vagrant/config/vm'
require 'vagrant/config/package'

59
lib/vagrant/config/top.rb Normal file
View File

@ -0,0 +1,59 @@
module Vagrant
class Config
# This class is the "top" configure class, which handles registering
# other configuration classes as well as validation of all configured
# classes. This is the object which is returned by {Environment#config}
# and has accessors to all other configuration classes.
#
# If you're looking to create your own configuration class, see {Base}.
class Top < Base
@@configures = {} if !defined?(@@configures)
class << self
# The list of registered configuration classes as well as the key
# they're registered under.
def configures_list
@@configures ||= {}
end
# Registers a configuration class with the given key. This method shouldn't
# be called. Instead, inherit from {Base} and call {Base.configures}.
def configures(key, klass)
configures_list[key] = klass
attr_reader key.to_sym
end
end
def initialize(env=nil)
self.class.configures_list.each do |key, klass|
config = klass.new
config.env = env
config.top = self
instance_variable_set("@#{key}".to_sym, config)
end
@env = env
end
# Validates the configuration classes of this instance and raises an
# exception if they are invalid. If you are implementing a custom configuration
# class, the method you want to implement is {Base#validate}. This is
# the method that checks all the validation, not one which defines
# validation rules.
def validate!
# Validate each of the configured classes and store the results into
# a hash.
errors = self.class.configures_list.inject({}) do |container, data|
key, _ = data
recorder = ErrorRecorder.new
send(key.to_sym).validate(recorder)
container[key.to_sym] = recorder if !recorder.errors.empty?
container
end
return if errors.empty?
raise Errors::ConfigValidationFailed, :messages => Util::TemplateRenderer.render("config/validation_failed", :errors => errors)
end
end
end
end

View File

@ -4,15 +4,10 @@ module Vagrant
configures :vagrant
attr_accessor :dotfile_name
attr_accessor :home
attr_accessor :host
def initialize
@home = nil
end
def validate(errors)
[:dotfile_name, :home, :host].each do |field|
[:dotfile_name, :host].each do |field|
errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
end
end

View File

@ -0,0 +1,7 @@
module Vagrant
module Downloaders
autoload :Base, 'vagrant/downloaders/base'
autoload :File, 'vagrant/downloaders/file'
autoload :HTTP, 'vagrant/downloaders/http'
end
end

View File

@ -9,6 +9,7 @@ module Vagrant
ROOTFILE_NAME = "Vagrantfile"
HOME_SUBDIRS = ["tmp", "boxes", "logs"]
DEFAULT_VM = :default
DEFAULT_HOME = "~/.vagrant"
# Parent environment (in the case of multi-VMs)
attr_reader :parent
@ -23,6 +24,9 @@ module Vagrant
# The {UI} object to communicate with the outside world.
attr_writer :ui
# The {Config} object representing the Vagrantfile loader
attr_reader :config_loader
#---------------------------------------------------------------
# Class Methods
#---------------------------------------------------------------
@ -33,7 +37,6 @@ module Vagrant
version = VirtualBox.version
raise Errors::VirtualBoxNotDetected if version.nil?
raise Errors::VirtualBoxInvalidVersion, :version => version.to_s if version.to_f < 4.0
raise Errors::VirtualBoxInvalidOSE, :version => version.to_s if version.to_s.downcase.include?("ose")
rescue Errors::VirtualBoxNotDetected
# On 64-bit Windows, show a special error. This error is a subclass
# of VirtualBoxNotDetected, so libraries which use Vagrant can just
@ -79,12 +82,11 @@ module Vagrant
root_path.join(config.vagrant.dotfile_name) rescue nil
end
# The path to the home directory, expanded relative to the root path,
# and converted into a Pathname object.
# The path to the home directory and converted into a Pathname object.
#
# @return [Pathname]
def home_path
@_home_path ||= Pathname.new(File.expand_path(config.vagrant.home, root_path))
@_home_path ||= Pathname.new(File.expand_path(ENV["VAGRANT_HOME"] || DEFAULT_HOME))
end
# The path to the Vagrant tmp directory
@ -114,7 +116,8 @@ module Vagrant
#
# @return [String]
def resource
vm.name rescue "vagrant"
result = vm.name rescue nil
result || "vagrant"
end
# Returns the collection of boxes for the environment.
@ -308,6 +311,7 @@ module Vagrant
# Reloads the configuration of this environment.
def reload_config!
@config = nil
@config_loader = nil
load_config!
self
end
@ -320,22 +324,23 @@ module Vagrant
first_run = @config.nil?
# First load the initial, non config-dependent Vagrantfiles
loader = Config.new(self)
loader.queue << File.expand_path("config/default.rb", Vagrant.source_root)
loader.queue << File.join(box.directory, ROOTFILE_NAME) if !first_run && box
loader.queue << File.join(home_path, ROOTFILE_NAME) if !first_run && home_path
loader.queue << File.join(root_path, ROOTFILE_NAME) if root_path
@config_loader ||= Config.new(parent ? parent.config_loader : nil)
@config_loader.load_order = [:default, :box, :home, :root, :sub_vm]
@config_loader.set(:default, File.expand_path("config/default.rb", Vagrant.source_root))
@config_loader.set(:box, File.join(box.directory, ROOTFILE_NAME)) if !first_run && vm && box
@config_loader.set(:home, File.join(home_path, ROOTFILE_NAME)) if !first_run && home_path
@config_loader.set(:root, File.join(root_path, ROOTFILE_NAME)) if root_path
# If this environment is representing a sub-VM, then we push that
# proc on as the last configuration.
if vm
subvm = parent.config.vm.defined_vms[vm.name]
loader.queue << subvm.proc_stack if subvm
@config_loader.set(:sub_vm, subvm.proc_stack) if subvm
end
# Execute the configuration stack and store the result as the final
# value in the config ivar.
@config = loader.load!
@config = @config_loader.load(self)
# (re)load the logger
@logger = nil

View File

@ -275,11 +275,6 @@ module Vagrant
error_key(:vagrantfile_syntax_error)
end
class VirtualBoxInvalidOSE < VagrantError
status_code(9)
error_key(:virtualbox_invalid_ose)
end
class VirtualBoxInvalidVersion < VagrantError
status_code(17)
error_key(:virtualbox_invalid_version)

7
lib/vagrant/hosts.rb Normal file
View File

@ -0,0 +1,7 @@
module Vagrant
module Hosts
autoload :Base, 'vagrant/hosts/base'
autoload :BSD, 'vagrant/hosts/bsd'
autoload :Linux, 'vagrant/hosts/linux'
end
end

View File

@ -0,0 +1,8 @@
# These aren't autoloaded because they have to register things such
# as configuration classes right away with Vagrant.
require 'vagrant/provisioners/base'
require 'vagrant/provisioners/chef'
require 'vagrant/provisioners/chef_server'
require 'vagrant/provisioners/chef_solo'
require 'vagrant/provisioners/puppet'
require 'vagrant/provisioners/puppet_server'

View File

@ -25,7 +25,14 @@ module Vagrant
def setup_config(template, filename, template_vars)
config_file = TemplateRenderer.render(template, {
:log_level => env.config.chef.log_level.to_sym
:log_level => env.config.chef.log_level.to_sym,
:http_proxy => env.config.chef.http_proxy,
:http_proxy_user => env.config.chef.http_proxy_user,
:http_proxy_pass => env.config.chef.http_proxy_pass,
:https_proxy => env.config.chef.https_proxy,
:https_proxy_user => env.config.chef.https_proxy_user,
:https_proxy_pass => env.config.chef.https_proxy_pass,
:no_proxy => env.config.chef.no_proxy
}.merge(template_vars))
vm.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename))
@ -80,6 +87,13 @@ module Vagrant
attr_accessor :provisioning_path
attr_accessor :log_level
attr_accessor :json
attr_accessor :http_proxy
attr_accessor :http_proxy_user
attr_accessor :http_proxy_pass
attr_accessor :https_proxy
attr_accessor :https_proxy_user
attr_accessor :https_proxy_pass
attr_accessor :no_proxy
def initialize
@validation_client_name = "chef-validator"
@ -87,11 +101,17 @@ module Vagrant
@cookbooks_path = ["cookbooks", [:vm, "cookbooks"]]
@roles_path = []
@provisioning_path = "/tmp/vagrant-chef"
@log_level = :info
@json = {
:instance_role => "vagrant",
}
@json = { :instance_role => "vagrant" }
@http_proxy = nil
@http_proxy_user = nil
@http_proxy_pass = nil
@https_proxy = nil
@https_proxy_user = nil
@https_proxy_pass = nil
@no_proxy = nil
end
# Returns the run list for the provisioning

View File

@ -0,0 +1,57 @@
module Vagrant
module Provisioners
class PuppetServerError < Vagrant::Errors::VagrantError
error_namespace("vagrant.provisioners.puppet_server")
end
class PuppetServerConfig < Vagrant::Config::Base
configures :puppet_server
attr_accessor :puppet_server
attr_accessor :puppet_node
attr_accessor :options
def initialize
@puppet_server = "puppet"
@puppet_node = "puppet_node"
@options = []
end
end
class PuppetServer < Base
def provision!
verify_binary("puppetd")
run_puppetd_client
end
def verify_binary(binary)
vm.ssh.execute do |ssh|
# Checks for the existence of puppetd binary and error if it
# doesn't exist.
ssh.exec!("which #{binary}", :error_class => PuppetServerError, :_key => :puppetd_not_detected, :binary => binary)
end
end
def run_puppetd_client
options = env.config.puppet_server.options
options = options.join(" ") if options.is_a?(Array)
if env.config.puppet_server.puppet_node
cn = env.config.puppet_server.puppet_node
else
cn = env.config.vm.box
end
command = "sudo -E puppetd #{options} --server #{env.config.puppet_server.puppet_server} --certname #{cn}"
env.ui.info I18n.t("vagrant.provisioners.puppet_server.running_puppetd")
vm.ssh.execute do |ssh|
ssh.exec!(command) do |channel, type, data|
ssh.check_exit_status(data, command) if type == :exit_status
env.ui.info("#{data}: #{type}") if type != :exit_status
end
end
end
end
end
end

View File

@ -3,6 +3,8 @@ require 'net/ssh'
require 'net/scp'
require 'mario'
require 'vagrant/ssh/session'
module Vagrant
# Manages SSH access to a specific environment. Allows an environment to
# replace the process with SSH itself, run a specific set of commands,
@ -163,76 +165,4 @@ module Vagrant
return env.config.ssh.port
end
end
class SSH
# A helper class which wraps around `Net::SSH::Connection::Session`
# in order to provide basic command error checking while still
# providing access to the actual session object.
class Session
include Util::Retryable
attr_reader :session
def initialize(session)
@session = session
end
# Executes a given command on the SSH session and blocks until
# the command completes. This is an almost line for line copy of
# the actual `exec!` implementation, except that this
# implementation also reports `:exit_status` to the block if given.
def exec!(command, options=nil, &block)
options = {
:error_check => true
}.merge(options || {})
block ||= Proc.new do |ch, type, data|
check_exit_status(data, command, options) if type == :exit_status && options[:error_check]
ch[:result] ||= ""
ch[:result] << data if [:stdout, :stderr].include?(type)
end
retryable(:tries => 5, :on => IOError, :sleep => 0.5) do
metach = session.open_channel do |channel|
channel.exec(command) do |ch, success|
raise "could not execute command: #{command.inspect}" unless success
# Output stdout data to the block
channel.on_data do |ch2, data|
block.call(ch2, :stdout, data)
end
# Output stderr data to the block
channel.on_extended_data do |ch2, type, data|
block.call(ch2, :stderr, data)
end
# Output exit status information to the block
channel.on_request("exit-status") do |ch2, data|
block.call(ch2, :exit_status, data.read_long)
end
end
end
metach.wait
metach[:result]
end
end
# Checks for an erroroneous exit status and raises an exception
# if so.
def check_exit_status(exit_status, command, options=nil)
if exit_status != 0
options = {
:_error_class => Errors::VagrantError,
:_key => :ssh_bad_exit_status,
:command => command
}.merge(options || {})
raise options[:_error_class], options
end
end
end
end
end

View File

@ -0,0 +1,81 @@
module Vagrant
class SSH
# A helper class which wraps around `Net::SSH::Connection::Session`
# in order to provide basic command error checking while still
# providing access to the actual session object.
class Session
include Util::Retryable
attr_reader :session
def initialize(session)
@session = session
end
# Executes a given command and simply returns true/false if the
# command succeeded or not.
def test?(command)
exec!(command) do |ch, type, data|
return true if type == :exit_status && data == 0
end
false
end
# Executes a given command on the SSH session and blocks until
# the command completes. This is an almost line for line copy of
# the actual `exec!` implementation, except that this
# implementation also reports `:exit_status` to the block if given.
def exec!(command, options=nil, &block)
options = { :error_check => true }.merge(options || {})
block ||= Proc.new do |ch, type, data|
check_exit_status(data, command, options) if type == :exit_status && options[:error_check]
ch[:result] ||= ""
ch[:result] << data if [:stdout, :stderr].include?(type)
end
retryable(:tries => 5, :on => IOError, :sleep => 0.5) do
metach = session.open_channel do |channel|
channel.exec(command) do |ch, success|
raise "could not execute command: #{command.inspect}" unless success
# Output stdout data to the block
channel.on_data do |ch2, data|
block.call(ch2, :stdout, data)
end
# Output stderr data to the block
channel.on_extended_data do |ch2, type, data|
block.call(ch2, :stderr, data)
end
# Output exit status information to the block
channel.on_request("exit-status") do |ch2, data|
block.call(ch2, :exit_status, data.read_long)
end
end
end
metach.wait
metach[:result]
end
end
# Checks for an erroroneous exit status and raises an exception
# if so.
def check_exit_status(exit_status, command, options=nil)
if exit_status != 0
options = {
:_error_class => Errors::VagrantError,
:_key => :ssh_bad_exit_status,
:command => command
}.merge(options || {})
raise options[:_error_class], options
end
end
end
end
end

8
lib/vagrant/systems.rb Normal file
View File

@ -0,0 +1,8 @@
# These can't be autoloaded because they have to register functionality
# with Vagrant core.
require 'vagrant/systems/base'
require 'vagrant/systems/linux'
require 'vagrant/systems/solaris'
require 'vagrant/systems/debian'
require 'vagrant/systems/gentoo'

View File

@ -15,6 +15,10 @@ module Vagrant
# required by systems can and will change at any time. Any
# changes will be noted on release notes.**
class Base
class BaseError < Errors::VagrantError
error_namespace("vagrant.systems.base")
end
include Vagrant::Util
# The VM which this system is tied to.
@ -27,6 +31,15 @@ module Vagrant
@vm = vm
end
# This method is automatically called when the system is available (when
# Vagrant can successfully SSH into the machine) to give the system a chance
# to determine the distro and return a distro-specific system.
#
# **Warning:** If a return value which subclasses from {Base} is
# returned, Vagrant will use it as the new system instance for the
# class.
def distro_dispatch; end
# Halt the machine. This method should gracefully shut down the
# operating system. This method will cause `vagrant halt` and associated
# commands to _block_, meaning that if the machine doesn't halt
@ -55,7 +68,9 @@ module Vagrant
# Prepares the system for host only networks. This is called
# once prior to any `enable_host_only_network` calls.
def prepare_host_only_network; end
def prepare_host_only_network
raise BaseError, :_key => :unsupported_host_only
end
# Setup the system by adding a new host only network. This
# method should configure and bring up the interface for the

View File

@ -0,0 +1,26 @@
module Vagrant
module Systems
class Debian < Linux
def prepare_host_only_network
# Remove any previous host only network additions to the
# interface file.
vm.ssh.execute do |ssh|
# Clear out any previous entries
ssh.exec!("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-interfaces > /etc/network/interfaces'")
end
end
def enable_host_only_network(net_options)
entry = TemplateRenderer.render('network_entry_debian', :net_options => net_options)
vm.ssh.upload!(StringIO.new(entry), "/tmp/vagrant-network-entry")
vm.ssh.execute do |ssh|
ssh.exec!("sudo /sbin/ifdown eth#{net_options[:adapter]} 2> /dev/null")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-entry >> /etc/network/interfaces'")
ssh.exec!("sudo /sbin/ifup eth#{net_options[:adapter]}")
end
end
end
end
end

View File

@ -0,0 +1,27 @@
module Vagrant
module Systems
class Gentoo < Linux
def prepare_host_only_network
# Remove any previous host only network additions to the
# interface file.
vm.ssh.execute do |ssh|
# Clear out any previous entries
ssh.exec!("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/conf.d/net > /tmp/vagrant-network-interfaces")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-interfaces > /etc/conf.d/net'")
end
end
def enable_host_only_network(net_options)
entry = TemplateRenderer.render('network_entry_gentoo', :net_options => net_options)
vm.ssh.upload!(StringIO.new(entry), "/tmp/vagrant-network-entry")
vm.ssh.execute do |ssh|
ssh.exec!("sudo ln -s /etc/init.d/net.lo /etc/init.d/net.eth#{net_options[:adapter]}")
ssh.exec!("sudo /etc/init.d/net.eth#{net_options[:adapter]} stop 2> /dev/null")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-entry >> /etc/conf.d/net'")
ssh.exec!("sudo /etc/init.d/net.eth#{net_options[:adapter]} start")
end
end
end
end
end

View File

@ -1,32 +1,20 @@
require 'vagrant/systems/linux/error'
require 'vagrant/systems/linux/config'
module Vagrant
module Systems
# A general Vagrant system implementation for "linux." In general,
# any linux-based OS will work fine with this system, although its
# not tested exhaustively. BSD or other based systems may work as
# well, but that hasn't been tested at all.
#
# At any rate, this system implementation should server as an
# example of how to implement any custom systems necessary.
class Linux < Base
# A custom config class which will be made accessible via `config.linux`
# This is not necessary for all system implementers, of course. However,
# generally, Vagrant tries to make almost every aspect of its execution
# configurable, and this assists that goal.
class LinuxConfig < Vagrant::Config::Base
configures :linux
attr_accessor :halt_timeout
attr_accessor :halt_check_interval
def initialize
@halt_timeout = 30
@halt_check_interval = 1
end
def distro_dispatch
vm.ssh.execute do |ssh|
return :debian if ssh.test?("cat /etc/debian_version")
return :gentoo if ssh.test?("cat /etc/gentoo-release")
return :redhat if ssh.test?("cat /etc/redhat-release")
end
# Can't detect the distro, assume vanilla linux
nil
end
#-------------------------------------------------------------------
# Overridden methods
#-------------------------------------------------------------------
def halt
vm.env.ui.info I18n.t("vagrant.systems.linux.attempting_halt")
vm.ssh.execute do |ssh|
@ -57,43 +45,7 @@ module Vagrant
folders.each do |name, opts|
vm.ssh.execute do |ssh|
ssh.exec!("sudo mkdir -p #{opts[:guestpath]}")
ssh.exec!("sudo mount #{ip}:#{opts[:hostpath]} #{opts[:guestpath]}")
end
end
end
def prepare_host_only_network(net_options)
# Remove any previous host only network additions to the
# interface file.
vm.ssh.execute do |ssh|
case distribution(ssh)
when :debian
# Clear out any previous entries
ssh.exec!("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-interfaces > /etc/network/interfaces'")
when :redhat
ssh.exec!("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]} > /tmp/vagrant-ifcfg-eth#{net_options[:adapter]}")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-ifcfg-eth#{net_options[:adapter]} > /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]}'")
end
end
end
def enable_host_only_network(net_options)
vm.ssh.execute do |ssh|
case distribution(ssh)
when :debian
entry = TemplateRenderer.render('debian_network_entry', :net_options => net_options)
vm.ssh.upload!(StringIO.new(entry), "/tmp/vagrant-network-entry")
ssh.exec!("sudo /sbin/ifdown eth#{net_options[:adapter]} 2> /dev/null")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-entry >> /etc/network/interfaces'")
ssh.exec!("sudo /sbin/ifup eth#{net_options[:adapter]}")
when :redhat
entry = TemplateRenderer.render('redhat_network_entry', :net_options => net_options)
vm.ssh.upload!(StringIO.new(entry), "/tmp/vagrant-network-entry")
ssh.exec!("sudo /sbin/ifdown eth#{net_options[:adapter]} 2> /dev/null")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-entry >> /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]}'")
ssh.exec!("sudo /sbin/ifup eth#{net_options[:adapter]}")
ssh.exec!("sudo mount #{ip}:#{opts[:hostpath]} #{opts[:guestpath]}", :error_class => LinuxError, :_key => :mount_nfs_fail)
end
end
end
@ -122,36 +74,6 @@ module Vagrant
sleep sleeptime
end
end
def debian?(ssh)
ssh.exec!("test -e /etc/debian_version") do |ch, type, data|
return true if type == :exit_status && data == 0
end
false
end
def redhat?(ssh)
ssh.exec!("test -e /etc/redhat-release") do |ch, type, data|
return true if type == :exit_status && data == 0
end
false
end
def distribution(ssh)
if debian?(ssh)
:debian
elsif redhat?(ssh)
:redhat
else
raise LinuxError.new(:distribution_not_supported)
end
end
end
class Linux < Base
class LinuxError < Errors::VagrantError
error_namespace("vagrant.systems.linux")
end
end
end
end

View File

@ -0,0 +1,21 @@
module Vagrant
module Systems
class Linux < Vagrant::Systems::Base
# A custom config class which will be made accessible via `config.linux`
# This is not necessary for all system implementers, of course. However,
# generally, Vagrant tries to make almost every aspect of its execution
# configurable, and this assists that goal.
class LinuxConfig < Vagrant::Config::Base
configures :linux
attr_accessor :halt_timeout
attr_accessor :halt_check_interval
def initialize
@halt_timeout = 30
@halt_check_interval = 1
end
end
end
end
end

View File

@ -0,0 +1,9 @@
module Vagrant
module Systems
class Linux < Vagrant::Systems::Base
class LinuxError < Errors::VagrantError
error_namespace("vagrant.systems.linux")
end
end
end
end

View File

@ -0,0 +1,30 @@
module Vagrant
module Systems
class Redhat < Linux
def prepare_host_only_network(net_options = nil)
# Remove any previous host only network additions to the
# interface file.
vm.ssh.execute do |ssh|
# Clear out any previous entries
#ssh.exec!("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]} > /tmp/vagrant-ifcfg-eth#{net_options[:adapter]}")
#ssh.exec!("sudo su -c 'cat /tmp/vagrant-ifcfg-eth#{net_options[:adapter]} > /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]}'")
end
end
def enable_host_only_network(net_options)
entry = TemplateRenderer.render('network_entry_redhat', :net_options => net_options)
vm.ssh.upload!(StringIO.new(entry), "/tmp/vagrant-network-entry")
vm.ssh.execute do |ssh|
ssh.exec!("sudo /sbin/ifdown eth#{net_options[:adapter]} 2> /dev/null")
ssh.exec!("sudo su -c 'cat /tmp/vagrant-network-entry >> /etc/sysconfig/network-scripts/ifcfg-eth#{net_options[:adapter]}'")
ssh.exec!("sudo /sbin/ifup eth#{net_options[:adapter]}")
end
end
end
end
end

View File

@ -31,8 +31,8 @@ module Vagrant
str = args.shift || ""
File.open(path.to_s, "w") do |f|
f.puts "ENV['VAGRANT_HOME'] = '#{home_path}'"
f.puts "Vagrant::Config.run do |config|"
f.puts "config.vagrant.home = '#{home_path}'"
f.puts "config.vm.base_mac = 'foo' if !config.vm.base_mac"
f.puts "config.vm.box = 'base'"
f.puts str

View File

@ -1,24 +0,0 @@
module Vagrant
module Util
# Eases the processes of loading specific files then globbing
# the rest from a specified directory.
module GlobLoader
# Glob requires all ruby files in a directory, optionally loading select
# files initially (since others may depend on them).
#
# @param [String] dir The directory to glob
# @param [Array<String>] initial_files Initial files (relative to `dir`)
# to load
def self.glob_require(dir, initial_files=[])
initial_files.each do |file|
require File.expand_path(file, dir)
end
# Glob require the rest
Dir[File.join(dir, "**", "*.rb")].each do |f|
require File.expand_path(f)
end
end
end
end
end

View File

@ -3,7 +3,6 @@ module Vagrant
include Vagrant::Util
attr_reader :env
attr_reader :system
attr_reader :name
attr_reader :vm
@ -41,6 +40,8 @@ module Vagrant
# Load the associated system.
load_system!
end
@loaded_system_distro = false
end
# Loads the system associated with the VM. The system class is
@ -48,15 +49,20 @@ module Vagrant
# can be found by reading the documentation on {Vagrant::Systems::Base}.
#
# **This method should never be called manually.**
def load_system!
system = env.config.vm.system
def load_system!(system=nil)
system ||= env.config.vm.system
if system.is_a?(Class)
@system = system.new(self)
raise Errors::VMSystemError, :_key => :invalid_class, :system => system.to_s if !@system.is_a?(Systems::Base)
elsif system.is_a?(Symbol)
# Hard-coded internal systems
mapping = { :linux => Systems::Linux, :solaris => Systems::Solaris }
mapping = {
:debian => Systems::Debian,
:gentoo => Systems::Gentoo,
:linux => Systems::Linux,
:solaris => Systems::Solaris
}
raise Errors::VMSystemError, :_key => :unknown_type, :system => system.to_s if !mapping.has_key?(system)
@system = mapping[system].new(self)
@ -65,6 +71,19 @@ module Vagrant
end
end
# Returns the system for this VM, loading the distro of the system if
# we can.
def system
if !@loaded_system_distro && created? && vm.running?
# Load the system distro for the first time
result = @system.distro_dispatch
load_system!(result)
@loaded_system_distro = true
end
@system
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.

BIN
templates/.DS_Store vendored

Binary file not shown.

View File

@ -6,6 +6,14 @@ cookbook_path <%= cookbooks_path %>
role_path <%= roles_path %>
log_level <%= log_level.inspect %>
<% if recipe_url %>
<% if recipe_url -%>
recipe_url "<%= recipe_url %>"
<% end %>
<% end -%>
http_proxy <%= http_proxy.inspect %>
http_proxy_user <%= http_proxy_user.inspect %>
http_proxy_pass <%= http_proxy_pass.inspect %>
https_proxy <%= https_proxy.inspect %>
https_proxy_user <%= https_proxy_user.inspect %>
https_proxy_pass <%= https_proxy_pass.inspect %>
no_proxy <%= no_proxy.inspect %>

View File

@ -16,6 +16,9 @@ en:
puppet_not_detected: |-
The `puppet` binary was not found on the VM and is required for Puppet provisioning.
Please verify that Puppet is installed and that the binary is available on the PATH.
puppetd_not_detected: |-
The `puppetd` binary was not found on the VM is required for Puppet Server provisioning.
Please verify that Puppet is installed and that the binary is available on the PATH.
cli_missing_env: This command requires that a Vagrant environment be properly passed in as the last parameter.
config_validation: |-
There was a problem with the configuration of Vagrant. The error message(s)
@ -89,11 +92,6 @@ en:
message is reproduced below for convenience:
%{file}
virtualbox_invalid_ose: |-
Vagrant has detected you're using an OSE ("Open Source Edition") of VirtualBox.
Vagrant currently doesn't support any of the OSE editions due to slight API
differences. Please download the regular package from virtualbox.org and install
to continue.
virtualbox_invalid_version: |-
Vagrant has detected that you have VirtualBox version %{version} installed!
Vagrant requires that you use at least VirtualBox version 4.0. Please install
@ -453,20 +451,34 @@ en:
manifest_to_run: "Puppet will use the %{manifest} manifest to configure your box."
manifest_missing: "The Puppet %{manifest} manifest is missing. You cannot configure this box."
puppet_server:
not_detected: |-
The `%{binary}` binary appears to not be in the PATH of the guest. This
could be because the PATH is not properly setup or perhaps Puppet is not
installed on this guest. Puppet provisioning can not continue without
Puppet properly installed.
running_puppetd: "Running Puppet agent..."
systems:
base:
unsupported_host_only: |-
Host only networking is very distro-specific. Vagrant has support for many
distros built-in: Debian, Ubuntu, Gentoo, and RedHat. The distro of your VM
couldn't be detected, or isn't supported for host only networking.
Most of the time this is simply due to the fact that no one has contributed
back the SSH commands necessary to set this up. Please report a bug and this
will be fixed for your distro.
linux:
attempting_halt: "Attempting graceful shutdown of linux..."
mount_fail: "Failed to mount shared folders. `vboxsf` was not available."
distribution_not_supported: |-
Host only networking is only supported for Debian/Ubuntu and Redhat Distributions by the built-in
"Linux" system. If you're using some other distro and want to implement
host only networking, please subclass the `Vagrant::Systems::Linux` class
and implement the `prepare_host_only_network` and `enable_host_only_network`
methods.
Otherwise, please report your distro and how to modify network interfaces
to the Vagrant mailing list or IRC and we'll probably be glad to add it
to the internal systems.
mount_nfs_fail: |-
Mounting NFS shared folders failed. This is most often caused by the NFS
client software not being installed on the guest machine. Please verify
that the NFS client software is properly installed, and consult any resources
specific to the linux distro you're using for more information on how to
do this.
solaris:
attempting_halt: "Attempting graceful shutdown of solaris..."

View File

@ -0,0 +1,7 @@
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant.
# Please do not modify any of these contents.
config_eth<%= net_options[:adapter] %>=("<%= net_options[:ip] %> netmask <%= net_options[:netmask] %>")
#VAGRANT-END
~

View File

@ -107,6 +107,10 @@ class ProvisionVMActionTest < Test::Unit::TestCase
should "set :puppet to the Puppet provisioner" do
provisioner_expectation(:puppet, Vagrant::Provisioners::Puppet)
end
should "set :puppet_server to the Puppet Server provisioner" do
provisioner_expectation(:puppet_server, Vagrant::Provisioners::PuppetServer)
end
end
end

View File

@ -8,7 +8,6 @@ class ConfigVagrantTest < Test::Unit::TestCase
context "validation" do
setup do
@config.dotfile_name = "foo"
@config.home = "foo"
@config.host = "foo"
@errors = Vagrant::Config::ErrorRecorder.new
@ -26,13 +25,6 @@ class ConfigVagrantTest < Test::Unit::TestCase
assert !@errors.errors.empty?
end
should "be invalid with no home" do
@config.home = nil
@config.validate(@errors)
assert !@errors.errors.empty?
end
should "be invalid with no host" do
@config.host = nil

View File

@ -5,120 +5,83 @@ class ConfigTest < Test::Unit::TestCase
@klass = Vagrant::Config
end
context "with the class" do
should "allow access to the last proc" do
foo = mock("object")
foo.expects(:call).once
@klass.run { |config| foo.call }
value = @klass.last_proc.first
assert value.is_a?(Proc)
value.call(nil)
assert @klass.last_proc.nil?
end
end
context "with an instance" do
setup do
@env = vagrant_env
@instance = @klass.new(@env)
# @env = vagrant_env
@instance = @klass.new
end
should "initially have an empty queue" do
assert @instance.queue.empty?
should "load the config files in the given order" do
names = %w{alpha beta gamma}
@instance.load_order = [:alpha, :beta]
names.each do |name|
vagrantfile(vagrant_box(name), "config.vm.box = '#{name}'")
@instance.set(name.to_sym, vagrant_box(name).join("Vagrantfile"))
end
should "reset the config class on load, then execute" do
seq = sequence("sequence")
@klass.expects(:reset!).with(@env).in_sequence(seq)
@klass.expects(:execute!).in_sequence(seq)
@instance.load!
config = @instance.load(nil)
assert_equal "beta", config.vm.box
end
should "run the queue in the order given" do
@instance.queue << Proc.new { |config| config.vm.box = "foo" }
@instance.queue << Proc.new { |config| config.vm.box = "bar" }
result = @instance.load!
should "load the config as procs" do
@instance.set(:proc, Proc.new { |config| config.vm.box = "proc" })
@instance.load_order = [:proc]
config = @instance.load(nil)
assert_equal "bar", result.vm.box
assert_equal "proc", config.vm.box
end
should "allow nested arrays" do
queue = []
queue << Proc.new { |config| config.vm.box = "foo" }
queue << Proc.new { |config| config.vm.box = "bar" }
@instance.queue << queue
result = @instance.load!
should "load an array of procs" do
@instance.set(:proc, [Proc.new { |config| config.vm.box = "proc" },
Proc.new { |config| config.vm.box = "proc2" }])
@instance.load_order = [:proc]
config = @instance.load(nil)
assert_equal "bar", result.vm.box
assert_equal "proc2", config.vm.box
end
should "load a file if it exists" do
filename = "foo"
File.expects(:exist?).with(filename).returns(true)
@instance.expects(:load).with(filename).once
@instance.queue << filename
@instance.load!
should "not care if a file doesn't exist" do
@instance.load_order = [:foo]
assert_nothing_raised { @instance.set(:foo, "i/dont/exist") }
assert_nothing_raised { @instance.load(nil) }
end
should "not load a file if it doesn't exist" do
filename = "foo"
File.expects(:exist?).with(filename).returns(false)
@instance.expects(:load).with(filename).never
should "not reload a file" do
foo_path = vagrant_box("foo").join("Vagrantfile")
@instance.queue << filename
@instance.load!
vagrantfile(vagrant_box("foo"))
@instance.set(:foo, foo_path)
# Nothing should be raised in this case because the file isn't reloaded
vagrantfile(vagrant_box("foo"), "^%&8318")
assert_nothing_raised { @instance.set(:foo, foo_path) }
end
should "raise an exception if there is a syntax error in a file" do
@instance.queue << "foo"
File.expects(:exist?).with("foo").returns(true)
@instance.expects(:load).with("foo").raises(SyntaxError.new)
vagrantfile(vagrant_box("foo"), "^%&8318")
assert_raises(Vagrant::Errors::VagrantfileSyntaxError) {
@instance.load!
@instance.set(:foo, vagrant_box("foo").join("Vagrantfile"))
}
end
end
context "resetting" do
setup do
@klass.reset!(vagrant_env)
@klass::Top.any_instance.stubs(:validate!)
@klass.run { |config| }
@klass.execute!
end
should "return the same config object typically" do
config = @klass.config
assert config.equal?(@klass.config)
end
should "create a new object if cleared" do
config = @klass.config
@klass.reset!
assert !config.equal?(@klass.config)
end
should "empty the proc stack" do
assert !@klass.proc_stack.empty?
@klass.reset!
assert @klass.proc_stack.empty?
end
should "reload the config object based on the given environment" do
env = mock("env")
@klass.expects(:config).with(env).once
@klass.reset!(env)
end
end
context "initializing" do
setup do
@klass.reset!(vagrant_env)
end
should "add the given block to the proc stack" do
proc = Proc.new {}
@klass.run(&proc)
assert_equal [proc], @klass.proc_stack
end
should "return the configuration on execute!" do
@klass.run {}
result = @klass.execute!
assert result.is_a?(@klass::Top)
end
end
context "top config class" do
setup do
@configures_list = {}

View File

@ -4,6 +4,8 @@ require "pathname"
class EnvironmentTest < Test::Unit::TestCase
setup do
@klass = Vagrant::Environment
clean_paths
end
context "class method check virtualbox version" do
@ -26,12 +28,6 @@ class EnvironmentTest < Test::Unit::TestCase
VirtualBox.expects(:version).returns(version)
assert_raises(Vagrant::Errors::VirtualBoxInvalidVersion) { @klass.check_virtualbox! }
end
should "error and exit for OSE VirtualBox" do
version = "4.0.0_OSE"
VirtualBox.expects(:version).returns(version)
assert_raises(Vagrant::Errors::VirtualBoxInvalidOSE) { @klass.check_virtualbox! }
end
end
context "initialization" do
@ -59,8 +55,21 @@ class EnvironmentTest < Test::Unit::TestCase
end
context "home path" do
setup do
@env = @klass.new
end
should "return the home path if it loaded" do
expected = Pathname.new(File.expand_path(@env.config.vagrant.home, @env.root_path))
ENV["VAGRANT_HOME"] = nil
expected = Pathname.new(File.expand_path(@klass::DEFAULT_HOME))
assert_equal expected, @env.home_path
end
should "return the home path set by the environmental variable" do
ENV["VAGRANT_HOME"] = "foo"
expected = Pathname.new(File.expand_path(ENV["VAGRANT_HOME"]))
assert_equal expected, @env.home_path
end
end
@ -391,7 +400,7 @@ class EnvironmentTest < Test::Unit::TestCase
create_box_vagrantfile
vagrantfile(@env.root_path, "config.vm.box = 'box'")
assert_equal "box.box", @env.config.package.name
assert_equal "box.box", @env.primary_vm.env.config.package.name
end
should "load from home path if exists" do

View File

@ -0,0 +1,64 @@
require "test_helper"
class PuppetServerProvisionerTest < Test::Unit::TestCase
setup do
@action_env = Vagrant::Action::Environment.new(vagrant_env.vms[:default].env)
@action = Vagrant::Provisioners::PuppetServer.new(@action_env)
@env = @action.env
@vm = @action.vm
end
context "provisioning" do
should "run the proper sequence of methods in order" do
prov_seq = sequence("prov_seq")
@action.expects(:verify_binary).with("puppetd").once.in_sequence(prov_seq)
@action.expects(:run_puppetd_client).once.in_sequence(prov_seq)
@action.provision!
end
end
context "verifying binary" do
setup do
@ssh = mock("ssh")
@vm.ssh.stubs(:execute).yields(@ssh)
end
should "verify binary exists" do
binary = "foo"
@ssh.expects(:exec!).with("which #{binary}", anything)
@action.verify_binary(binary)
end
end
context "running puppetd client" do
setup do
@cn = "puppet_node"
@ssh = mock("ssh")
@vm.ssh.stubs(:execute).yields(@ssh)
end
should "run the puppetd client" do
@ssh.expects(:exec!).with("sudo -E puppetd --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once
@action.run_puppetd_client
end
should "run puppetd with given options when given as an array" do
@env.config.puppet_server.options = ["--modulepath", "modules", "--verbose"]
@ssh.expects(:exec!).with("sudo -E puppetd --modulepath modules --verbose --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once
@action.run_puppetd_client
end
should "run puppetd with the options when given as a string" do
@env.config.puppet_server.options = "--modulepath modules --verbose"
@ssh.expects(:exec!).with("sudo -E puppetd --modulepath modules --verbose --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once
@action.run_puppetd_client
end
should "check the exit status if that is given" do
@ssh.stubs(:exec!).yields(nil, :exit_status, :foo)
@ssh.expects(:check_exit_status).with(:foo, anything).once
@action.run_puppetd_client
end
end
end

View File

@ -0,0 +1,18 @@
require "test_helper"
class BaseSystemTest < Test::Unit::TestCase
setup do
@klass = Vagrant::Systems::Base
@vm = mock("vm")
@instance = @klass.new(@vm)
end
should "provide access to the VM" do
assert_equal @vm, @instance.vm
end
should "error on preparing host only network" do
assert_raises(@klass::BaseError) { @instance.prepare_host_only_network }
end
end

View File

@ -43,37 +43,6 @@ class LinuxSystemTest < Test::Unit::TestCase
end
end
context "prepare host only network" do
setup do
@ssh_session = mock("ssh_session")
@ssh.stubs(:execute).yields(@ssh_session)
@vm.stubs(:ssh).returns(@ssh)
end
should "determin distribution debian, clear out any previous entries for adapter, then create interfaces" do
prepare_seq = sequence("prepare_seq")
@instance.expects(:distribution).returns(:debian).in_sequence(prepare_seq)
@ssh_session.expects(:exec!).with("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces").in_sequence(prepare_seq)
@ssh_session.expects(:exec!).with("sudo su -c 'cat /tmp/vagrant-network-interfaces > /etc/network/interfaces'").in_sequence(prepare_seq)
@instance.prepare_host_only_network({})
end
should "determin distribution redhat, clear out any previous entries for adapter, then create interfaces" do
prepare_seq = sequence("prepare_seq")
@instance.expects(:distribution).returns(:redhat).in_sequence(prepare_seq)
@ssh_session.expects(:exec!).with("sudo sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/sysconfig/network-scripts/ifcfg-eth1 > /tmp/vagrant-ifcfg-eth1").in_sequence(prepare_seq)
@ssh_session.expects(:exec!).with("sudo su -c 'cat /tmp/vagrant-ifcfg-eth1 > /etc/sysconfig/network-scripts/ifcfg-eth1'").in_sequence(prepare_seq)
@instance.prepare_host_only_network({:adapter => 1})
end
should "determin distribution not supported" do
@instance.expects(:distribution).raises(Vagrant::Systems::Linux::LinuxError)
assert_raises(Vagrant::Systems::Linux::LinuxError) {
@instance.prepare_host_only_network({})
}
end
end
#-------------------------------------------------------------------
# "Private" methods tests
#-------------------------------------------------------------------
@ -142,54 +111,4 @@ class LinuxSystemTest < Test::Unit::TestCase
mount_folder
end
end
context "determine distribution" do
setup do
@debian_test_command = "test -e /etc/debian_version"
@redhat_test_command = "test -e /etc/redhat-release"
end
should "is debian" do
@ssh.expects(:exec!).with(@debian_test_command).yields(nil, :exit_status, 0)
assert_equal true, @instance.debian?(@ssh)
end
should "is not debian" do
@ssh.expects(:exec!).with(@debian_test_command).yields(nil, :exit_status, 1)
assert_equal false, @instance.debian?(@ssh)
end
should "is redhat" do
@ssh.expects(:exec!).with(@redhat_test_command).yields(nil, :exit_status, 0)
assert_equal true, @instance.redhat?(@ssh)
end
should "is not redhat" do
@ssh.expects(:exec!).with(@redhat_test_command).yields(nil, :exit_status, 1)
assert_equal false, @instance.redhat?(@ssh)
end
should "debian selected" do
@instance.expects(:debian?).returns(true)
@instance.expects(:redhat?).never()
assert_equal :debian, @instance.distribution(@ssh)
end
should "redhat selected" do
check_seq = sequence("check_seq")
@instance.expects(:debian?).returns(false).in_sequence(check_seq)
@instance.expects(:redhat?).returns(true).in_sequence(check_seq)
assert_equal :redhat, @instance.distribution(@ssh)
end
should "not supported" do
check_seq = sequence("check_seq")
@instance.expects(:debian?).returns(false).in_sequence(check_seq)
@instance.expects(:redhat?).returns(false).in_sequence(check_seq)
assert_raises(Vagrant::Systems::Linux::LinuxError) {
@instance.distribution(@ssh)
}
end
end
end

View File

@ -25,6 +25,7 @@ class VMTest < Test::Unit::TestCase
setup do
@vm_name = "foo"
@mock_vm = mock("vm")
@mock_vm.stubs(:running?).returns(false)
@vm = Vagrant::VM.new(:env => @env, :vm => @mock_vm, :name => @vm_name)
@mock_vm.stubs(:uuid).returns("foo")
end
@ -96,11 +97,14 @@ class VMTest < Test::Unit::TestCase
}
end
context "with a class" do
class FakeSystemClass
def initialize(vm); end
should "load the given system if specified" do
fake_class = Class.new(Vagrant::Systems::Base)
assert_nothing_raised { @vm.load_system!(fake_class) }
assert @vm.system.is_a?(fake_class)
end
context "with a class" do
should "initialize class if given" do
@vm.env.config.vm.system = Vagrant::Systems::Linux
@ -109,7 +113,7 @@ class VMTest < Test::Unit::TestCase
end
should "raise error if class has invalid parent" do
@vm.env.config.vm.system = FakeSystemClass
@vm.env.config.vm.system = Class.new
assert_raises(Vagrant::Errors::VMSystemError) {
@vm.load_system!
}
@ -140,6 +144,30 @@ class VMTest < Test::Unit::TestCase
}
end
end
context "loading the distro" do
setup do
@vm.vm.stubs(:running?).returns(true)
end
should "not replace the distro if it is nil" do
@vm.env.config.vm.system = Class.new(Vagrant::Systems::Base)
@vm.load_system!
assert @vm.system.is_a?(@vm.env.config.vm.system)
end
should "replace the distro if it is not nil" do
@vm.env.config.vm.system = Class.new(Vagrant::Systems::Base) do
def distro_dispatch
:linux
end
end
@vm.load_system!
assert @vm.system.is_a?(Vagrant::Systems::Linux)
end
end
end
context "uuid" do

View File

@ -1,4 +1,5 @@
require File.expand_path("../lib/vagrant/version", __FILE__)
$:.unshift File.expand_path("../lib", __FILE__)
require "vagrant/version"
Gem::Specification.new do |s|
s.name = "vagrant"
@ -18,10 +19,10 @@ Gem::Specification.new do |s|
s.add_dependency "json", "~> 1.4.6"
s.add_dependency "mario", "~> 0.0.6"
s.add_dependency "net-ssh", "~> 2.0.23"
s.add_dependency "net-scp", "~> 1.0.3"
s.add_dependency "i18n", "~> 0.4.1"
s.add_dependency "thor", "~> 0.14.2"
s.add_dependency "virtualbox", "~> 0.8.0"
s.add_dependency "net-scp", "~> 1.0.4"
s.add_dependency "i18n", "~> 0.5.0"
s.add_dependency "thor", "~> 0.14.6"
s.add_dependency "virtualbox", "~> 0.8.1"
s.add_development_dependency "rake"
s.add_development_dependency "contest", ">= 0.1.2"