diff options
-rw-r--r-- | lib/puppet/indirector/rest.rb | 27 | ||||
-rw-r--r-- | lib/puppet/network/http/handler.rb | 12 | ||||
-rw-r--r-- | spec/integration/indirector/rest.rb | 93 | ||||
-rw-r--r-- | spec/unit/network/server.rb | 2 |
4 files changed, 112 insertions, 22 deletions
diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 33ae34006..889f63648 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -4,47 +4,46 @@ require 'uri' # Access objects via REST class Puppet::Indirector::REST < Puppet::Indirector::Terminus def network_fetch(path) - network(path, 'get') + Net::HTTP.start("127.0.0.1", 34343) {|x| x.get("/#{path}").body } end def network_delete(path) - network(path, 'delete') + Net::HTTP.start("127.0.0.1", 34343) {|x| x.delete("/#{path}").body } end def network_put(path, data) - network(path, 'put', data) - end - - def network(path, meth, data = nil) - # TODO: include data here, for #save - Net::HTTP.start("127.0.0.1", 34343) {|x| x.send(meth.to_sym, "/#{path}").body } # weird-ass net/http library + Net::HTTP.start("127.0.0.1", 34343) {|x| x.put("/#{path}", data).body } end def find(name, options = {}) network_result = network_fetch("#{indirection.name}/#{name}") raise YAML.load(network_result) if exception?(network_result) - decoded_result = indirection.model.from_yaml(network_result) + indirection.model.from_yaml(network_result) end def search(name, options = {}) network_results = network_fetch("#{indirection.name}s/#{name}") raise YAML.load(network_results) if exception?(network_results) - decoded_results = YAML.load(network_results.to_s).collect {|result| indirection.model.from_yaml(result) } + YAML.load(network_results.to_s).collect {|result| indirection.model.from_yaml(result) } end def destroy(name, options = {}) network_result = network_delete("#{indirection.name}/#{name}") raise YAML.load(network_result) if exception?(network_result) - decoded_result = YAML.load(network_result.to_s) + YAML.load(network_result.to_s) end - def save - + def save(obj, options = {}) + network_result = network_put("#{indirection.name}/", obj.to_yaml) + # TODO: swap these two lines out: + raise network_result.inspect if exception?(network_result) + # raise YAML.load(network_result) if exception?(network_result) + indirection.model.from_yaml(network_result) end private def exception?(yaml_string) - yaml_string =~ %r{--- !ruby/exception} + yaml_string =~ %r{--- !ruby/exception} end end diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb index 9e6c28512..7113c92d3 100644 --- a/lib/puppet/network/http/handler.rb +++ b/lib/puppet/network/http/handler.rb @@ -44,13 +44,17 @@ module Puppet::Network::HTTP::Handler end def do_save(request, response) - data = body(request) + data = body(request).to_s raise ArgumentError, "No data to save" if !data or data.empty? - args = params(request) - obj = model.new - result = obj.save(args.merge(:data => data)).to_yaml + # args = params(request) + obj = model.from_yaml(data) + result = save_object(obj).to_yaml encode_result(request, response, result) end + + def save_object(obj) + obj.save + end def do_exception(request, response, exception, status=404) encode_result(request, response, exception.to_yaml, status) diff --git a/spec/integration/indirector/rest.rb b/spec/integration/indirector/rest.rb index 46a26ee91..a969a975b 100644 --- a/spec/integration/indirector/rest.rb +++ b/spec/integration/indirector/rest.rb @@ -9,6 +9,7 @@ class Puppet::TestIndirectedFoo indirects :test_indirected_foo, :terminus_setting => :test_indirected_foo_terminus attr_reader :value + attr_accessor :version def initialize(value = 0) @value = value @@ -17,6 +18,10 @@ class Puppet::TestIndirectedFoo def self.from_yaml(yaml) YAML.load(yaml) end + + def name + "bob" + end end # empty Terminus class -- this would normally have to be in a directory findable by the autoloader, but we short-circuit that below @@ -186,7 +191,49 @@ describe Puppet::Indirector::REST do end describe "when saving a model instance over REST" do - it "needs more specs" + before :each do + @instance = Puppet::TestIndirectedFoo.new(42) + @mock_model = stub('faked model', :from_yaml => @instance) + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model) + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).returns(@instance) + end + + describe "when a successful save can be performed" do + before :each do + end + + it "should not fail" do + lambda { @instance.save }.should_not raise_error + end + + it 'should return an instance of the model class' do + @instance.save.class.should == Puppet::TestIndirectedFoo + end + + it 'should return a matching instance of the model class' do + @instance.save.value.should == @instance.value + end + end + + describe "when a save cannot be completed" do + before :each do + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).returns(false) + end + + it "should return failure" do + @instance.save.should == false + end + end + + describe "when an exception is encountered in performing a save" do + before :each do + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).raises(RuntimeError) + end + + it "should raise an exception" do + lambda { @instance.save }.should raise_error(RuntimeError) + end + end end after :each do @@ -357,7 +404,49 @@ describe Puppet::Indirector::REST do end describe "when saving a model instance over REST" do - it "needs more specs" + before :each do + @instance = Puppet::TestIndirectedFoo.new(42) + @mock_model = stub('faked model', :from_yaml => @instance) + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model) + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).returns(@instance) + end + + describe "when a successful save can be performed" do + before :each do + end + + it "should not fail" do + lambda { @instance.save }.should_not raise_error + end + + it 'should return an instance of the model class' do + @instance.save.class.should == Puppet::TestIndirectedFoo + end + + it 'should return a matching instance of the model class' do + @instance.save.value.should == @instance.value + end + end + + describe "when a save cannot be completed" do + before :each do + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).returns(false) + end + + it "should return failure" do + @instance.save.should == false + end + end + + describe "when an exception is encountered in performing a save" do + before :each do + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).raises(RuntimeError) + end + + it "should raise an exception" do + lambda { @instance.save }.should raise_error(RuntimeError) + end + end end after :each do diff --git a/spec/unit/network/server.rb b/spec/unit/network/server.rb index 2e02ffbc3..4e47c22fd 100644 --- a/spec/unit/network/server.rb +++ b/spec/unit/network/server.rb @@ -309,8 +309,6 @@ end describe Class.new, "put these somewhere" do - it "should allow indirections to deny access to services based upon which client is connecting, or whether the client is authorized" - it "should deny access to clients based upon rules" it "should have the ability to use a class-level from_ hook (from_yaml, from_text, etc.) that can be called, based on content-type header, to allow for different deserializations of an object" it "should allow from_* on the inbound :data packet (look at its content_type) when doing a PUT/.new.save" it "should prepend a rest version number on the path (w00t)" |