diff options
Diffstat (limited to 'ansible_collections/community/general/plugins/modules/homebrew.py')
-rw-r--r-- | ansible_collections/community/general/plugins/modules/homebrew.py | 157 |
1 files changed, 47 insertions, 110 deletions
diff --git a/ansible_collections/community/general/plugins/modules/homebrew.py b/ansible_collections/community/general/plugins/modules/homebrew.py index 5d471797a..2b60846b4 100644 --- a/ansible_collections/community/general/plugins/modules/homebrew.py +++ b/ansible_collections/community/general/plugins/modules/homebrew.py @@ -76,6 +76,13 @@ options: type: list elements: str version_added: '0.2.0' + force_formula: + description: + - Force the package(s) to be treated as a formula (equivalent to C(brew --formula)). + - To install a cask, use the M(community.general.homebrew_cask) module. + type: bool + default: false + version_added: 9.0.0 notes: - When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the O(name) option. @@ -141,6 +148,12 @@ EXAMPLES = ''' community.general.homebrew: upgrade_all: true upgrade_options: ignore-pinned + +- name: Force installing a formula whose name is also a cask name + community.general.homebrew: + name: ambiguous_formula + state: present + force_formula: true ''' RETURN = ''' @@ -166,9 +179,10 @@ changed_pkgs: ''' import json -import os.path import re +from ansible_collections.community.general.plugins.module_utils.homebrew import HomebrewValidate + from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import iteritems, string_types @@ -195,99 +209,8 @@ def _check_package_in_json(json_output, package_type): class Homebrew(object): '''A class to manage Homebrew packages.''' - # class regexes ------------------------------------------------ {{{ - VALID_PATH_CHARS = r''' - \w # alphanumeric characters (i.e., [a-zA-Z0-9_]) - \s # spaces - : # colons - {sep} # the OS-specific path separator - . # dots - \- # dashes - '''.format(sep=os.path.sep) - - VALID_BREW_PATH_CHARS = r''' - \w # alphanumeric characters (i.e., [a-zA-Z0-9_]) - \s # spaces - {sep} # the OS-specific path separator - . # dots - \- # dashes - '''.format(sep=os.path.sep) - - VALID_PACKAGE_CHARS = r''' - \w # alphanumeric characters (i.e., [a-zA-Z0-9_]) - . # dots - / # slash (for taps) - \+ # plusses - \- # dashes - : # colons (for URLs) - @ # at-sign - ''' - - INVALID_PATH_REGEX = _create_regex_group_complement(VALID_PATH_CHARS) - INVALID_BREW_PATH_REGEX = _create_regex_group_complement(VALID_BREW_PATH_CHARS) - INVALID_PACKAGE_REGEX = _create_regex_group_complement(VALID_PACKAGE_CHARS) - # /class regexes ----------------------------------------------- }}} - # class validations -------------------------------------------- {{{ @classmethod - def valid_path(cls, path): - ''' - `path` must be one of: - - list of paths - - a string containing only: - - alphanumeric characters - - dashes - - dots - - spaces - - colons - - os.path.sep - ''' - - if isinstance(path, string_types): - return not cls.INVALID_PATH_REGEX.search(path) - - try: - iter(path) - except TypeError: - return False - else: - paths = path - return all(cls.valid_brew_path(path_) for path_ in paths) - - @classmethod - def valid_brew_path(cls, brew_path): - ''' - `brew_path` must be one of: - - None - - a string containing only: - - alphanumeric characters - - dashes - - dots - - spaces - - os.path.sep - ''' - - if brew_path is None: - return True - - return ( - isinstance(brew_path, string_types) - and not cls.INVALID_BREW_PATH_REGEX.search(brew_path) - ) - - @classmethod - def valid_package(cls, package): - '''A valid package is either None or alphanumeric.''' - - if package is None: - return True - - return ( - isinstance(package, string_types) - and not cls.INVALID_PACKAGE_REGEX.search(package) - ) - - @classmethod def valid_state(cls, state): ''' A valid state is one of: @@ -346,7 +269,7 @@ class Homebrew(object): @path.setter def path(self, path): - if not self.valid_path(path): + if not HomebrewValidate.valid_path(path): self._path = [] self.failed = True self.message = 'Invalid path: {0}.'.format(path) @@ -366,7 +289,7 @@ class Homebrew(object): @brew_path.setter def brew_path(self, brew_path): - if not self.valid_brew_path(brew_path): + if not HomebrewValidate.valid_brew_path(brew_path): self._brew_path = None self.failed = True self.message = 'Invalid brew_path: {0}.'.format(brew_path) @@ -391,7 +314,7 @@ class Homebrew(object): @current_package.setter def current_package(self, package): - if not self.valid_package(package): + if not HomebrewValidate.valid_package(package): self._current_package = None self.failed = True self.message = 'Invalid package: {0}.'.format(package) @@ -404,7 +327,8 @@ class Homebrew(object): def __init__(self, module, path, packages=None, state=None, update_homebrew=False, upgrade_all=False, - install_options=None, upgrade_options=None): + install_options=None, upgrade_options=None, + force_formula=False): if not install_options: install_options = list() if not upgrade_options: @@ -414,7 +338,8 @@ class Homebrew(object): state=state, update_homebrew=update_homebrew, upgrade_all=upgrade_all, install_options=install_options, - upgrade_options=upgrade_options,) + upgrade_options=upgrade_options, + force_formula=force_formula) self._prep() @@ -476,7 +401,7 @@ class Homebrew(object): # checks ------------------------------------------------------- {{{ def _current_package_is_installed(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -487,17 +412,19 @@ class Homebrew(object): "--json=v2", self.current_package, ] + if self.force_formula: + cmd.append("--formula") rc, out, err = self.module.run_command(cmd) - if err: + if rc != 0: self.failed = True - self.message = err.strip() + self.message = err.strip() or ("Unknown failure with exit code %d" % rc) raise HomebrewException(self.message) data = json.loads(out) return _check_package_in_json(data, "formulae") or _check_package_in_json(data, "casks") def _current_package_is_outdated(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): return False rc, out, err = self.module.run_command([ @@ -509,7 +436,7 @@ class Homebrew(object): return rc != 0 def _current_package_is_installed_from_head(self): - if not Homebrew.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): return False elif not self._current_package_is_installed(): return False @@ -607,7 +534,7 @@ class Homebrew(object): # installed ------------------------------ {{{ def _install_current_package(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -632,10 +559,15 @@ class Homebrew(object): else: head = None + if self.force_formula: + formula = '--formula' + else: + formula = None + opts = ( [self.brew_path, 'install'] + self.install_options - + [self.current_package, head] + + [self.current_package, head, formula] ) cmd = [opt for opt in opts if opt] rc, out, err = self.module.run_command(cmd) @@ -663,7 +595,7 @@ class Homebrew(object): def _upgrade_current_package(self): command = 'upgrade' - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -734,7 +666,7 @@ class Homebrew(object): # uninstalled ---------------------------- {{{ def _uninstall_current_package(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -783,7 +715,7 @@ class Homebrew(object): # linked --------------------------------- {{{ def _link_current_package(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -830,7 +762,7 @@ class Homebrew(object): # unlinked ------------------------------- {{{ def _unlink_current_package(self): - if not self.valid_package(self.current_package): + if not HomebrewValidate.valid_package(self.current_package): self.failed = True self.message = 'Invalid package: {0}.'.format(self.current_package) raise HomebrewException(self.message) @@ -919,7 +851,11 @@ def main(): default=None, type='list', elements='str', - ) + ), + force_formula=dict( + default=False, + type='bool', + ), ), supports_check_mode=True, ) @@ -951,6 +887,7 @@ def main(): if state in ('absent', 'removed', 'uninstalled'): state = 'absent' + force_formula = p['force_formula'] update_homebrew = p['update_homebrew'] if not update_homebrew: module.run_command_environ_update.update( @@ -967,7 +904,7 @@ def main(): brew = Homebrew(module=module, path=path, packages=packages, state=state, update_homebrew=update_homebrew, upgrade_all=upgrade_all, install_options=install_options, - upgrade_options=upgrade_options) + upgrade_options=upgrade_options, force_formula=force_formula) (failed, changed, message) = brew.run() changed_pkgs = brew.changed_pkgs unchanged_pkgs = brew.unchanged_pkgs |