+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 -~----------~----~----~----~------~----~------~--~---
