From 3204b3a580f1064a5b3de68b2f9559a11ec9ed53 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 21 May 2012 21:47:01 -0700 Subject: [PATCH] Vagrant.configure and versioned configuration Vagrant.configure is now how configuration is done in Vagrantfiles (previously it was Vagrant::Config.run). This function takes a single argument which is the version of configuration to use. Various internals were updated for this new versioned configuration. Note that multiple versions of configuration aren't yet used so aren't fully supported by Vagrant, but the foundation is being set here. --- lib/vagrant.rb | 12 ++++++++ lib/vagrant/config.rb | 4 +-- lib/vagrant/config/loader.rb | 11 ++++--- templates/commands/init/Vagrantfile.erb | 4 +-- test/unit/vagrant/config_test.rb | 41 ++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 7adf8402f..cc10d327c 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -92,6 +92,18 @@ module Vagrant @source_root ||= Pathname.new(File.expand_path('../../', __FILE__)) end + # Configure a Vagrant environment. The version specifies the version + # of the configuration that is expected by the block. The block, based + # on that version, configures the environment. + # + # Note that the block isn't run immediately. Instead, the configuration + # block is stored until later, and is run when an environment is loaded. + # + # @param [String] version Version of the configuration + def self.configure(version, &block) + Config.run(version, &block) + end + # Returns a superclass to use when creating a plugin for Vagrant. # Given a specific version, this returns a proper superclass to use # to register plugins for that version. diff --git a/lib/vagrant/config.rb b/lib/vagrant/config.rb index a6aef45aa..71b4e5b48 100644 --- a/lib/vagrant/config.rb +++ b/lib/vagrant/config.rb @@ -32,10 +32,10 @@ module Vagrant # # Note that the block is not run immediately. Instead, it's proc is stored # away for execution later. - def self.run(&block) + def self.run(version="1", &block) # Store it for later @last_procs ||= [] - @last_procs << block + @last_procs << [version, block] end # This is a method which will yield to a block and will capture all diff --git a/lib/vagrant/config/loader.rb b/lib/vagrant/config/loader.rb index e2df7ef04..fceed7d55 100644 --- a/lib/vagrant/config/loader.rb +++ b/lib/vagrant/config/loader.rb @@ -80,11 +80,10 @@ module Vagrant @load_order.each do |key| next if !@sources.has_key?(key) - @sources[key].each do |proc| + @sources[key].each do |version, proc| if !@config_cache.has_key?(proc) @logger.debug("Loading from: #{key} (evaluating)") - current = current_config_klass.load(proc) - @config_cache[proc] = current + @config_cache[proc] = current_config_klass.load(proc) else @logger.debug("Loading from: #{key} (cache)") end @@ -105,7 +104,11 @@ module Vagrant # the configuration object and are expected to mutate this # configuration object. def procs_for_source(source) - return [source] if source.is_a?(Proc) + # If the source is just a proc, we assume it is for the latest + # version of the configuration. This may be an ill assumption, + # but it made building the initial version of multi-versioned + # configuration easy to support the old sub-VM stuff. + return [[Config::VERSIONS_ORDER.last, source]] if source.is_a?(Proc) # Assume all string sources are actually pathnames source = Pathname.new(source) if source.is_a?(String) diff --git a/templates/commands/init/Vagrantfile.erb b/templates/commands/init/Vagrantfile.erb index d0cfa0d8a..ce577b14b 100644 --- a/templates/commands/init/Vagrantfile.erb +++ b/templates/commands/init/Vagrantfile.erb @@ -1,7 +1,7 @@ # -*- mode: ruby -*- # vi: set ft=ruby : -Vagrant::Config.run do |config| +Vagrant.configure("1") do |config| # All Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. @@ -60,7 +60,7 @@ Vagrant::Config.run do |config| # end # Enable provisioning with chef solo, specifying a cookbooks path, roles - # path, and data_bags path (all relative to this Vagrantfile), and adding + # path, and data_bags path (all relative to this Vagrantfile), and adding # some recipes and/or roles. # # config.vm.provision :chef_solo do |chef| diff --git a/test/unit/vagrant/config_test.rb b/test/unit/vagrant/config_test.rb index 451745e23..aa90fdf77 100644 --- a/test/unit/vagrant/config_test.rb +++ b/test/unit/vagrant/config_test.rb @@ -7,6 +7,31 @@ describe Vagrant::Config do end end + it "should capture calls to `Vagrant.configure`" do + receiver = double() + + procs = described_class.capture_configures do + Vagrant.configure("1") do + receiver.one + end + + Vagrant.configure("2") do + receiver.two + end + end + + procs.should be_kind_of(Array) + procs.length.should == 2 + procs[0][0].should == "1" + procs[1][0].should == "2" + + # Verify the proper procs were captured + receiver.should_receive(:one).once.ordered + receiver.should_receive(:two).once.ordered + procs[0][1].call + procs[1][1].call + end + it "should capture configuration procs" do receiver = double() @@ -22,6 +47,20 @@ describe Vagrant::Config do # Verify that the proper proc was captured receiver.should_receive(:hello!).once - procs[0].call + procs[0][0].should == "1" + procs[0][1].call + end + + it "should capture the proper version" do + procs = described_class.capture_configures do + described_class.run("1") {} + described_class.run("2") {} + end + + # Verify the structure of the result + procs.should be_kind_of(Array) + procs.length.should == 2 + procs[0][0].should == "1" + procs[1][0].should == "2" end end