diff options
-rw-r--r-- | lib/puppet/indirector/rest.rb | 35 | ||||
-rw-r--r-- | spec/integration/indirector/rest.rb | 76 | ||||
-rwxr-xr-x | spec/unit/indirector/rest.rb | 59 |
3 files changed, 157 insertions, 13 deletions
diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 0c86b2706..076e96356 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -4,19 +4,38 @@ require 'uri' # Access objects via REST class Puppet::Indirector::REST < Puppet::Indirector::Terminus def network_fetch(path) - # TODO: url_encode path, set proper server + port Net::HTTP.get(URI.parse("http://127.0.0.1:34343/#{path}")) end + def network_delete(path) + Net::HTTP.start("127.0.0.1", 34343) {|x| x.delete("/#{path}").body } # weird-ass net/http library + end + def find(name, options = {}) - network_result = network_fetch("#{indirection.name}/#{name}") - raise YAML.load(network_result) if network_result =~ %r{--- !ruby/exception} - decoded_result = indirection.model.from_yaml(network_result) + network_result = network_fetch("#{indirection.name}/#{name}") + raise YAML.load(network_result) if exception?(network_result) + decoded_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) } + 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) + end + + def save + end - def search(key, options = {}) - network_results = network_fetch("#{indirection.name}s/#{key}") - raise YAML.load(network_results) if network_results =~ %r{--- !ruby/exception} - decoded_results = YAML.load(network_results.to_s).collect {|result| indirection.model.from_yaml(result) } + private + + def exception?(yaml_string) + yaml_string =~ %r{--- !ruby/exception} end end diff --git a/spec/integration/indirector/rest.rb b/spec/integration/indirector/rest.rb index 418575fb6..46a26ee91 100644 --- a/spec/integration/indirector/rest.rb +++ b/spec/integration/indirector/rest.rb @@ -146,7 +146,43 @@ describe Puppet::Indirector::REST do end describe "when destroying a model instance over REST" do - it "needs more specs" + describe "when a matching model instance can be found" do + before :each do + @mock_model = stub('faked model', :destroy => true) + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should not fail" do + lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should_not raise_error + end + + it 'should return success' do + Puppet::TestIndirectedFoo.destroy('bar').should == true + end + end + + describe "when no matching model instance can be found" do + before :each do + @mock_model = stub('faked model', :destroy => false) + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should return failure" do + Puppet::TestIndirectedFoo.destroy('bar').should == false + end + end + + describe "when an exception is encountered in destroying a model instance" do + before :each do + @mock_model = stub('faked model') + @mock_model.stubs(:destroy).raises(RuntimeError) + Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should raise an exception" do + lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should raise_error(RuntimeError) + end + end end describe "when saving a model instance over REST" do @@ -281,7 +317,43 @@ describe Puppet::Indirector::REST do end describe "when destroying a model instance over REST" do - it "needs more specs" + describe "when a matching model instance can be found" do + before :each do + @mock_model = stub('faked model', :destroy => true) + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should not fail" do + lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should_not raise_error + end + + it 'should return success' do + Puppet::TestIndirectedFoo.destroy('bar').should == true + end + end + + describe "when no matching model instance can be found" do + before :each do + @mock_model = stub('faked model', :destroy => false) + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should return failure" do + Puppet::TestIndirectedFoo.destroy('bar').should == false + end + end + + describe "when an exception is encountered in destroying a model instance" do + before :each do + @mock_model = stub('faked model') + @mock_model.stubs(:destroy).raises(RuntimeError) + Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model) + end + + it "should raise an exception" do + lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should raise_error(RuntimeError) + end + end end describe "when saving a model instance over REST" do diff --git a/spec/unit/indirector/rest.rb b/spec/unit/indirector/rest.rb index 37c0480ed..fb3790e0c 100755 --- a/spec/unit/indirector/rest.rb +++ b/spec/unit/indirector/rest.rb @@ -19,6 +19,28 @@ describe Puppet::Indirector::REST do @searcher = @rest_class.new end + + describe "when doing a network fetch" do + it "should escape the provided path" + it "should look up the appropriate remote server" + it "should look up the appropriate remote port" + it "should use the GET http method" + it "should use the appropriate remote server" + it "should use the appropriate remote port" + it "should use the escaped provided path" + it "should return the results of the GET request" + end + + describe "when doing a network delete" do + it "should escape the provided path" + it "should look up the appropriate remote server" + it "should look up the appropriate remote port" + it "should use the delete http method" + it "should use the appropriate remote server" + it "should use the appropriate remote port" + it "should use the escaped provided path" + it "should return the results of the DELETE request" + end describe "when doing a find" do before :each do @@ -106,9 +128,40 @@ describe Puppet::Indirector::REST do end describe "when doing a destroy" do - it "should deserialize result data into a boolean" - it "should generate an error when result data deserializes improperly" - it "should generate an error when result data specifies an error" + before :each do + @result = true.to_yaml + @searcher.stubs(:network_delete).returns(@result) # neuter the network connection + @model.stubs(:from_yaml).returns(@instance) + end + + it "should look up the model instance over the network" do + @searcher.expects(:network_delete).returns(@result) + @searcher.destroy('foo') + end + + it "should look up the model instance using the named indirection" do + @searcher.expects(:network_delete).with {|path| path =~ %r{^#{@indirection.name.to_s}/} }.returns(@result) + @searcher.destroy('foo') + end + + it "should look up the model instance using the provided key" do + @searcher.expects(:network_delete).with {|path| path =~ %r{/foo$} }.returns(@result) + @searcher.destroy('foo') + end + + it "should deserialize result data" do + YAML.expects(:load).with(@result) + @searcher.destroy('foo') + end + + it "should return deserialized result data" do + @searcher.destroy('foo').should == true + end + + it "should generate an error when result data specifies an error" do + @searcher.stubs(:network_delete).returns(RuntimeError.new("bogus").to_yaml) + lambda { @searcher.destroy('foo') }.should raise_error(RuntimeError) + end end describe "when doing a save" do |