summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/defaults.rb4
-rw-r--r--lib/puppet/feature/base.rb3
-rw-r--r--lib/puppet/indirector/couch.rb68
-rw-r--r--lib/puppet/indirector/facts/couch.rb31
-rwxr-xr-xlib/puppet/node/facts.rb5
5 files changed, 111 insertions, 0 deletions
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 78f4cd52e..9de73f526 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 8a21fd30f..0ca408ce4 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 000000000..b328f5cb7
--- /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 000000000..522fe3350
--- /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 2b086afea..0b9fc5879 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.