From a924a7b48c4cdd5f7c2ffbca2e54765ff3a47bc1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 26 Jan 2014 13:55:11 -0800 Subject: [PATCH 1/2] core: provider capabilities --- lib/vagrant/machine.rb | 1 + lib/vagrant/plugin/v2/components.rb | 6 ++++ lib/vagrant/plugin/v2/manager.rb | 16 +++++++++- lib/vagrant/plugin/v2/plugin.rb | 12 ++++++++ lib/vagrant/plugin/v2/provider.rb | 16 ++++++++++ test/unit/vagrant/machine_test.rb | 21 +++++++++++-- test/unit/vagrant/plugin/v2/plugin_test.rb | 10 ++++++ test/unit/vagrant/plugin/v2/provider_test.rb | 32 ++++++++++++++++++++ 8 files changed, 111 insertions(+), 3 deletions(-) diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 1f6de52d0..e5c9651fb 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -114,6 +114,7 @@ module Vagrant # Initializes the provider last so that it has access to all the # state we setup on this machine. @provider = provider_cls.new(self) + @provider._initialize(@provider_name, self) end # This calls an action on the provider. The provider may or may not diff --git a/lib/vagrant/plugin/v2/components.rb b/lib/vagrant/plugin/v2/components.rb index c99d14967..7bae6c29a 100644 --- a/lib/vagrant/plugin/v2/components.rb +++ b/lib/vagrant/plugin/v2/components.rb @@ -49,6 +49,11 @@ module Vagrant # @return [Hash] attr_reader :providers + # This contains all the registered provider capabilities. + # + # @return [Hash] + attr_reader :provider_capabilities + # This contains all the synced folder implementations by name. # # @return [Registry>] @@ -65,6 +70,7 @@ module Vagrant @hosts = Registry.new @host_capabilities = Hash.new { |h, k| h[k] = Registry.new } @providers = Registry.new + @provider_capabilities = Hash.new { |h, k| h[k] = Registry.new } @synced_folders = Registry.new end end diff --git a/lib/vagrant/plugin/v2/manager.rb b/lib/vagrant/plugin/v2/manager.rb index dd4788dd3..62a23f82a 100644 --- a/lib/vagrant/plugin/v2/manager.rb +++ b/lib/vagrant/plugin/v2/manager.rb @@ -113,7 +113,6 @@ module Vagrant results end - # This returns all registered providers. # # @return [Hash] @@ -125,6 +124,21 @@ module Vagrant end end + # This returns all the registered provider capabilities. + # + # @return [Hash] + def provider_capabilities + results = Hash.new { |h, k| h[k] = Registry.new } + + @registered.each do |plugin| + plugin.components.provider_capabilities.each do |provider, caps| + results[provider].merge!(caps) + end + end + + results + end + # This returns all the config classes for the various providers. # # @return [Hash] diff --git a/lib/vagrant/plugin/v2/plugin.rb b/lib/vagrant/plugin/v2/plugin.rb index bacf891dc..51a9f458b 100644 --- a/lib/vagrant/plugin/v2/plugin.rb +++ b/lib/vagrant/plugin/v2/plugin.rb @@ -193,6 +193,18 @@ module Vagrant nil end + # Defines a capability for the given provider. The block should return + # a class/module that has a method with the capability name, ready + # to be executed. This means that if it is an instance method, + # the block should return an instance of the class. + # + # @param [String] provider The name of the provider + # @param [String] cap The name of the capability + def self.provider_capability(provider, cap, &block) + components.provider_capabilities[provider.to_sym].register(cap.to_sym, &block) + nil + end + # Registers additional provisioners to be available. # # @param [String] name Name of the provisioner. diff --git a/lib/vagrant/plugin/v2/provider.rb b/lib/vagrant/plugin/v2/provider.rb index 60cd5c217..e208496e3 100644 --- a/lib/vagrant/plugin/v2/provider.rb +++ b/lib/vagrant/plugin/v2/provider.rb @@ -1,3 +1,5 @@ +require "vagrant/capability_host" + module Vagrant module Plugin module V2 @@ -5,6 +7,8 @@ module Vagrant # is responsible for creating compute resources to match the needs # of a Vagrant-configured system. class Provider + include CapabilityHost + # Initialize the provider to represent the given machine. # # @param [Vagrant::Machine] machine The machine that this provider @@ -63,6 +67,18 @@ module Vagrant def state nil end + + # This is an internal initialize function that should never be + # overridden. It is used to initialize some common internal state + # that is used in a provider. + def _initialize(name, machine) + initialize_capabilities!( + name.to_sym, + { name.to_sym => [Class.new, nil] }, + Vagrant.plugin("2").manager.provider_capabilities, + machine, + ) + end end end end diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index b8e2f45d8..afcca8478 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -48,9 +48,14 @@ describe Vagrant::Machine do # # @yield [machine] Yields the machine that the provider initialization # method received so you can run additional tests on it. - def provider_init_test + def provider_init_test(instance=nil) received_machine = nil + if !instance + instance = double("instance") + instance.stub(:_initialize => nil) + end + provider_cls = double("provider_cls") provider_cls.should_receive(:new) do |machine| # Store this for later so we can verify that it is the @@ -62,7 +67,8 @@ describe Vagrant::Machine do # Yield our machine if we want to do additional tests yield machine if block_given? - end + true + end.and_return(instance) # Initialize a new machine and verify that we properly receive # the machine we expect. @@ -117,6 +123,17 @@ describe Vagrant::Machine do machine.provider.should be_nil end end + + it "should initialize the capabilities" do + instance = double("instance") + instance.should_receive(:_initialize).with do |p, m| + expect(p).to eq(provider_name) + expect(m.name).to eq(name) + true + end + + provider_init_test + end end end diff --git a/test/unit/vagrant/plugin/v2/plugin_test.rb b/test/unit/vagrant/plugin/v2/plugin_test.rb index 4a7a32feb..226a0f875 100644 --- a/test/unit/vagrant/plugin/v2/plugin_test.rb +++ b/test/unit/vagrant/plugin/v2/plugin_test.rb @@ -281,6 +281,16 @@ describe Vagrant::Plugin::V2::Plugin do end end + describe "provider capabilities" do + it "should register host capabilities" do + plugin = Class.new(described_class) do + provider_capability("foo", "bar") { "baz" } + end + + plugin.components.provider_capabilities[:foo][:bar].should == "baz" + end + end + describe "provisioners" do it "should register provisioner classes" do plugin = Class.new(described_class) do diff --git a/test/unit/vagrant/plugin/v2/provider_test.rb b/test/unit/vagrant/plugin/v2/provider_test.rb index 7a7b11876..489a3ba94 100644 --- a/test/unit/vagrant/plugin/v2/provider_test.rb +++ b/test/unit/vagrant/plugin/v2/provider_test.rb @@ -1,9 +1,13 @@ require File.expand_path("../../../../base", __FILE__) describe Vagrant::Plugin::V2::Provider do + include_context "unit" + let(:machine) { Object.new } let(:instance) { described_class.new(machine) } + subject { instance } + it "should return nil by default for actions" do instance.action(:whatever).should be_nil end @@ -15,4 +19,32 @@ describe Vagrant::Plugin::V2::Provider do it "should return nil by default for state" do instance.state.should be_nil end + + context "capabilities" do + before do + register_plugin("2") do |p| + p.provider_capability("bar", "foo") {} + + p.provider_capability("foo", "bar") do + Class.new do + def self.bar(machine) + raise "bar #{machine.id}" + end + end + end + end + + machine.stub(id: "YEAH") + + instance._initialize("foo", machine) + end + + it "can execute capabilities" do + expect(subject.capability?(:foo)).to be_false + expect(subject.capability?(:bar)).to be_true + + expect { subject.capability(:bar) }. + to raise_error("bar YEAH") + end + end end From 78e7e2746f41de421c8d6dce092dd9cef21e993d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 26 Jan 2014 14:33:22 -0800 Subject: [PATCH 2/2] core: fix machine tests with provider changes --- test/unit/vagrant/machine_test.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index afcca8478..0be5455be 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -7,7 +7,11 @@ describe Vagrant::Machine do include_context "unit" let(:name) { "foo" } - let(:provider) { double("provider") } + let(:provider) do + double("provider").tap do |obj| + obj.stub(:_initialize => nil) + end + end let(:provider_cls) do obj = double("provider_cls") obj.stub(:new => provider) @@ -132,7 +136,7 @@ describe Vagrant::Machine do true end - provider_init_test + provider_init_test(instance) end end end