summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrice Figureau <brice-puppet@daysofwonder.com>2011-01-03 19:45:51 +0100
committerJames Turnbull <james@lovedthanlost.net>2011-04-08 18:19:53 +1000
commit596571fd2b03957e7ed185856ee649c1e610716c (patch)
treebd483ba28d9380d82d1de8c9cb9e5976e5e0aa4a
parent6560da52674dfce10a622b633a9ed511f75b0a89 (diff)
downloadpuppet-596571fd2b03957e7ed185856ee649c1e610716c.tar.gz
puppet-596571fd2b03957e7ed185856ee649c1e610716c.tar.xz
puppet-596571fd2b03957e7ed185856ee649c1e610716c.zip
Base class for network device based providers
This is the common bits of all future network device providers that are using prefetching/flushing to limit the number of calls to the remote network device. The idea is that we need one transaction to prefetch and one to flush each instance. Implementors needs to implement lookup which returns a hash of the found entity, and flush to update the remote device. Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com>
-rw-r--r--lib/puppet/provider/network_device.rb59
-rw-r--r--spec/unit/provider/network_device_spec.rb148
2 files changed, 207 insertions, 0 deletions
diff --git a/lib/puppet/provider/network_device.rb b/lib/puppet/provider/network_device.rb
new file mode 100644
index 000000000..58865fddc
--- /dev/null
+++ b/lib/puppet/provider/network_device.rb
@@ -0,0 +1,59 @@
+
+# This is the base class of all prefetched network device provider
+class Puppet::Provider::NetworkDevice < Puppet::Provider
+
+ def self.lookup(url, name)
+ raise "This provider doesn't implement the necessary lookup method"
+ end
+
+ def self.prefetch(resources)
+ resources.each do |name, resource|
+ if result = lookup(resource[:device_url], name)
+ result[:ensure] = :present
+ resource.provider = new(result)
+ else
+ resource.provider = new(:ensure => :absent)
+ end
+ end
+ end
+
+ def exists?
+ @property_hash[:ensure] != :absent
+ end
+
+ def initialize(*args)
+ super
+
+ # Make a duplicate, so that we have a copy for comparison
+ # at the end.
+ @properties = @property_hash.dup
+ end
+
+ def create
+ @property_hash[:ensure] = :present
+ self.class.resource_type.validproperties.each do |property|
+ if val = resource.should(property)
+ @property_hash[property] = val
+ end
+ end
+ end
+
+ def destroy
+ @property_hash[:ensure] = :absent
+ end
+
+ def flush
+ @property_hash.clear
+ end
+
+ def self.instances
+ end
+
+ def former_properties
+ @properties.dup
+ end
+
+ def properties
+ @property_hash.dup
+ end
+end \ No newline at end of file
diff --git a/spec/unit/provider/network_device_spec.rb b/spec/unit/provider/network_device_spec.rb
new file mode 100644
index 000000000..3e6d382ee
--- /dev/null
+++ b/spec/unit/provider/network_device_spec.rb
@@ -0,0 +1,148 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/provider/network_device'
+
+Puppet::Type.type(:vlan).provide :test, :parent => Puppet::Provider::NetworkDevice do
+ mk_resource_methods
+ def self.lookup(device_url, name)
+ end
+end
+
+provider_class = Puppet::Type.type(:vlan).provider(:test)
+
+describe provider_class do
+ before do
+ @resource = stub("resource", :name => "test")
+ @provider = provider_class.new(@resource)
+ end
+
+ it "should be able to prefetch instances from the device" do
+ provider_class.should respond_to(:prefetch)
+ end
+
+ it "should have an instances method" do
+ provider_class.should respond_to(:instances)
+ end
+
+ describe "when prefetching" do
+ before do
+ @resource = stub_everything 'resource'
+ @resources = {"200" => @resource}
+ provider_class.stubs(:lookup)
+ end
+
+ it "should lookup an entry for each passed resource" do
+ provider_class.expects(:lookup).with(nil, "200").returns nil
+
+ provider_class.stubs(:new)
+ @resource.stubs(:provider=)
+ provider_class.prefetch(@resources)
+ end
+
+ describe "resources that do not exist" do
+ it "should create a provider with :ensure => :absent" do
+ provider_class.stubs(:lookup).returns(nil)
+ provider_class.expects(:new).with(:ensure => :absent).returns "myprovider"
+ @resource.expects(:provider=).with("myprovider")
+ provider_class.prefetch(@resources)
+ end
+ end
+
+ describe "resources that exist" do
+ it "should create a provider with the results of the find and ensure at present" do
+ provider_class.stubs(:lookup).returns({ :name => "200", :description => "myvlan"})
+
+ provider_class.expects(:new).with(:name => "200", :description => "myvlan", :ensure => :present).returns "myprovider"
+ @resource.expects(:provider=).with("myprovider")
+
+ provider_class.prefetch(@resources)
+ end
+ end
+ end
+
+ describe "when being initialized" do
+ describe "with a hash" do
+ before do
+ @resource_class = mock 'resource_class'
+ provider_class.stubs(:resource_type).returns @resource_class
+
+ @property_class = stub 'property_class', :array_matching => :all, :superclass => Puppet::Property
+ @resource_class.stubs(:attrclass).with(:one).returns(@property_class)
+ @resource_class.stubs(:valid_parameter?).returns true
+ end
+
+ it "should store a copy of the hash as its vlan_properties" do
+ instance = provider_class.new(:one => :two)
+ instance.former_properties.should == {:one => :two}
+ end
+ end
+ end
+
+ describe "when an instance" do
+ before do
+ @instance = provider_class.new
+
+ @property_class = stub 'property_class', :array_matching => :all, :superclass => Puppet::Property
+ @resource_class = stub 'resource_class', :attrclass => @property_class, :valid_parameter? => true, :validproperties => [:description]
+ provider_class.stubs(:resource_type).returns @resource_class
+ end
+
+ it "should have a method for creating the instance" do
+ @instance.should respond_to(:create)
+ end
+
+ it "should have a method for removing the instance" do
+ @instance.should respond_to(:destroy)
+ end
+
+ it "should indicate when the instance already exists" do
+ @instance = provider_class.new(:ensure => :present)
+ @instance.exists?.should be_true
+ end
+
+ it "should indicate when the instance does not exist" do
+ @instance = provider_class.new(:ensure => :absent)
+ @instance.exists?.should be_false
+ end
+
+ describe "is being flushed" do
+ it "should flush properties" do
+ @instance = provider_class.new(:ensure => :present, :name => "200", :description => "myvlan")
+ @instance.flush
+ @instance.properties.should be_empty
+ end
+ end
+
+ describe "is being created" do
+ before do
+ @rclass = mock 'resource_class'
+ @rclass.stubs(:validproperties).returns([:description])
+ @resource = stub_everything 'resource'
+ @resource.stubs(:class).returns @rclass
+ @resource.stubs(:should).returns nil
+ @instance.stubs(:resource).returns @resource
+ end
+
+ it "should set its :ensure value to :present" do
+ @instance.create
+ @instance.properties[:ensure].should == :present
+ end
+
+ it "should set all of the other attributes from the resource" do
+ @resource.expects(:should).with(:description).returns "myvlan"
+
+ @instance.create
+ @instance.properties[:description].should == "myvlan"
+ end
+ end
+
+ describe "is being destroyed" do
+ it "should set its :ensure value to :absent" do
+ @instance.destroy
+ @instance.properties[:ensure].should == :absent
+ end
+ end
+ end
+end