core: Vagrantfile can create machines, Environment#machine uses that

This commit is contained in:
Mitchell Hashimoto 2014-02-06 21:31:11 -08:00
parent 506e1a433f
commit 3533256cd7
4 changed files with 134 additions and 73 deletions

View File

@ -301,45 +301,16 @@ module Vagrant
@logger.info("Uncached load of machine.")
# Load the actual configuration for the machine
results = vagrantfile.machine_config(name, provider, boxes)
box = results[:box]
config = results[:config]
config_errors = results[:config_errors]
config_warnings = results[:config_warnings]
provider_cls = results[:provider_cls]
provider_options = results[:provider_options]
# Determine the machine data directory and pass it to the machine.
# XXX: Permissions error here.
machine_data_path = @local_data_path.join(
"machines/#{name}/#{provider}")
FileUtils.mkdir_p(machine_data_path)
# If there were warnings or errors we want to output them
if !config_warnings.empty? || !config_errors.empty?
# The color of the output depends on whether we have warnings
# or errors...
level = config_errors.empty? ? :warn : :error
output = Util::TemplateRenderer.render(
"config/messages",
:warnings => config_warnings,
:errors => config_errors).chomp
@ui.send(level, I18n.t("vagrant.general.config_upgrade_messages",
name: name,
:output => output))
# If we had errors, then we bail
raise Errors::ConfigUpgradeErrors if !config_errors.empty?
end
# Get the provider configuration from the final loaded configuration
provider_config = config.vm.get_provider_config(provider)
# Create the machine and cache it for future calls. This will also
# return the machine from this method.
@machines[cache_key] = Machine.new(name, provider, provider_cls, provider_config,
provider_options, config, machine_data_path, box, self)
@machines[cache_key] = vagrantfile.machine(
name, provider, boxes, machine_data_path, self)
end
# This returns a list of the configured machines for this environment.

View File

@ -34,7 +34,7 @@ module Vagrant
# Name of the machine. This is assigned by the Vagrantfile.
#
# @return [String]
# @return [Symbol]
attr_reader :name
# The provider backing this machine.

View File

@ -1,3 +1,5 @@
require "vagrant/util/template_renderer"
module Vagrant
# This class provides a way to load and access the contents
# of a Vagrantfile.
@ -26,6 +28,54 @@ module Vagrant
@config, _ = loader.load(keys)
end
# Returns a {Machine} for the given name and provider that
# is represented by this Vagrantfile.
#
# @param [Symbol] name Name of the machine.
# @param [Symbol] provider The provider the machine should
# be backed by (required for provider overrides).
# @param [BoxCollection] boxes BoxCollection to look up the
# box Vagrantfile.
# @param [Pathname] data_path Path where local machine data
# can be stored.
# @param [Environment] env The environment running this machine
# @return [Machine]
def machine(name, provider, boxes, data_path, env)
# Load the configuration for the machine
results = machine_config(name, provider, boxes)
box = results[:box]
config = results[:config]
config_errors = results[:config_errors]
config_warnings = results[:config_warnings]
provider_cls = results[:provider_cls]
provider_options = results[:provider_options]
# If there were warnings or errors we want to output them
if !config_warnings.empty? || !config_errors.empty?
# The color of the output depends on whether we have warnings
# or errors...
level = config_errors.empty? ? :warn : :error
output = Util::TemplateRenderer.render(
"config/messages",
:warnings => config_warnings,
:errors => config_errors).chomp
env.ui.send(level, I18n.t("vagrant.general.config_upgrade_messages",
name: name,
output: output))
# If we had errors, then we bail
raise Errors::ConfigUpgradeErrors if !config_errors.empty?
end
# Get the provider configuration from the final loaded configuration
provider_config = config.vm.get_provider_config(provider)
# Create the machine and cache it for future calls. This will also
# return the machine from this method.
return Machine.new(name, provider, provider_cls, provider_config,
provider_options, config, data_path, box, env)
end
# Returns the configuration for a single machine.
#
# When loading a box Vagrantfile, it will be prepended to the
@ -38,11 +88,23 @@ module Vagrant
# - sub-machine
# - provider
#
# The return value is a hash with the following keys (symbols)
# and values:
#
# - box: the {Box} backing the machine
# - config: the actual configuration
# - config_errors: list of errors, if any
# - config_warnings: list of warnings, if any
# - provider_cls: class of the provider backing the machine
# - provider_options: options for the provider
#
# @param [Symbol] name Name of the machine.
# @param [Symbol] provider The provider the machine should
# be backed by (required for provider overrides).
# @param [BoxCollection] boxes BoxCollection to look up the
# box Vagrantfile.
# @return [Hash<Symbol, Object>] Various configuration parameters for a
# machine. See the main documentation body for more info.
def machine_config(name, provider, boxes)
keys = @keys.dup

View File

@ -1,5 +1,8 @@
require File.expand_path("../../base", __FILE__)
require "pathname"
require "tmpdir"
require "vagrant/vagrantfile"
describe Vagrant::Vagrantfile do
@ -13,15 +16,30 @@ describe Vagrant::Vagrantfile do
subject { described_class.new(loader, keys) }
before do
keys << :test
end
def configure(&block)
loader.set(:test, [["2", block]])
end
# A helper to register a provider for use in tests.
def register_provider(name, config_class=nil, options=nil)
provider_cls = Class.new(Vagrant.plugin("2", :provider))
register_plugin("2") do |p|
p.provider(name, options) { provider_cls }
if config_class
p.config(name, :provider) { config_class }
end
end
provider_cls
end
describe "#config" do
before do
keys << :test
end
def configure(&block)
loader.set(:test, [["2", block]])
end
it "exposes the global configuration" do
configure do |config|
config.vm.box = "what"
@ -31,33 +49,59 @@ describe Vagrant::Vagrantfile do
end
end
describe "#machine_config" do
let(:iso_env) { isolated_environment }
describe "#machine" do
let(:boxes) { Vagrant::BoxCollection.new(iso_env.boxes_dir) }
let(:data_path) { Pathname.new(Dir.mktmpdir) }
let(:env) { iso_env.create_vagrant_env }
let(:iso_env) { isolated_environment }
subject { super().machine(:default, :foo, boxes, data_path, env) }
before do
keys << :test
end
@foo_config_cls = Class.new(Vagrant.plugin("2", "config")) do
attr_accessor :value
end
def configure(&block)
loader.set(:test, [["2", block]])
end
@provider_cls = register_provider("foo", @foo_config_cls)
# A helper to register a provider for use in tests.
def register_provider(name, config_class=nil, options=nil)
provider_cls = Class.new(Vagrant.plugin("2", :provider))
register_plugin("2") do |p|
p.provider(name, options) { provider_cls }
if config_class
p.config(name, :provider) { config_class }
configure do |config|
config.vm.box = "foo"
config.vm.provider "foo" do |p|
p.value = "rawr"
end
end
provider_cls
iso_env.box3("foo", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
end
its(:data_dir) { should eq(data_path) }
its(:env) { should equal(env) }
its(:name) { should eq(:default) }
its(:provider) { should be_kind_of(@provider_cls) }
its(:provider_name) { should eq(:foo) }
it "has the proper box" do
expect(subject.box.name).to eq("foo")
end
it "has the valid configuration" do
expect(subject.config.vm.box).to eq("foo")
end
it "loads the provider-specific configuration" do
expect(subject.provider_config).to be_kind_of(@foo_config_cls)
expect(subject.provider_config.value).to eq("rawr")
end
end
describe "#machine_config" do
let(:iso_env) { isolated_environment }
let(:boxes) { Vagrant::BoxCollection.new(iso_env.boxes_dir) }
it "should return a basic configured machine" do
provider_cls = register_provider("foo")
@ -232,14 +276,6 @@ describe Vagrant::Vagrantfile do
end
describe "#machine_names" do
before do
keys << :test
end
def configure(&block)
loader.set(:test, [["2", block]])
end
it "returns the default name when single-VM" do
configure { |config| }
@ -258,14 +294,6 @@ describe Vagrant::Vagrantfile do
end
describe "#primary_machine_name" do
before do
keys << :test
end
def configure(&block)
loader.set(:test, [["2", block]])
end
it "returns the default name when single-VM" do
configure { |config| }