diff --git a/lib/puppet/indirector/couch.rb b/lib/puppet/indirector/couch.rb index fae934fd8..243d33dd4 100644 --- a/lib/puppet/indirector/couch.rb +++ b/lib/puppet/indirector/couch.rb @@ -1,76 +1,78 @@ -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 + def initialize(*args) + raise "Couch terminus not supported without couchrest gem" unless Puppet.features.couchdb? + super + 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 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/spec/unit/indirector/facts/couch_spec.rb b/spec/unit/indirector/facts/couch_spec.rb index 1de2f7dfb..3ac085251 100755 --- a/spec/unit/indirector/facts/couch_spec.rb +++ b/spec/unit/indirector/facts/couch_spec.rb @@ -1,97 +1,103 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/node/facts' +require 'puppet/indirector/facts/couch' -describe "Puppet::Node::Facts::Couch", :if => Puppet.features.couchdb? do - require 'puppet/indirector/facts/couch' if Puppet.features.couchdb? - - 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(fake_request.key).returns(mock_document) - Puppet::Node::Facts::Couch.stubs(:db).returns(@mock_db) +describe "Puppet::Node::Facts::Couch" do + describe "when couchdb is not available", :unless => Puppet.features.couchdb? do + it "should fail to initialize" do + lambda { Puppet::Node::Facts::Couch.new }.should raise_error + end end - subject { Puppet::Node::Facts::Couch } - - describe "#find" do - describe "when the node document exists" 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 + describe "when couchdb is available", :if => Puppet.features.couchdb? 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(fake_request.key).returns(mock_document) + Puppet::Node::Facts::Couch.stubs(:db).returns(@mock_db) end - describe "when the node document does not exist" do - before do - @mock_db.expects(:get). - with(fake_request.key). - raises(RestClient::ResourceNotFound) - end + subject { Puppet::Node::Facts::Couch } - it "should return nil" do - subject.new.find(fake_request).should be_nil + describe "#find" do + describe "when the node document exists" 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 - it "should send Puppet a debug message" do - Puppet.expects(:debug).with("No couchdb document with id: test.local") - subject.new.find(fake_request).should be_nil - end + describe "when the node document does not exist" do + before do + @mock_db.expects(:get). + with(fake_request.key). + raises(RestClient::ResourceNotFound) + end - end - end + it "should return nil" do + subject.new.find(fake_request).should be_nil + end - describe "#save" do - describe "with options" do - subject do - lambda { Puppet::Node::Facts::Couch.new.save(fake_request([1])) } - end + it "should send Puppet a debug message" do + Puppet.expects(:debug).with("No couchdb document with id: test.local") + subject.new.find(fake_request).should be_nil + end - it { should raise_error(ArgumentError, "PUT does not accept options") } + end end - 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 + describe "#save" do + describe "with options" do + subject do + lambda { Puppet::Node::Facts::Couch.new.save(fake_request([1])) } + end - describe "when the document exists" do - before do - @doc = CouchRest::Document.new(:_id => fake_request.key, :facts => fake_request.instance.values) - @mock_db.expects(:get).with(fake_request.key).returns(@doc) + it { should raise_error(ArgumentError, "PUT does not accept options") } end - it "saves the document" do - @doc.expects(:save) + 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 + describe "when the document exists" do + before do + @doc = CouchRest::Document.new(:_id => fake_request.key, :facts => fake_request.instance.values) + @mock_db.expects(:get).with(fake_request.key).returns(@doc) + end + + it "saves the document" do + @doc.expects(:save) + subject.new.save(fake_request) + end - describe "when the document does not exist" do - before do - @mock_db.expects(:get). - with(fake_request.key). - raises(RestClient::ResourceNotFound) end - it "saves the document" do - @mock_db.expects(:save_doc) - subject.new.save(fake_request) + describe "when the document does not exist" do + before do + @mock_db.expects(:get). + with(fake_request.key). + raises(RestClient::ResourceNotFound) + end + + it "saves the document" do + @mock_db.expects(:save_doc) + subject.new.save(fake_request) + end + end end + def fake_request(options={}) + facts = YAML.load_file(File.join(PuppetSpec::FIXTURE_DIR, 'yaml', 'test.local.yaml')) + Struct.new(:instance, :key, :options).new(facts, facts.name, options) + end + private :fake_request end - - def fake_request(options={}) - facts = YAML.load_file(File.join(PuppetSpec::FIXTURE_DIR, 'yaml', 'test.local.yaml')) - Struct.new(:instance, :key, :options).new(facts, facts.name, options) - end - private :fake_request - end