# frozen_string_literal: true ## # {QB::Role} methods for dealing with role search path. # # Broken out from the main `//lib/qb/role.rb` file because it was starting to # get long and unwieldy. # ## # Refinements # ======================================================================= using NRSER using NRSER::Types # Definitions # ======================================================================= class QB::Role # Constants # ===================================================================== # "Factory defaults" that {QB::Role::PATH} is initialized to, and what it # gets reset to when {QB::Role.reset_path!} is called. # # Read the {QB::Role::PATH} docs for details on how QB role paths work. # # This value is deeply frozen, and you should not attempt to change it - # mess with {QB::Role::PATH} instead. # # @return [Array<String>] # BUILTIN_PATH = [ # Development Paths # ================= # # These come first because: # # 1. They are working dir-local. # # 2. They should only be present in local development, and should be # capable of overriding roles in other local directories to allow # custom development behavior (the same way `./dev/bin` is put in # front or `./bin`). # # Role paths declared in ./dev/ansible.cfg, if it exists. File.join('.', 'dev', 'ansible.cfg'), # Roles in ./dev/roles File.join('.', 'dev', 'roles'), # Working Directory Paths # ======================= # # Next up, `ansible.cfg` and `roles` directory in the working dir. # Makes sense, right? # # ./ansible.cfg File.join('.', 'ansible.cfg'), # ./roles File.join('.', 'roles'), # Working Directory-Local Ansible Directory # ========================================= # # `ansible.cfg` and `roles` in a `./ansible` directory, making a common # place to put Ansible stuff in an project accessible when running from # the project root. # # ./ansible/ansible.cfg File.join('.', 'ansible', 'ansible.cfg'), # ./ansible/roles File.join('.', 'ansible', 'roles'), # TODO Git repo root relative? # Some sort of flag file for a find-up? # System Ansible locations? # QB Gem Role Directories # ======================= # # Last, but far from least, paths provided by the QB Gem to the user's # QB role install location and the roles that come built-in to the gem. QB::USER_ROLES_DIR, QB::GEM_ROLES_DIR, ].freeze # Array of string paths to directories to search for roles or paths to # `ansible.cfg` files to look for an extract role paths from. # # Value is a duplicate of the frozen {QB::Role::BUILTIN_PATH}. You can # reset to those values at any time via {QB::Role.reset_path!}. # # For the moment at least you can just mutate this value like you would # `$LOAD_PATH`: # # QB::Role::PATH.unshift '~/where/some/roles/be' # QB::Role::PATH.unshift '~/my/ansible.cfg' # # The paths are searched from first to last. # # **WARNING** # # Search is **deep** - don't point this at large directory trees and # expect any sort of reasonable performance (any directory that # contains `node_modules` is usually a terrible idea for instance). # # @return [Array<String>] # PATH = BUILTIN_PATH.dup # Class Methods # ====================================================================== # Reset {QB::Role::PATH} to the original built-in values in # {QB::Role::BUILTIN_PATH}. # # Created for testing but might be useful elsewhere as well. # # @return [Array<String>] # The reset {QB::Role::PATH}. # def self.reset_path! PATH.clear BUILTIN_PATH.each { |path| PATH << path } PATH end # .reset_path! # Gets the array of paths to search for QB roles based on {QB::Role::PATH} # and the working directory at the time it's called. # # QB then uses the returned value to figure out what roles are available. # # The process: # # 1. Resolve relative paths against the working directory. # # 2. Load up any `ansible.cfg` files on the path and add any `roles_path` # they define where the `ansible.cfg` entry was in {QB::Role::PATH}. # # @return [Array<Pathname>] # Directories to search for QB roles. # def self.search_path QB::Role::PATH. map { |path| if QB::Ansible::ConfigFile.end_with_config_file?(path) if File.file?(path) QB::Ansible::ConfigFile.new(path).defaults.roles_path end else QB::Util.resolve path end }. flatten. reject(&:nil?) end end # class QB::Role