diff --git a/lib/puppet/indirector/resource/ral.rb b/lib/puppet/indirector/resource/ral.rb index 3f6c4a49e75..27d4f766aa3 100644 --- a/lib/puppet/indirector/resource/ral.rb +++ b/lib/puppet/indirector/resource/ral.rb @@ -24,7 +24,12 @@ def search( request ) type(request).instances.map do |res| res.to_resource end.find_all do |res| - conditions.all? {|property, value| res.to_resource[property].to_s == value.to_s} + conditions.all? do |property, value| + # even though `res` is an instance of Puppet::Resource, calling + # `res[:name]` on it returns nil, and for some reason it is necessary + # to invoke the Puppet::Resource#copy_as_resource copy constructor... + res.copy_as_resource[property].to_s == value.to_s + end end.sort_by(&:title) end diff --git a/spec/unit/indirector/resource/ral_spec.rb b/spec/unit/indirector/resource/ral_spec.rb index dec444f3e59..3c0111ee2a9 100644 --- a/spec/unit/indirector/resource/ral_spec.rb +++ b/spec/unit/indirector/resource/ral_spec.rb @@ -1,120 +1,85 @@ require 'spec_helper' require 'puppet/indirector/resource/ral' -describe "Puppet::Resource::Ral" do +describe Puppet::Resource::Ral do + let(:my_instance) { Puppet::Type.type(:user).new(:name => "root") } + let(:wrong_instance) { Puppet::Type.type(:user).new(:name => "bob")} + + def stub_retrieve(*instances) + instances.each do |i| + allow(i).to receive(:retrieve).and_return(Puppet::Resource.new(i, nil)) + end + end + + before do + described_class.indirection.terminus_class = :ral + + # make sure we don't try to retrieve current state + allow_any_instance_of(Puppet::Type.type(:user)).to receive(:retrieve).never + stub_retrieve(my_instance, wrong_instance) + end + it "disallows remote requests" do expect(Puppet::Resource::Ral.new.allow_remote_requests?).to eq(false) end describe "find" do - before do - @request = double('request', :key => "user/root") - end - it "should find an existing instance" do - my_resource = double("my user resource") + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ]) - wrong_instance = double("wrong user", :name => "bob") - my_instance = double("my user", :name => "root", :to_resource => my_resource) - - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ]) - expect(Puppet::Resource::Ral.new.find(@request)).to eq(my_resource) + actual_resource = described_class.indirection.find('user/root') + expect(actual_resource.name).to eq('User/root') end it "should produce Puppet::Error instead of ArgumentError" do - @bad_request = double('thiswillcauseanerror', :key => "thiswill/causeanerror") - expect{Puppet::Resource::Ral.new.find(@bad_request)}.to raise_error(Puppet::Error) + expect{described_class.indirection.find('thiswill/causeanerror')}.to raise_error(Puppet::Error) end it "if there is no instance, it should create one" do - wrong_instance = double("wrong user", :name => "bob") - root = double("Root User") - root_resource = double("Root Resource") - - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, wrong_instance ]) - expect(Puppet::Type.type(:user)).to receive(:new).with(hash_including(name: "root")).and_return(root) - expect(root).to receive(:to_resource).and_return(root_resource) - - result = Puppet::Resource::Ral.new.find(@request) + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([wrong_instance]) - expect(result).to eq(root_resource) + expect(Puppet::Type.type(:user)).to receive(:new).with(hash_including(name: "root")).and_return(my_instance) + expect(described_class.indirection.find('user/root')).to be end end describe "search" do - before do - @request = double('request', :key => "user/", :options => {}) - end - it "should convert ral resources into regular resources" do - my_resource = double("my user resource", :title => "my user resource") - my_instance = double("my user", :name => "root", :to_resource => my_resource) + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance ]) - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance ]) - expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource]) + actual = described_class.indirection.search('user') + expect(actual).to contain_exactly(an_instance_of(Puppet::Resource)) end it "should filter results by name if there's a name in the key" do - my_resource = double("my user resource", title: "my user resource") - allow(my_resource).to receive(:to_resource).and_return(my_resource) - allow(my_resource).to receive(:[]).with(:name).and_return("root") - - wrong_resource = double("wrong resource") - allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource) - allow(wrong_resource).to receive(:[]).with(:name).and_return("bad") + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ]) - my_instance = double("my user", :to_resource => my_resource) - wrong_instance = double("wrong user", :to_resource => wrong_resource) - - @request = double('request', :key => "user/root", :options => {}) - - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ]) - expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource]) + actual = described_class.indirection.search('user/root') + expect(actual).to contain_exactly(an_object_having_attributes(name: 'User/root')) end it "should filter results by query parameters" do - wrong_resource = double("my user resource", title: "my user resource") - allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource) - allow(wrong_resource).to receive(:[]).with(:name).and_return("root") - - my_resource = double("wrong resource", title: "wrong resource") - allow(my_resource).to receive(:to_resource).and_return(my_resource) - allow(my_resource).to receive(:[]).with(:name).and_return("bob") + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ]) - my_instance = double("my user", :to_resource => my_resource) - wrong_instance = double("wrong user", :to_resource => wrong_resource) - - @request = double('request', :key => "user/", :options => {:name => "bob"}) - - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ]) - expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource]) + actual = described_class.indirection.search('user', name: 'bob') + expect(actual).to contain_exactly(an_object_having_attributes(name: 'User/bob')) end it "should return sorted results" do - a_resource = double("alice resource") - allow(a_resource).to receive(:to_resource).and_return(a_resource) - allow(a_resource).to receive(:title).and_return("alice") - - b_resource = double("bob resource") - allow(b_resource).to receive(:to_resource).and_return(b_resource) - allow(b_resource).to receive(:title).and_return("bob") - - a_instance = double("alice user", :to_resource => a_resource) - b_instance = double("bob user", :to_resource => b_resource) - - @request = double('request', :key => "user/", :options => {}) + a_instance = Puppet::Type.type(:user).new(:name => "alice") + b_instance = Puppet::Type.type(:user).new(:name => "bob") + stub_retrieve(a_instance, b_instance) + allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ b_instance, a_instance ]) - expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ b_instance, a_instance ]) - expect(Puppet::Resource::Ral.new.search(@request)).to eq([a_resource, b_resource]) + expect(described_class.indirection.search('user').map(&:title)).to eq(['alice', 'bob']) end end describe "save" do it "returns a report covering the application of the given resource to the system" do resource = Puppet::Resource.new(:notify, "the title") - ral = Puppet::Resource::Ral.new - applied_resource, report = ral.save(Puppet::Indirector::Request.new(:ral, :save, 'testing', resource, :environment => Puppet::Node::Environment.remote(:testing))) + applied_resource, report = described_class.indirection.save(resource, nil, environment: Puppet::Node::Environment.remote(:testing)) expect(applied_resource.title).to eq("the title") expect(report.environment).to eq("testing")