+1

On 12/04/09 0:36, Luke Kanies wrote:
> This is most of the way to replacing standard StoreConfigs
> integration with the Indirector.  We still need to convert
> the Catalog and then change all of the integraiton points
> (which is mostly the 'store' call in the Compiler).
> 
> Signed-off-by: Luke Kanies <[email protected]>
> ---
>  lib/puppet/indirector/active_record.rb       |   28 +++++++
>  lib/puppet/indirector/facts/active_record.rb |   35 +++++++++
>  lib/puppet/indirector/node/active_record.rb  |    7 ++
>  lib/puppet/rails/host.rb                     |   26 ++++++-
>  spec/unit/indirector/active_record.rb        |   75 +++++++++++++++++++
>  spec/unit/indirector/facts/active_record.rb  |  103 
> ++++++++++++++++++++++++++
>  spec/unit/indirector/node/active_record.rb   |   18 +++++
>  spec/unit/rails/host.rb                      |   91 +++++++++++++++++++++++
>  8 files changed, 382 insertions(+), 1 deletions(-)
>  create mode 100644 lib/puppet/indirector/active_record.rb
>  create mode 100644 lib/puppet/indirector/facts/active_record.rb
>  create mode 100644 lib/puppet/indirector/node/active_record.rb
>  create mode 100755 spec/unit/indirector/active_record.rb
>  create mode 100755 spec/unit/indirector/facts/active_record.rb
>  create mode 100755 spec/unit/indirector/node/active_record.rb
>  create mode 100755 spec/unit/rails/host.rb
> 
> diff --git a/lib/puppet/indirector/active_record.rb 
> b/lib/puppet/indirector/active_record.rb
> new file mode 100644
> index 0000000..531109a
> --- /dev/null
> +++ b/lib/puppet/indirector/active_record.rb
> @@ -0,0 +1,28 @@
> +require 'puppet/indirector'
> +
> +class Puppet::Indirector::ActiveRecord < Puppet::Indirector::Terminus
> +    class << self
> +        attr_accessor :ar_model
> +    end
> +
> +    def self.use_ar_model(klass)
> +        self.ar_model = klass
> +    end
> +
> +    def ar_model
> +        self.class.ar_model
> +    end
> +
> +    def initialize
> +        Puppet::Rails.init
> +    end
> +
> +    def find(request)
> +        return nil unless instance = ar_model.find_by_name(request.key)
> +        instance.to_puppet
> +    end
> +
> +    def save(request)
> +        ar_model.from_puppet(request.instance).save
> +    end
> +end
> diff --git a/lib/puppet/indirector/facts/active_record.rb 
> b/lib/puppet/indirector/facts/active_record.rb
> new file mode 100644
> index 0000000..5fb2596
> --- /dev/null
> +++ b/lib/puppet/indirector/facts/active_record.rb
> @@ -0,0 +1,35 @@
> +require 'puppet/rails/fact_name'
> +require 'puppet/rails/fact_value'
> +require 'puppet/indirector/active_record'
> +
> +class Puppet::Node::Facts::ActiveRecord < Puppet::Indirector::ActiveRecord
> +    use_ar_model Puppet::Rails::Host
> +
> +    # Find the Rails host and pull its facts as a Facts instance.
> +    def find(request)
> +        return nil unless host = ar_model.find_by_name(request.key, :include 
> => {:fact_values => :fact_name})
> +
> +        facts = Puppet::Node::Facts.new(host.name)
> +        facts.values = host.get_facts_hash.inject({}) do |hash, ary|
> +            # Convert all single-member arrays into plain values.
> +            param = ary[0]
> +            values = ary[1].collect { |v| v.value }
> +            values = values[0] if values.length == 1
> +            hash[param] = values
> +            hash
> +        end
> +
> +        facts
> +    end
> +
> +    # Save the values from a Facts instance as the facts on a Rails Host 
> instance.
> +    def save(request)
> +        facts = request.instance
> +
> +        host = ar_model.find_by_name(facts.name) || ar_model.create(:name => 
> facts.name)
> +        
> +        host.setfacts(facts.values)
> +
> +        host.save
> +    end
> +end
> diff --git a/lib/puppet/indirector/node/active_record.rb 
> b/lib/puppet/indirector/node/active_record.rb
> new file mode 100644
> index 0000000..ab33af4
> --- /dev/null
> +++ b/lib/puppet/indirector/node/active_record.rb
> @@ -0,0 +1,7 @@
> +require 'puppet/rails/host'
> +require 'puppet/indirector/active_record'
> +require 'puppet/node'
> +
> +class Puppet::Node::ActiveRecord < Puppet::Indirector::ActiveRecord
> +    use_ar_model Puppet::Rails::Host
> +end
> diff --git a/lib/puppet/rails/host.rb b/lib/puppet/rails/host.rb
> index 851cc21..23a2255 100644
> --- a/lib/puppet/rails/host.rb
> +++ b/lib/puppet/rails/host.rb
> @@ -22,6 +22,18 @@ class Puppet::Rails::Host < ActiveRecord::Base
>          end
>      end
>  
> +    def self.from_puppet(node)
> +        host = find_by_name(node.name) || new(:name => node.name)
> +
> +        {"ipaddress" => "ip", "environment" => "environment"}.each do 
> |myparam, itsparam|
> +            if value = node.send(myparam)
> +                host.send(itsparam + "=", value)
> +            end
> +        end
> +
> +        host
> +    end
> +
>      # Store our host in the database.
>      def self.store(node, resources)
>          args = {}
> @@ -70,6 +82,8 @@ class Puppet::Rails::Host < ActiveRecord::Base
>      end
>      
>      # returns a hash of fact_names.name => [ fact_values ] for this host.
> +    # Note that 'fact_values' is actually a list of the value instances, not
> +    # just actual values.
>      def get_facts_hash
>          fact_values = self.fact_values.find(:all, :include => :fact_name)
>          return fact_values.inject({}) do | hash, value |
> @@ -202,5 +216,15 @@ class Puppet::Rails::Host < ActiveRecord::Base
>          self.last_connect = Time.now
>          save
>      end
> -end
>  
> +    def to_puppet
> +        node = Puppet::Node.new(self.name)
> +        {"ip" => "ipaddress", "environment" => "environment"}.each do 
> |myparam, itsparam|
> +            if value = send(myparam)
> +                node.send(itsparam + "=", value)
> +            end
> +        end
> +
> +        node
> +    end
> +end
> diff --git a/spec/unit/indirector/active_record.rb 
> b/spec/unit/indirector/active_record.rb
> new file mode 100755
> index 0000000..6d81b0f
> --- /dev/null
> +++ b/spec/unit/indirector/active_record.rb
> @@ -0,0 +1,75 @@
> +#!/usr/bin/env ruby
> +
> +require File.dirname(__FILE__) + '/../../spec_helper'
> +require 'puppet/indirector/active_record'
> +
> +describe Puppet::Indirector::ActiveRecord do
> +    before do
> +        Puppet::Rails.stubs(:init)
> +
> +        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
> +        @model = mock 'model'
> +        @indirection = stub 'indirection', :name => :mystuff, 
> :register_terminus_type => nil, :model => @model
> +        
> Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
> +
> +        @active_record_class = Class.new(Puppet::Indirector::ActiveRecord) do
> +            def self.to_s
> +                "Mystuff::Testing"
> +            end
> +        end
> +
> +        @ar_model = mock 'ar_model'
> +
> +        @active_record_class.use_ar_model @ar_model
> +        @terminus = @active_record_class.new
> +
> +        @name = "me"
> +        @instance = stub 'instance', :name => @name
> +
> +        @request = stub 'request', :key => @name, :instance => @instance
> +    end
> +
> +    it "should allow declaration of an ActiveRecord model to use" do
> +        @active_record_class.use_ar_model "foo"
> +        @active_record_class.ar_model.should == "foo"
> +    end
> +
> +    describe "when initializing" do
> +        it "should init Rails" do
> +            Puppet::Rails.expects(:init)
> +            @active_record_class.new
> +        end
> +    end
> +
> +    describe "when finding an instance" do
> +        it "should use the ActiveRecord model to find the instance" do
> +            @ar_model.expects(:find_by_name).with(@name)
> +
> +            @terminus.find(@request)
> +        end
> +        
> +        it "should return nil if no instance is found" do
> +            @ar_model.expects(:find_by_name).with(@name).returns nil
> +            @terminus.find(@request).should be_nil
> +        end
> +
> +        it "should convert the instance to a Puppet object if it is found" do
> +            instance = mock 'rails_instance'
> +            instance.expects(:to_puppet).returns "mypuppet"
> +
> +            @ar_model.expects(:find_by_name).with(@name).returns instance
> +            @terminus.find(@request).should == "mypuppet"
> +        end
> +    end
> +
> +    describe "when saving an instance" do
> +        it "should use the ActiveRecord model to convert the instance into a 
> Rails object and then save that rails object" do
> +            rails_object = mock 'rails_object'
> +            @ar_model.expects(:from_puppet).with(@instance).returns 
> rails_object
> +
> +            rails_object.expects(:save)
> +
> +            @terminus.save(@request)
> +        end
> +    end
> +end
> diff --git a/spec/unit/indirector/facts/active_record.rb 
> b/spec/unit/indirector/facts/active_record.rb
> new file mode 100755
> index 0000000..340f2cf
> --- /dev/null
> +++ b/spec/unit/indirector/facts/active_record.rb
> @@ -0,0 +1,103 @@
> +#!/usr/bin/env ruby
> +
> +require File.dirname(__FILE__) + '/../../../spec_helper'
> +
> +require 'puppet/node/facts'
> +require 'puppet/indirector/facts/active_record'
> +
> +describe Puppet::Node::Facts::ActiveRecord do
> +    confine "Missing Rails" => Puppet.features.rails?
> +
> +    before do
> +        Puppet.features.stubs(:rails?).returns true
> +        @terminus = Puppet::Node::Facts::ActiveRecord.new
> +    end
> +
> +    it "should be a subclass of the ActiveRecord terminus class" do
> +        Puppet::Node::Facts::ActiveRecord.ancestors.should 
> be_include(Puppet::Indirector::ActiveRecord)
> +    end
> +
> +    it "should use Puppet::Rails::Host as its ActiveRecord model" do
> +        Puppet::Node::Facts::ActiveRecord.ar_model.should 
> equal(Puppet::Rails::Host)
> +    end
> +
> +    describe "when finding an instance" do
> +        before do
> +            @request = stub 'request', :key => "foo"
> +        end
> +
> +        it "should use the Hosts ActiveRecord class to find the host" do
> +            Puppet::Rails::Host.expects(:find_by_name).with { |key, args| 
> key == "foo" }
> +            @terminus.find(@request)
> +        end
> +
> +        it "should include the fact names and values when finding the host" 
> do
> +            Puppet::Rails::Host.expects(:find_by_name).with { |key, args| 
> args[:include] == {:fact_values => :fact_name} }
> +            @terminus.find(@request)
> +        end
> +
> +        it "should return nil if no host instance can be found" do
> +            Puppet::Rails::Host.expects(:find_by_name).returns nil
> +
> +            @terminus.find(@request).should be_nil
> +        end
> +
> +        it "should convert the node's parameters into a Facts instance if a 
> host instance is found" do
> +            host = stub 'host', :name => "foo"
> +            host.expects(:get_facts_hash).returns("one" => 
> [mock("two_value", :value => "two")], "three" => [mock("three_value", :value 
> => "four")])
> +
> +            Puppet::Rails::Host.expects(:find_by_name).returns host
> +
> +            result = @terminus.find(@request)
> +
> +            result.should be_instance_of(Puppet::Node::Facts)
> +            result.name.should == "foo"
> +            result.values.should == {"one" => "two", "three" => "four"}
> +        end
> +
> +        it "should convert all single-member arrays into non-arrays" do
> +            host = stub 'host', :name => "foo"
> +            host.expects(:get_facts_hash).returns("one" => 
> [mock("two_value", :value => "two")])
> +
> +            Puppet::Rails::Host.expects(:find_by_name).returns host
> +
> +            @terminus.find(@request).values["one"].should == "two"
> +        end
> +    end
> +
> +    describe "when saving an instance" do
> +        before do
> +            @host = stub 'host', :name => "foo", :save => nil, :setfacts => 
> nil
> +            Puppet::Rails::Host.stubs(:find_by_name).returns @host
> +            @facts = Puppet::Node::Facts.new("foo", "one" => "two", "three" 
> => "four")
> +            @request = stub 'request', :key => "foo", :instance => @facts
> +        end
> +
> +        it "should find the Rails host with the same name" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> @host
> +
> +            @terminus.save(@request)
> +        end
> +
> +        it "should create a new Rails host if none can be found" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> nil
> +
> +            Puppet::Rails::Host.expects(:create).with(:name => 
> "foo").returns @host
> +
> +            @terminus.save(@request)
> +        end
> +
> +        it "should set the facts as facts on the Rails host instance" do
> +            # There is other stuff added to the hash.
> +            @host.expects(:setfacts).with { |args| args["one"] == "two" and 
> args["three"] == "four" }
> +
> +            @terminus.save(@request)
> +        end
> +
> +        it "should save the Rails host instance" do
> +            @host.expects(:save)
> +
> +            @terminus.save(@request)
> +        end
> +    end
> +end
> diff --git a/spec/unit/indirector/node/active_record.rb 
> b/spec/unit/indirector/node/active_record.rb
> new file mode 100755
> index 0000000..22a6beb
> --- /dev/null
> +++ b/spec/unit/indirector/node/active_record.rb
> @@ -0,0 +1,18 @@
> +#!/usr/bin/env ruby
> +
> +require File.dirname(__FILE__) + '/../../../spec_helper'
> +
> +require 'puppet/node'
> +require 'puppet/indirector/node/active_record'
> +
> +describe Puppet::Node::ActiveRecord do
> +    confine "Missing Rails" => Puppet.features.rails?
> +
> +    it "should be a subclass of the ActiveRecord terminus class" do
> +        Puppet::Node::ActiveRecord.ancestors.should 
> be_include(Puppet::Indirector::ActiveRecord)
> +    end
> +
> +    it "should use Puppet::Rails::Host as its ActiveRecord model" do
> +        Puppet::Node::ActiveRecord.ar_model.should equal(Puppet::Rails::Host)
> +    end
> +end
> diff --git a/spec/unit/rails/host.rb b/spec/unit/rails/host.rb
> new file mode 100755
> index 0000000..882abbd
> --- /dev/null
> +++ b/spec/unit/rails/host.rb
> @@ -0,0 +1,91 @@
> +#!/usr/bin/env ruby
> +
> +require File.dirname(__FILE__) + '/../../spec_helper'
> +
> +describe "Puppet::Rails::Host" do
> +    confine "Cannot test without ActiveRecord" => Puppet.features.rails?
> +
> +    def column(name, type)
> +        ActiveRecord::ConnectionAdapters::Column.new(name, nil, type, false)
> +    end
> +
> +    before do
> +        require 'puppet/rails/host'
> +
> +        # Stub this so we don't need access to the DB.
> +        Puppet::Rails::Host.stubs(:columns).returns([column("name", 
> "string"), column("environment", "string"), column("ip", "string")])
> +
> +        @node = Puppet::Node.new("foo")
> +        @node.environment = "production"
> +        @node.ipaddress = "127.0.0.1"
> +
> +        @host = stub 'host', :environment= => nil, :ip= => nil
> +    end
> +
> +    describe "when converting a Puppet::Node instance into a Rails instance" 
> do
> +        it "should modify any existing instance in the database" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> @host
> +
> +            Puppet::Rails::Host.from_puppet(@node)
> +        end
> +
> +        it "should create a new instance in the database if none can be 
> found" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> nil
> +            Puppet::Rails::Host.expects(:new).with(:name => "foo").returns 
> @host
> +
> +            Puppet::Rails::Host.from_puppet(@node)
> +        end
> +
> +        it "should copy the environment from the Puppet instance" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> @host
> +
> +            @node.environment = "production"
> +            @host.expects(:environment=).with "production"
> +
> +            Puppet::Rails::Host.from_puppet(@node)
> +        end
> +
> +        it "should copy the ipaddress from the Puppet instance" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> @host
> +
> +            @node.ipaddress = "192.168.0.1"
> +            @host.expects(:ip=).with "192.168.0.1"
> +
> +            Puppet::Rails::Host.from_puppet(@node)
> +        end
> +
> +        it "should not save the Rails instance" do
> +            Puppet::Rails::Host.expects(:find_by_name).with("foo").returns 
> @host
> +
> +            @host.expects(:save).never
> +
> +            Puppet::Rails::Host.from_puppet(@node)
> +        end
> +    end
> +
> +    describe "when converting a Puppet::Rails::Host instance into a 
> Puppet::Node instance" do
> +        before do
> +            @host = Puppet::Rails::Host.new(:name => "foo", :environment => 
> "production", :ip => "127.0.0.1")
> +            @node = Puppet::Node.new("foo")
> +            Puppet::Node.stubs(:new).with("foo").returns @node
> +        end
> +
> +        it "should create a new instance with the correct name" do
> +            Puppet::Node.expects(:new).with("foo").returns @node
> +
> +            @host.to_puppet
> +        end
> +
> +        it "should copy the environment from the Rails instance" do
> +            @host.environment = "prod"
> +            @node.expects(:environment=).with "prod"
> +            @host.to_puppet
> +        end
> +
> +        it "should copy the ipaddress from the Rails instance" do
> +            @host.ip = "192.168.0.1"
> +            @node.expects(:ipaddress=).with "192.168.0.1"
> +            @host.to_puppet
> +        end
> +    end
> +end


-- 
Brice Figureau
Days of Wonder
http://www.daysofwonder.com

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to