diff --git a/changelogs/fragments/7870-homebrew-cask-installed-detection.yml b/changelogs/fragments/7870-homebrew-cask-installed-detection.yml new file mode 100644 index 0000000000..1c70c9a2d4 --- /dev/null +++ b/changelogs/fragments/7870-homebrew-cask-installed-detection.yml @@ -0,0 +1,2 @@ +bugfixes: + - homebrew - detect already installed formulae and casks using JSON output from ``brew info`` (https://github.com/ansible-collections/community.general/issues/864). diff --git a/plugins/modules/homebrew.py b/plugins/modules/homebrew.py index a408f4661f..117b8d422f 100644 --- a/plugins/modules/homebrew.py +++ b/plugins/modules/homebrew.py @@ -165,6 +165,7 @@ changed_pkgs: version_added: '0.2.0' ''' +import json import os.path import re @@ -184,6 +185,10 @@ def _create_regex_group_complement(s): chars = filter(None, (line.split('#')[0].strip() for line in lines)) group = r'[^' + r''.join(chars) + r']' return re.compile(group) + + +def _check_package_in_json(json_output, package_type): + return bool(json_output.get(package_type, []) and json_output[package_type][0].get("installed")) # /utils ------------------------------------------------------------------ }}} @@ -479,17 +484,13 @@ class Homebrew(object): cmd = [ "{brew_path}".format(brew_path=self.brew_path), "info", + "--json=v2", self.current_package, ] rc, out, err = self.module.run_command(cmd) - for line in out.split('\n'): - if ( - re.search(r'Built from source', line) - or re.search(r'Poured from bottle', line) - ): - return True + data = json.loads(out) - return False + 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): diff --git a/tests/integration/targets/homebrew/tasks/casks.yml b/tests/integration/targets/homebrew/tasks/casks.yml new file mode 100644 index 0000000000..42d3515bf2 --- /dev/null +++ b/tests/integration/targets/homebrew/tasks/casks.yml @@ -0,0 +1,99 @@ +--- +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +# Test code for the homebrew module. +# Copyright (c) 2020, Abhijeet Kasurde +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +- name: Find brew binary + command: which brew + register: brew_which + when: ansible_distribution in ['MacOSX'] + +- name: Get owner of brew binary + stat: + path: "{{ brew_which.stdout }}" + register: brew_stat + when: ansible_distribution in ['MacOSX'] + +#- name: Use ignored-pinned option while upgrading all +# homebrew: +# upgrade_all: true +# upgrade_options: ignore-pinned +# become: true +# become_user: "{{ brew_stat.stat.pw_name }}" +# register: upgrade_option_result +# environment: +# HOMEBREW_NO_AUTO_UPDATE: True + +#- assert: +# that: +# - upgrade_option_result.changed + +- vars: + package_name: kitty + + block: + - name: Make sure {{ package_name }} package is not installed + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + + - name: Install {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: present + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - package_result.changed + + - name: Again install {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: present + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - not package_result.changed + + - name: Uninstall {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - package_result.changed + + - name: Again uninstall {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - not package_result.changed diff --git a/tests/integration/targets/homebrew/tasks/formulae.yml b/tests/integration/targets/homebrew/tasks/formulae.yml new file mode 100644 index 0000000000..1db3ef1a6a --- /dev/null +++ b/tests/integration/targets/homebrew/tasks/formulae.yml @@ -0,0 +1,99 @@ +--- +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +# Test code for the homebrew module. +# Copyright (c) 2020, Abhijeet Kasurde +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +- name: Find brew binary + command: which brew + register: brew_which + when: ansible_distribution in ['MacOSX'] + +- name: Get owner of brew binary + stat: + path: "{{ brew_which.stdout }}" + register: brew_stat + when: ansible_distribution in ['MacOSX'] + +#- name: Use ignored-pinned option while upgrading all +# homebrew: +# upgrade_all: true +# upgrade_options: ignore-pinned +# become: true +# become_user: "{{ brew_stat.stat.pw_name }}" +# register: upgrade_option_result +# environment: +# HOMEBREW_NO_AUTO_UPDATE: True + +#- assert: +# that: +# - upgrade_option_result.changed + +- vars: + package_name: gnu-tar + + block: + - name: Make sure {{ package_name }} package is not installed + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + + - name: Install {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: present + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - package_result.changed + + - name: Again install {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: present + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - not package_result.changed + + - name: Uninstall {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - package_result.changed + + - name: Again uninstall {{ package_name }} package using homebrew + homebrew: + name: "{{ package_name }}" + state: absent + update_homebrew: false + become: true + become_user: "{{ brew_stat.stat.pw_name }}" + register: package_result + + - assert: + that: + - not package_result.changed diff --git a/tests/integration/targets/homebrew/tasks/main.yml b/tests/integration/targets/homebrew/tasks/main.yml index 1db3ef1a6a..f5479917ea 100644 --- a/tests/integration/targets/homebrew/tasks/main.yml +++ b/tests/integration/targets/homebrew/tasks/main.yml @@ -9,91 +9,9 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -- name: Find brew binary - command: which brew - register: brew_which - when: ansible_distribution in ['MacOSX'] - -- name: Get owner of brew binary - stat: - path: "{{ brew_which.stdout }}" - register: brew_stat - when: ansible_distribution in ['MacOSX'] - -#- name: Use ignored-pinned option while upgrading all -# homebrew: -# upgrade_all: true -# upgrade_options: ignore-pinned -# become: true -# become_user: "{{ brew_stat.stat.pw_name }}" -# register: upgrade_option_result -# environment: -# HOMEBREW_NO_AUTO_UPDATE: True - -#- assert: -# that: -# - upgrade_option_result.changed - -- vars: - package_name: gnu-tar - +- block: + - include_tasks: 'formulae.yml' + +- when: ansible_distribution in ['MacOSX'] block: - - name: Make sure {{ package_name }} package is not installed - homebrew: - name: "{{ package_name }}" - state: absent - update_homebrew: false - become: true - become_user: "{{ brew_stat.stat.pw_name }}" - - - name: Install {{ package_name }} package using homebrew - homebrew: - name: "{{ package_name }}" - state: present - update_homebrew: false - become: true - become_user: "{{ brew_stat.stat.pw_name }}" - register: package_result - - - assert: - that: - - package_result.changed - - - name: Again install {{ package_name }} package using homebrew - homebrew: - name: "{{ package_name }}" - state: present - update_homebrew: false - become: true - become_user: "{{ brew_stat.stat.pw_name }}" - register: package_result - - - assert: - that: - - not package_result.changed - - - name: Uninstall {{ package_name }} package using homebrew - homebrew: - name: "{{ package_name }}" - state: absent - update_homebrew: false - become: true - become_user: "{{ brew_stat.stat.pw_name }}" - register: package_result - - - assert: - that: - - package_result.changed - - - name: Again uninstall {{ package_name }} package using homebrew - homebrew: - name: "{{ package_name }}" - state: absent - update_homebrew: false - become: true - become_user: "{{ brew_stat.stat.pw_name }}" - register: package_result - - - assert: - that: - - not package_result.changed + - include_tasks: 'casks.yml'