From 67855be77b19dace0038cab5d7748ce7f1447d80 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 7 Nov 2012 21:45:09 -0800 Subject: [PATCH] Add the Environment#machine method This will eventually replace the Environment#vms method. Because of the introduction of providers, the environment doesn't know what the backing of the machines will be (and they're _machines_ now, not _vms_). Instead, users of Environment will now call `#machine` on the environment to retrieve a machine with the given backing provider as it needs it. --- lib/vagrant/environment.rb | 32 +++++++++++++ lib/vagrant/errors.rb | 8 ++++ plugins/commands/up/command.rb | 8 +++- plugins/kernel_v2/config/vm.rb | 1 - templates/locales/en.yml | 6 +++ test/unit/vagrant/environment_test.rb | 67 +++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 2 deletions(-) diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index d4b756a5d..4799eb3dd 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -129,6 +129,38 @@ module Vagrant @_boxes ||= BoxCollection.new(boxes_path) end + # This returns a machine with the proper provider for this environment. + # The machine named by `name` must be in this environment. + # + # @param [Symbol] name Name of the machine (as configured in the + # Vagrantfile). + # @param [Symbol] provider The provider that this machine should be + # backed by. + # @return [Machine] + def machine(name, provider) + vm_config = config.for_vm(name) + if !vm_config + raise Errors::MachineNotFound, :name => name, :provider => provider + end + + provider_cls = Vagrant.plugin("2").manager.providers[provider] + if !provider_cls + raise Errors::ProviderNotFound, :machine => name, :provider => provider + end + + box = boxes.find(vm_config.vm.box, provider) + Machine.new(name, provider_cls, vm_config, box, self) + end + + # This returns a list of the configured machines for this environment. + # Each of the names returned by this method is valid to be used with + # the {#machine} method. + # + # @return [Array] Configured machine names. + def machine_names + config.vms + end + # Returns the VMs associated with this environment. # # @return [Hash] diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 1afb29b25..690afa86d 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -234,6 +234,10 @@ module Vagrant error_key(:machine_guest_not_ready) end + class MachineNotFound < VagrantError + error_key(:machine_not_found) + end + class MultiVMEnvironmentRequired < VagrantError status_code(5) error_key(:multi_vm_required) @@ -314,6 +318,10 @@ module Vagrant error_key(:dotfile_error, "vagrant.actions.vm.persist") end + class ProviderNotFound < VagrantError + error_key(:provider_not_found) + end + class PluginLoadError < VagrantError status_code(81) error_key(:plugin_load_error) diff --git a/plugins/commands/up/command.rb b/plugins/commands/up/command.rb index e3b6088cd..61a71bc3e 100644 --- a/plugins/commands/up/command.rb +++ b/plugins/commands/up/command.rb @@ -12,9 +12,15 @@ module VagrantPlugins def execute options = {} opts = OptionParser.new do |o| - o.banner = "Usage: vagrant up [vm-name] [--[no-]provision] [-h]" + o.banner = "Usage: vagrant up [vm-name] [--[no-]provision] [--provider provider] [-h]" o.separator "" + build_start_options(o, options) + + o.on("--provider provider", String, + "Back the machine with a specific provider.") do |provider| + options["provider"] = provider + end end # Parse the options diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 3d2fd4e98..77ef5528d 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -163,7 +163,6 @@ module VagrantPlugins elsif type == :hostonly # Validate the host-only network ip = args[0] - options = args[1] || {} if !ip errors.add(I18n.t("vagrant.config.vm.network_ip_required")) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 25785d5f9..28f4600d1 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -89,6 +89,9 @@ en: Guest-specific operations were attempted on a machine that is not ready for guest communication. This should not happen and a bug should be reported. + machine_not_found: |- + The machine with the name '%{name}' was not found configured for + this Vagrant environment. multi_vm_required: |- A multi-vm environment is required for name specification to this command. multi_vm_target_required: |- @@ -105,6 +108,9 @@ en: for you but VirtualBox only allows forwarded ports to change if the VM is powered off. Therefore, please reload your VM or halt the other running VMs to continue. + provider_not_found: |- + The provider '%{provider}' could not be found, but was requested to + back the machine '%{machine}'. Please use a provider that exists. scp_permission_denied: |- Failed to upload a file to the guest VM via SCP due to a permissions error. This is normally because the user running Vagrant doesn't have diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index 844f12928..b04001f7e 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -236,4 +236,71 @@ VF instance.ui.should be_kind_of(CustomUI) end end + + describe "getting a machine" do + it "should return a machine object with the correct provider" do + # Create a provider + foo_provider = Class.new(Vagrant.plugin("2", :provider)) + register_plugin("2") do |p| + p.provider("foo") { foo_provider } + end + + # Create the configuration + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" + config.vm.define "foo" +end +VF + end + + # Verify that we can get the machine + env = isolated_env.create_vagrant_env + machine = env.machine(:foo, :foo) + machine.should be_kind_of(Vagrant::Machine) + machine.name.should == :foo + machine.provider.should be_kind_of(foo_provider) + end + + it "should raise an error if the VM is not found" do + expect { instance.machine("i-definitely-dont-exist", :virtualbox) }. + to raise_error(Vagrant::Errors::MachineNotFound) + end + + it "should raise an error if the provider is not found" do + expect { instance.machine(:default, :lol_no) }. + to raise_error(Vagrant::Errors::ProviderNotFound) + end + end + + describe "getting machine names" do + it "should return the default machine if no multi-VM is used" do + # Create the config + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| +end +VF + end + + env = isolated_env.create_vagrant_env + env.machine_names.should == [:default] + end + + it "should return the machine names in order" do + # Create the config + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.define "foo" + config.vm.define "bar" +end +VF + end + + env = isolated_env.create_vagrant_env + env.machine_names.should == [:foo, :bar] + end + end end