# # Author:: Tyler Ball () # Copyright:: Copyright (c) 2014 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'spec_helper' describe Chef::ResourceCollection::ResourceSet do let(:collection) { Chef::ResourceCollection::ResourceSet.new } let(:zen_master_name) { "Neo" } let(:zen_master2_name) { "Morpheus" } let(:zen_follower_name) { "Squid" } let(:zen_master) { Chef::Resource::ZenMaster.new(zen_master_name) } let(:zen_master2) { Chef::Resource::ZenMaster.new(zen_master2_name) } let(:zen_follower) { Chef::Resource::ZenFollower.new(zen_follower_name) } describe "initialize" do it "should return a Chef::ResourceSet" do expect(collection).to be_instance_of(Chef::ResourceCollection::ResourceSet) end end describe "keys" do it "should return an empty list for an empty ResourceSet" do expect(collection.keys).to eq([]) end it "should return the keys for a non-empty ResourceSet" do collection.instance_variable_get(:@resources_by_key)["key"] = nil expect(collection.keys).to eq(["key"]) end end describe "insert_as, lookup and find" do # To validate insert_as you need lookup, and vice-versa - putting all tests in 1 context to avoid duplication it "should accept only Chef::Resources" do expect { collection.insert_as(zen_master) }.to_not raise_error expect { collection.insert_as("string") }.to raise_error(ArgumentError) end it "should allow you to lookup resources by a default .to_s" do collection.insert_as(zen_master) expect(collection.lookup(zen_master.to_s)).to equal(zen_master) end it "should use a custom type and name to insert" do collection.insert_as(zen_master, "OtherResource", "other_resource") expect(collection.lookup("OtherResource[other_resource]")).to equal(zen_master) end it "should raise an exception if you send something strange to lookup" do expect { collection.lookup(:symbol) }.to raise_error(ArgumentError) end it "should raise an exception if it cannot find a resource with lookup" do expect { collection.lookup(zen_master.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound) end it "should find a resource by type symbol and name" do collection.insert_as(zen_master) expect(collection.find(:zen_master => zen_master_name)).to equal(zen_master) end it "should find a resource by type symbol and array of names" do collection.insert_as(zen_master) collection.insert_as(zen_master2) check_by_names(collection.find(:zen_master => [zen_master_name,zen_master2_name]), zen_master_name, zen_master2_name) end it "should find a resource by type symbol and array of names with custom names" do collection.insert_as(zen_master, :zzz, "name1") collection.insert_as(zen_master2, :zzz, "name2") check_by_names(collection.find( :zzz => ["name1","name2"]), zen_master_name, zen_master2_name) end it "should find resources of multiple kinds (:zen_master => a, :zen_follower => b)" do collection.insert_as(zen_master) collection.insert_as(zen_follower) check_by_names(collection.find(:zen_master => [zen_master_name], :zen_follower => [zen_follower_name]), zen_master_name, zen_follower_name) end it "should find resources of multiple kinds (:zen_master => a, :zen_follower => b with custom names)" do collection.insert_as(zen_master, :zzz, "name1") collection.insert_as(zen_master2, :zzz, "name2") collection.insert_as(zen_follower, :yyy, "name3") check_by_names(collection.find(:zzz => ["name1","name2"], :yyy => ["name3"]), zen_master_name, zen_follower_name, zen_master2_name) end it "should find a resource by string zen_master[a]" do collection.insert_as(zen_master) expect(collection.find("zen_master[#{zen_master_name}]")).to eq(zen_master) end it "should find a resource by string zen_master[a] with custom names" do collection.insert_as(zen_master, :zzz, "name1") expect(collection.find("zzz[name1]")).to eq(zen_master) end it "should find resources by strings of zen_master[a,b]" do collection.insert_as(zen_master) collection.insert_as(zen_master2) check_by_names(collection.find("zen_master[#{zen_master_name},#{zen_master2_name}]"), zen_master_name, zen_master2_name) end it "should find resources by strings of zen_master[a,b] with custom names" do collection.insert_as(zen_master, :zzz, "name1") collection.insert_as(zen_master2, :zzz, "name2") check_by_names(collection.find("zzz[name1,name2]"), zen_master_name, zen_master2_name) end it "should find resources of multiple types by strings of zen_master[a]" do collection.insert_as(zen_master) collection.insert_as(zen_follower) check_by_names(collection.find("zen_master[#{zen_master_name}]", "zen_follower[#{zen_follower_name}]"), zen_master_name, zen_follower_name) end it "should find resources of multiple types by strings of zen_master[a] with custom names" do collection.insert_as(zen_master, :zzz, "name1") collection.insert_as(zen_master2, :zzz, "name2") collection.insert_as(zen_follower, :yyy, "name3") check_by_names(collection.find("zzz[name1,name2]", "yyy[name3]"), zen_master_name, zen_follower_name,zen_master2_name) end it "should only keep the last copy when multiple instances of a Resource are inserted" do collection.insert_as(zen_master) expect(collection.find("zen_master[#{zen_master_name}]")).to eq(zen_master) new_zm =zen_master.dup new_zm.retries = 10 expect(new_zm).to_not eq(zen_master) collection.insert_as(new_zm) expect(collection.find("zen_master[#{zen_master_name}]")).to eq(new_zm) end it "should raise an exception if you pass a bad name to resources" do expect { collection.find("michael jackson") }.to raise_error(ArgumentError) end it "should raise an exception if you pass something other than a string or hash to resource" do expect { collection.find([Array.new]) }.to raise_error(ArgumentError) end it "raises an error when attempting to find a resource that does not exist" do expect { collection.find("script[nonesuch]") }.to raise_error(Chef::Exceptions::ResourceNotFound) end end describe "validate_lookup_spec!" do it "accepts a string of the form 'resource_type[resource_name]'" do expect(collection.validate_lookup_spec!("resource_type[resource_name]")).to be_truthy end it "accepts a single-element :resource_type => 'resource_name' Hash" do expect(collection.validate_lookup_spec!(:service => "apache2")).to be_truthy end it "accepts a chef resource object" do expect(collection.validate_lookup_spec!(zen_master)).to be_truthy end it "rejects a malformed query string" do expect { collection.validate_lookup_spec!("resource_type[missing-end-bracket") }.to \ raise_error(Chef::Exceptions::InvalidResourceSpecification) end it "rejects an argument that is not a String, Hash, or Chef::Resource" do expect { collection.validate_lookup_spec!(Object.new) }.to \ raise_error(Chef::Exceptions::InvalidResourceSpecification) end end def check_by_names(results, *names) expect(results.size).to eq(names.size) names.each do |name| expect(results.detect{|r| r.name == name}).to_not eq(nil) end end end