diff options
| author | Rein Henrichs <rein@puppetlabs.com> | 2010-06-07 15:45:45 -0700 |
|---|---|---|
| committer | James Turnbull <james@lovedthanlost.net> | 2010-06-27 03:54:08 +1000 |
| commit | 97936c6d3fa3950d22266679b65d4a6877008a74 (patch) | |
| tree | 0a3ec96444635c6b7604da50cb79657aabbee448 /lib | |
| parent | db39b7c0848f8931989cbe21ff202552c0ae78c1 (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.rb | 4 | ||||
| -rw-r--r-- | lib/puppet/application/puppetmasterd.rb | 3 | ||||
| -rw-r--r-- | lib/puppet/defaults.rb | 5 | ||||
| -rw-r--r-- | lib/puppet/feature/base.rb | 3 | ||||
| -rw-r--r-- | lib/puppet/indirector/couch.rb | 76 | ||||
| -rw-r--r-- | lib/puppet/indirector/facts/couch.rb | 31 | ||||
| -rwxr-xr-x | lib/puppet/node/facts.rb | 8 |
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. |
