summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRein Henrichs <rein@puppetlabs.com>2010-06-07 15:45:45 -0700
committerJames Turnbull <james@lovedthanlost.net>2010-06-27 03:54:08 +1000
commit97936c6d3fa3950d22266679b65d4a6877008a74 (patch)
tree0a3ec96444635c6b7604da50cb79657aabbee448 /lib
parentdb39b7c0848f8931989cbe21ff202552c0ae78c1 (diff)
[#3921] Add facts_terminus setting to Puppet settings
* defaults to "facter" * no longer set the facts terminus class in for puppetmaster, use setting instead 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.
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/application/puppetd.rb4
-rw-r--r--lib/puppet/application/puppetmasterd.rb3
-rw-r--r--lib/puppet/defaults.rb5
-rw-r--r--lib/puppet/feature/base.rb3
-rw-r--r--lib/puppet/indirector/couch.rb76
-rw-r--r--lib/puppet/indirector/facts/couch.rb31
-rwxr-xr-xlib/puppet/node/facts.rb8
7 files changed, 124 insertions, 6 deletions
diff --git a/lib/puppet/application/puppetd.rb b/lib/puppet/application/puppetd.rb
index 8b07c90dd..ca5a0d47b 100644
--- a/lib/puppet/application/puppetd.rb
+++ b/lib/puppet/application/puppetd.rb
@@ -215,9 +215,11 @@ Puppet::Application.new(:puppetd) do
# You can still override this on the command-line with, e.g., :compiler.
Puppet[:catalog_terminus] = :rest
+ # Override the default.
+ Puppet[:facts_terminus] = :facter
+
Puppet::Resource::Catalog.cache_class = :yaml
- Puppet::Node::Facts.terminus_class = :facter
# We need tomake the client either way, we just don't start it
# if --no-client is set.
diff --git a/lib/puppet/application/puppetmasterd.rb b/lib/puppet/application/puppetmasterd.rb
index 9b0bf30ce..6e694452f 100644
--- a/lib/puppet/application/puppetmasterd.rb
+++ b/lib/puppet/application/puppetmasterd.rb
@@ -150,9 +150,6 @@ Puppet::Application.new(:puppetmasterd) do
Puppet.settings.use :main, :puppetmasterd, :ssl
- # A temporary solution, to at least make the master work for now.
- Puppet::Node::Facts.terminus_class = :yaml
-
# Cache our nodes in yaml. Currently not configurable.
Puppet::Node.cache_class = :yaml
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index c81513382..0ae055351 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -151,6 +151,7 @@ module Puppet
:node_terminus => ["plain", "Where to find information about nodes."],
:catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
+ :facts_terminus => ["facter", "Where to get node facts."],
:httplog => { :default => "$logdir/http.log",
:owner => "root",
:mode => 0640,
@@ -694,6 +695,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 aac04f234..a6111d836 100644
--- a/lib/puppet/feature/base.rb
+++ b/lib/puppet/feature/base.rb
@@ -31,3 +31,6 @@ Puppet.features.add(:rrd, :libs => ["RRDtool"])
# We have OpenSSL
Puppet.features.add(:openssl, :libs => ["openssl"])
+
+# 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..6818ee834
--- /dev/null
+++ b/lib/puppet/indirector/couch.rb
@@ -0,0 +1,76 @@
+raise "Couch terminus not supported without couchrest gem" unless Puppet.features.couchdb?
+
+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 get(request)
+ end
+
+ # Create or update the couchdb document with the request's data hash.
+ #
+ def save(request)
+ raise ArgumentError, "PUT does not accept options" unless request.options.empty?
+ update(request) || create(request)
+ end
+
+ private
+
+ # RKH:TODO: Do not depend on error handling, check if the document exists
+ # first. (Does couchrest support this?)
+ #
+ def get(request)
+ db.get(id_for(request))
+ rescue RestClient::ResourceNotFound
+ Puppet.debug "No couchdb document with id: #{id_for(request)}"
+ return nil
+ end
+
+ def update(request)
+ doc = get request
+ return unless doc
+ doc.merge!(hash_from(request))
+ doc.save
+ return true
+ end
+
+ def create(request)
+ db.save_doc hash_from(request)
+ end
+
+ # 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 && 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 dca435c7d..a8761f874 100755
--- a/lib/puppet/node/facts.rb
+++ b/lib/puppet/node/facts.rb
@@ -16,8 +16,7 @@ class Puppet::Node::Facts
end
end
- # Use the node source as the indirection terminus.
- indirects :facts, :terminus_class => :facter, :extend => NodeExpirer
+ indirects :facts, :terminus_setting => :facts_terminus, :extend => NodeExpirer
attr_accessor :name, :values
@@ -49,6 +48,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.