diff options
Diffstat (limited to 'lib/chef/resource_set.rb')
-rw-r--r-- | lib/chef/resource_set.rb | 236 |
1 files changed, 122 insertions, 114 deletions
diff --git a/lib/chef/resource_set.rb b/lib/chef/resource_set.rb index e0e2038f78..8c39065e75 100644 --- a/lib/chef/resource_set.rb +++ b/lib/chef/resource_set.rb @@ -20,141 +20,149 @@ require 'chef/resource' require 'chef/resource_collection/resource_collection_serialization' class Chef - class ResourceSet - include ResourceCollection::ResourceCollectionSerialization + # TODO move into subfolder until we promote these to top level classes + class ResourceCollection + class ResourceSet + include ResourceCollection::ResourceCollectionSerialization - # Matches a multiple resource lookup specification, - # e.g., "service[nginx,unicorn]" - MULTIPLE_RESOURCE_MATCH = /^(.+)\[(.+?),(.+)\]$/ + # Matches a multiple resource lookup specification, + # e.g., "service[nginx,unicorn]" + MULTIPLE_RESOURCE_MATCH = /^(.+)\[(.+?),(.+)\]$/ - # Matches a single resource lookup specification, - # e.g., "service[nginx]" - SINGLE_RESOURCE_MATCH = /^(.+)\[(.+)\]$/ + # Matches a single resource lookup specification, + # e.g., "service[nginx]" + SINGLE_RESOURCE_MATCH = /^(.+)\[(.+)\]$/ - def initialize - @resources_by_key = Hash.new - end + def initialize + @resources_by_key = Hash.new + end - def keys - @resources_by_key.keys - end + def keys + @resources_by_key.keys + end - def insert_as(resource_type, instance_name, resource) - is_chef_resource(resource) - key = ResourceSet.create_key(resource_type, instance_name) - @resources_by_key[key] = resource - end + def insert_as(resource, resource_type=resource.resource_name, instance_name=resource.name) + is_chef_resource!(resource) + key = ResourceSet.create_key(resource_type, instance_name) + @resources_by_key[key] = resource + end + + def lookup(key) + case + when key.kind_of?(String) + lookup_by = key + when key.kind_of?(Chef::Resource) + lookup_by = ResourceSet.create_key(key.resource_name, key.name) + else + raise ArgumentError, "Must pass a Chef::Resource or String to lookup" + end - # TODO when do we need to lookup a resource by resource? That smells like we should still have the resource say how its indexed, or we shouldn't be doing that. - def lookup(resource_type, instance_name) - raise ArgumentError, "Must pass resource_type as a String or Symbol and instance_name as a String" unless - (resource_type.kind_of?(String) || resource_type.kind_of?(Symbol)) && instance_name.kind_of?(String) - key = ResourceSet.create_key(resource_type, instance_name) - res = @resources_by_key[key] - unless res - raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" + res = @resources_by_key[lookup_by] + unless res + raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{lookup_by} (did you define it first?)" + end + res end - res - end - # Find existing resources by searching the list of existing resources. Possible - # forms are: - # - # find(:file => "foobar") - # find(:file => [ "foobar", "baz" ]) - # find("file[foobar]", "file[baz]") - # find("file[foobar,baz]") - # - # Returns the matching resource, or an Array of matching resources. - # - # Raises an ArgumentError if you feed it bad lookup information - # Raises a Runtime Error if it can't find the resources you are looking for. - def find(*args) - results = Array.new - args.each do |arg| - case arg + # Find existing resources by searching the list of existing resources. Possible + # forms are: + # + # find(:file => "foobar") + # find(:file => [ "foobar", "baz" ]) + # find("file[foobar]", "file[baz]") + # find("file[foobar,baz]") + # + # Returns the matching resource, or an Array of matching resources. + # + # Raises an ArgumentError if you feed it bad lookup information + # Raises a Runtime Error if it can't find the resources you are looking for. + def find(*args) + results = Array.new + args.each do |arg| + case arg + when Hash + results << find_resource_by_hash(arg) + when String + results << find_resource_by_string(arg) + else + msg = "arguments to #{self.class.name}#find should be of the form :resource => 'name' or 'resource[name]'" + raise Chef::Exceptions::InvalidResourceSpecification, msg + end + end + flat_results = results.flatten + flat_results.length == 1 ? flat_results[0] : flat_results + end + + # resources is a poorly named, but we have to maintain it for back + # compat. + alias_method :resources, :find + + # Returns true if +query_object+ is a valid string for looking up a + # resource, or raises InvalidResourceSpecification if not. + # === Arguments + # * query_object should be a string of the form + # "resource_type[resource_name]", a single element Hash (e.g., :service => + # "apache2"), or a Chef::Resource (this is the happy path). Other arguments + # will raise an exception. + # === Returns + # * true returns true for all valid input. + # === Raises + # * Chef::Exceptions::InvalidResourceSpecification for all invalid input. + def validate_lookup_spec!(query_object) + case query_object + when Chef::Resource + true + when SINGLE_RESOURCE_MATCH, MULTIPLE_RESOURCE_MATCH + true when Hash - results << find_resource_by_hash(arg) + true when String - results << find_resource_by_string(arg) + raise Chef::Exceptions::InvalidResourceSpecification, + "The string `#{query_object}' is not valid for resource collection lookup. Correct syntax is `resource_type[resource_name]'" else - msg = "arguments to #{self.class.name}#find should be of the form :resource => 'name' or 'resource[name]'" - raise Chef::Exceptions::InvalidResourceSpecification, msg + raise Chef::Exceptions::InvalidResourceSpecification, + "The object `#{query_object.inspect}' is not valid for resource collection lookup. " + + "Use a String like `resource_type[resource_name]' or a Chef::Resource object" end end - flat_results = results.flatten - flat_results.length == 1 ? flat_results[0] : flat_results - end - # resources is a poorly named, but we have to maintain it for back - # compat. - alias_method :resources, :find - - # Returns true if +query_object+ is a valid string for looking up a - # resource, or raises InvalidResourceSpecification if not. - # === Arguments - # * query_object should be a string of the form - # "resource_type[resource_name]", a single element Hash (e.g., :service => - # "apache2"), or a Chef::Resource (this is the happy path). Other arguments - # will raise an exception. - # === Returns - # * true returns true for all valid input. - # === Raises - # * Chef::Exceptions::InvalidResourceSpecification for all invalid input. - def self.validate_lookup_spec!(query_object) - case query_object - when Chef::Resource - true - when SINGLE_RESOURCE_MATCH, MULTIPLE_RESOURCE_MATCH - true - when Hash - true - when String - raise Chef::Exceptions::InvalidResourceSpecification, - "The string `#{query_object}' is not valid for resource collection lookup. Correct syntax is `resource_type[resource_name]'" - else - raise Chef::Exceptions::InvalidResourceSpecification, - "The object `#{query_object.inspect}' is not valid for resource collection lookup. " + - "Use a String like `resource_type[resource_name]' or a Chef::Resource object" + def self.create_key(resource_type, instance_name) + "#{resource_type}[#{instance_name}]" end - end - def self.create_key(resource_type, instance_name) - "#{resource_type}[#{instance_name}]" - end - - private + private - def find_resource_by_hash(arg) - results = Array.new - arg.each do |resource_type, name_list| - instance_names = name_list.kind_of?(Array) ? name_list : [ name_list ] - instance_names.each do |instance_name| - results << lookup(resource_type, instance_name) + def find_resource_by_hash(arg) + results = Array.new + arg.each do |resource_type, name_list| + instance_names = name_list.kind_of?(Array) ? name_list : [ name_list ] + instance_names.each do |instance_name| + results << lookup(ResourceSet.create_key(resource_type, instance_name)) + end end + return results end - return results - end - def find_resource_by_string(arg) - results = Array.new - case arg - when MULTIPLE_RESOURCE_MATCH - resource_type = $1 - arg =~ /^.+\[(.+)\]$/ - resource_list = $1 - resource_list.split(",").each do |instance_name| - results << lookup(resource_type, instance_name) - end - when SINGLE_RESOURCE_MATCH - resource_type = $1 - name = $2 - results << lookup(resource_type, name) - else - raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!" + def find_resource_by_string(arg) + results = Array.new + case arg + when MULTIPLE_RESOURCE_MATCH + resource_type = $1 + arg =~ /^.+\[(.+)\]$/ + resource_list = $1 + resource_list.split(",").each do |instance_name| + results << lookup(ResourceSet.create_key(resource_type, instance_name)) + end + when SINGLE_RESOURCE_MATCH + resource_type = $1 + name = $2 + results << lookup(ResourceSet.create_key(resource_type, name)) + else + raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!" + end + return results end - return results - end + end end end |