[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, upstream, updated. 0.25.5-639-g8f94f35
test branch
puppet-dev at googlegroups.com
Wed Jul 14 10:34:43 UTC 2010
The following commit has been merged in the upstream branch:
commit 432db2593f15de200767ec16c14f433f718a44d9
Author: Rein Henrichs <rein at puppetlabs.com>
Date: Mon Jun 14 16:40:38 2010 -0700
[#4055] Add CouchDB terminus for facts
Implements an abstract CouchDB terminus and a concrete CouchDB terminus
used to store node facts. Node facts are stored in a "node" document as
the "facts" attribute. This node document may also be used by other
couchdb termini that store node-related information. It is recommended
to use a separate document (or documents) to store large data structures
like catalogs, linking them to their related node document using
embedded ids.
This implementation depends on the "couchrest" gem.
* Add Puppet.features.couchdb?
* Add Puppet[:couchdb_url] setting
* Add Puppet::Node::Facts#== for testing
* Add PuppetSpec::FIXTURE_DIR for easy access to fixture files
* Add CouchDB Terminus
* Add Facts::CouchDB terminus
* Stores facts inside a "node" document
* Use key (hostname) as _id for node document
* #find returns nil if document cannot be found
* #save finds and updates existing document OR creates new doc [1]
* Store facts in "facts" attribute of node document
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 78f4cd5..9de73f5 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -680,6 +680,10 @@ module Puppet
and other environments normally use ``debug``."]
)
+ setdefaults(:couchdb,
+ :couchdb_url => ["http://127.0.0.1:5984/puppet", "The url where the puppet couchdb database will be created"]
+ )
+
setdefaults(:transaction,
:tags => ["", "Tags to use to find resources. If this is set, then
only resources tagged with the specified tags will be applied.
diff --git a/lib/puppet/feature/base.rb b/lib/puppet/feature/base.rb
index 8a21fd3..0ca408c 100644
--- a/lib/puppet/feature/base.rb
+++ b/lib/puppet/feature/base.rb
@@ -45,3 +45,6 @@ end
Puppet.features.add(:win32, :libs => ["sys/admin", "win32/process", "win32/dir"])
raise Puppet::Error "Cannot determine basic system flavour" unless Puppet.features.posix? or Puppet.features.win32?
+
+# We have CouchDB
+Puppet.features.add(:couchdb, :libs => ["couchrest"])
diff --git a/lib/puppet/indirector/couch.rb b/lib/puppet/indirector/couch.rb
new file mode 100644
index 0000000..b328f5c
--- /dev/null
+++ b/lib/puppet/indirector/couch.rb
@@ -0,0 +1,68 @@
+require 'couchrest'
+class Puppet::Indirector::Couch < Puppet::Indirector::Terminus
+
+ # The CouchRest database instance. One database instance per Puppet runtime
+ # should be sufficient.
+ #
+ def self.db
+ @db ||= CouchRest.database! Puppet[:couchdb_url]
+ end
+
+ def db; self.class.db end
+
+ def find(request)
+ attributes_of db.get(id_for(request))
+ rescue RestClient::ResourceNotFound
+ Puppet.debug "No couchdb document with id: #{id_for(request)}"
+ return nil
+ end
+
+ # Create or update the couchdb document with the request's data hash.
+ #
+ # RKH:TODO: Do not depend on error handling, check if the document exists
+ # first. (Does couchrest support this?)
+ #
+ def save(request)
+ raise ArgumentError, "PUT does not accept options" unless request.options.empty?
+
+ # Try to find an existing document.
+ doc = db.get(id_for(request))
+ doc.merge(hash_from(request))
+ doc.save
+ rescue RestClient::ResourceNotFound
+ # Document does not yet exist, create it
+ db.save_doc hash_from(request)
+ end
+
+ private
+
+ # The attributes hash that is serialized to CouchDB as JSON. It includes
+ # metadata that is used to help aggregate data in couchdb. Add
+ # model-specific attributes in subclasses.
+ #
+ def hash_from(request)
+ {
+ "_id" => id_for(request),
+ "puppet_type" => document_type_for(request)
+ }
+ end
+
+ # The couchdb response stripped of metadata, used to instantiate the model
+ # instance that is returned by save.
+ #
+ def attributes_of(response)
+ response.reject{|k,v| k =~ /^(_rev|puppet_)/ }
+ end
+
+ def document_type_for(request)
+ request.indirection_name
+ end
+
+ # The id used to store the object in couchdb. Implemented in subclasses.
+ #
+ def id_for(request)
+ raise NotImplementedError
+ end
+
+end
+
diff --git a/lib/puppet/indirector/facts/couch.rb b/lib/puppet/indirector/facts/couch.rb
new file mode 100644
index 0000000..522fe33
--- /dev/null
+++ b/lib/puppet/indirector/facts/couch.rb
@@ -0,0 +1,31 @@
+require 'puppet/node/facts'
+require 'puppet/indirector/couch'
+class Puppet::Node::Facts::Couch < Puppet::Indirector::Couch
+
+ # Return the facts object or nil if there is no document
+ def find(request)
+ doc = super
+ doc ? model.new(doc['_id'], doc['facts']) : nil
+ end
+
+ private
+
+ # Facts values are stored to the document's 'facts' attribute. Hostname is
+ # stored to 'name'
+ #
+ def hash_from(request)
+ super.merge('facts' => request.instance.values)
+ end
+
+ # Facts are stored to the 'node' document.
+ def document_type_for(request)
+ 'node'
+ end
+
+ # The id used to store the object in couchdb.
+ def id_for(request)
+ request.key.to_s
+ end
+
+end
+
diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb
index 2b086af..0b9fc58 100755
--- a/lib/puppet/node/facts.rb
+++ b/lib/puppet/node/facts.rb
@@ -49,6 +49,11 @@ class Puppet::Node::Facts
end
end
+ def ==(other)
+ return false unless self.name == other.name
+ strip_internal == other.send(:strip_internal)
+ end
+
private
# Add internal data to the facts for storage.
diff --git a/spec/fixtures/yaml/test.local.yaml b/spec/fixtures/yaml/test.local.yaml
new file mode 100644
index 0000000..194d8aa
--- /dev/null
+++ b/spec/fixtures/yaml/test.local.yaml
@@ -0,0 +1,16 @@
+--- !ruby/object:Puppet::Node::Facts
+ expiration: 2010-06-07 19:15:36.519351 -07:00
+ name: test.local
+ values:
+ sp_number_processors: "2"
+ kernelmajversion: "10.3"
+ kernelversion: 10.3.1
+ sp_secure_vm: secure_vm_enabled
+ ps: ps auxwww
+ macosx_productversion_major: "10.6"
+ hostname: test
+ !ruby/sym _timestamp: Mon Jun 07 18:45:36 -0700 2010
+ facterversion: 1.5.7
+ sp_packages: "1"
+ timezone: PDT
+ environment: production
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d657f83..0ea24bb 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -23,6 +23,7 @@ require 'spec/autorun'
# So everyone else doesn't have to include this base constant.
module PuppetSpec
+ FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR)
end
# load any monkey-patches
diff --git a/spec/unit/application/master.rb b/spec/unit/application/master.rb
index f082ece..c3f4d9e 100644
--- a/spec/unit/application/master.rb
+++ b/spec/unit/application/master.rb
@@ -176,12 +176,6 @@ describe Puppet::Application::Master do
@master.setup
end
- it "should set node facst terminus to yaml" do
- Puppet::Node::Facts.expects(:terminus_class=).with(:yaml)
-
- @master.setup
- end
-
it "should cache class in yaml" do
Puppet::Node.expects(:cache_class=).with(:yaml)
diff --git a/spec/unit/indirector/facts/couch.rb b/spec/unit/indirector/facts/couch.rb
new file mode 100644
index 0000000..acc28b9
--- /dev/null
+++ b/spec/unit/indirector/facts/couch.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/node/facts'
+require 'puppet/indirector/facts/couch'
+
+describe Puppet::Node::Facts::Couch do
+ before do
+ @mock_db = mock('couch db')
+ mock_document = CouchRest::Document.new(:_id => fake_request.key, :facts => fake_request.values)
+ mock_document.stubs(:database).returns(@mock_db)
+ @mock_db.stubs(:get).with('test.local').returns(mock_document)
+ Puppet::Node::Facts::Couch.stubs(:db).returns(@mock_db)
+ end
+
+ subject { Puppet::Node::Facts::Couch }
+
+ describe "#find" do
+ it "should find the request by key" do
+ @mock_db.expects(:get).with(fake_request.key).returns({'_id' => fake_request.key, 'facts' => fake_request.instance.values})
+ subject.new.find(fake_request).should == fake_request.instance
+ end
+ end
+
+ describe "#save" do
+ it "should save the json to the CouchDB database" do
+ @mock_db.expects(:save_doc).at_least_once.returns({'ok' => true })
+ subject.new.save(fake_request)
+ end
+ end
+
+ def fake_request
+ facts = YAML.load_file(File.join(PuppetSpec::FIXTURE_DIR, 'yaml', 'test.local.yaml'))
+ Struct.new(:instance, :key, :options).new(facts, facts.name, {})
+ end
+ private :fake_request
+
+end
+
--
Puppet packaging for Debian
More information about the Pkg-puppet-devel
mailing list