module PoolParty # Abstracts out the searchable path for a resource such as a # template file, key, or clouds.rb # # NOTE: this is currently _only_ implemented on templates # (PoolParty::Resources::File) and not yet working on clouds.rb or key files. # These will eventually be refactored to use this class. module SearchablePaths def self.included(mod) mod.extend(ClassMethods) end module ClassMethods # Specify that a particular class has methods for searchable paths. # # Options: # * :dirs: array of directories to look in *under* the search paths. (default: ["/"]) # * :dir: set the directory to look in *under* the search paths. Use either dir or dirs, not both. (default: +/+) # * :paths: overwrite all default paths and set the paths to this array exactly # * :append_paths: append these paths to any existing paths # * :prepend_paths: prepend these paths to any existing paths def has_searchable_paths(opts={}) class_eval do extend PoolParty::SearchablePaths::SingletonMethods @searchable_paths_dirs = [opts[:dir]] if opts[:dir] @searchable_paths_dirs = opts[:dirs] if opts[:dirs] @paths_override = opts[:paths] if opts[:paths] @paths_prepend = opts[:prepend_paths] || [] @paths_append = opts[:append_paths] || [] end include PoolParty::SearchablePaths::InstanceMethods end end module SingletonMethods def searchable_paths_dir; @searchable_paths_dirs.first; end def searchable_paths_dirs @searchable_paths_dirs && @searchable_paths_dirs.size > 0 ? @searchable_paths_dirs : ["/"] end # The default paths are primarily defined in PoolParty::Default. These are the default search paths in order: # # * current working directory (Dir.pwd) # * ~/.poolparty # * ~/.ec2 # * /etc/poolparty # * /var/poolparty def default_paths @default_searchable_paths ||= [ Dir.pwd, PoolParty::Default.poolparty_home_path, PoolParty::Default.base_keypair_path, PoolParty::Default.poolparty_src_path, PoolParty::Default.poolparty_src_path/:lib/:poolparty, PoolParty::Default.base_config_directory, PoolParty::Default.remote_storage_path ] end def add_searchable_path(path) default_paths # instantiate @default_searchable_paths @default_searchable_paths << path end # returns the full set of valid searchable paths, given the options def searchable_paths return @paths_override if @paths_override && @paths_override.size > 0 @paths_prepend + default_paths + @paths_append end end module InstanceMethods # Searches for +filepath+ in the searchable_paths iff +filepath+ # doesn't exist. e.g. +filepath+ is interpreted *first* as an absolute # path, if +filepath+ doesn't exist verbatim then it looks for the file # in the searchable_paths. # # Returns +nil+ if the file cannot be found. def search_in_known_locations(filepath, additional_search_paths=[]) return filepath if ::File.exists?(filepath) # return the file if its an absolute path additional_search_paths.each do |path| full_path = ::File.expand_path(path / filepath) return full_path if ::File.exists?(full_path) end self.class.searchable_paths.each do |path| self.class.searchable_paths_dirs.each do |dir| full_path = ::File.expand_path(path / dir / filepath) return full_path if ::File.exists?(full_path) end end nil end alias_method :find_file, :search_in_known_locations end end end