Homebrew Cask: Multiple updates (#35759)

pull/35910/head
Daniel Jaouen 7 years ago committed by Sam Doran
parent abbac1a2ff
commit 33cbbe0b39

@ -42,7 +42,7 @@ options:
state: state:
description: description:
- state of the cask - state of the cask
choices: [ 'present', 'absent' ] choices: [ 'present', 'absent', 'upgraded' ]
required: false required: false
default: present default: present
update_homebrew: update_homebrew:
@ -61,6 +61,24 @@ options:
default: null default: null
aliases: ['options'] aliases: ['options']
version_added: "2.2" version_added: "2.2"
accept_external_apps:
description:
- allow external apps
required: false
default: False
version_added: "2.5.0"
upgrade_all:
description:
- upgrade all casks (mutually exclusive with `upgrade`)
required: False
default: False
version_added: "2.5.0"
upgrade:
description:
- upgrade all casks (mutually exclusive with `upgrade_all`)
required: False
default: False
version_added: "2.5.0"
''' '''
EXAMPLES = ''' EXAMPLES = '''
- homebrew_cask: - homebrew_cask:
@ -81,10 +99,24 @@ EXAMPLES = '''
state: present state: present
install_options: 'debug,appdir=/Applications' install_options: 'debug,appdir=/Applications'
- homebrew_cask:
name: alfred
state: present
allow_external_apps: True
- homebrew_cask: - homebrew_cask:
name: alfred name: alfred
state: absent state: absent
install_options: force install_options: force
- homebrew_cask:
upgrade_all: true
- homebrew_cask:
name: alfred
state: upgraded
install_options: force
''' '''
import os.path import os.path
@ -225,7 +257,6 @@ class HomebrewCask(object):
'''A valid module is an instance of AnsibleModule.''' '''A valid module is an instance of AnsibleModule.'''
return isinstance(module, AnsibleModule) return isinstance(module, AnsibleModule)
# /class validations ------------------------------------------- }}} # /class validations ------------------------------------------- }}}
# class properties --------------------------------------------- {{{ # class properties --------------------------------------------- {{{
@ -308,13 +339,16 @@ class HomebrewCask(object):
# /class properties -------------------------------------------- }}} # /class properties -------------------------------------------- }}}
def __init__(self, module, path=path, casks=None, state=None, def __init__(self, module, path=path, casks=None, state=None,
update_homebrew=False, install_options=None): update_homebrew=False, install_options=None,
accept_external_apps=False, upgrade_all=False):
if not install_options: if not install_options:
install_options = list() install_options = list()
self._setup_status_vars() self._setup_status_vars()
self._setup_instance_vars(module=module, path=path, casks=casks, self._setup_instance_vars(module=module, path=path, casks=casks,
state=state, update_homebrew=update_homebrew, state=state, update_homebrew=update_homebrew,
install_options=install_options,) install_options=install_options,
accept_external_apps=accept_external_apps,
upgrade_all=upgrade_all, )
self._prep() self._prep()
@ -373,6 +407,19 @@ class HomebrewCask(object):
return (failed, changed, message) return (failed, changed, message)
# checks ------------------------------------------------------- {{{ # checks ------------------------------------------------------- {{{
def _current_cask_is_outdated(self):
if not self.valid_cask(self.current_cask):
return False
rc, out, err = self.module.run_command([
self.brew_path,
'cask',
'outdated',
self.current_cask,
])
return out != ""
def _current_cask_is_installed(self): def _current_cask_is_installed(self):
if not self.valid_cask(self.current_cask): if not self.valid_cask(self.current_cask):
self.failed = True self.failed = True
@ -382,33 +429,33 @@ class HomebrewCask(object):
cmd = [ cmd = [
"{brew_path}".format(brew_path=self.brew_path), "{brew_path}".format(brew_path=self.brew_path),
"cask", "cask",
"list" "list",
self.current_cask
] ]
rc, out, err = self.module.run_command(cmd) rc, out, err = self.module.run_command(cmd)
if 'nothing to list' in err: if re.search(r'Error: Cask .* is not installed.', err):
return False return False
elif rc == 0:
casks = [cask_.strip() for cask_ in out.split('\n') if cask_.strip()]
return self.current_cask in casks
else: else:
self.failed = True return True
self.message = err.strip()
raise HomebrewCaskException(self.message)
# /checks ------------------------------------------------------ }}} # /checks ------------------------------------------------------ }}}
# commands ----------------------------------------------------- {{{ # commands ----------------------------------------------------- {{{
def _run(self): def _run(self):
if self.update_homebrew: if self.upgrade_all:
self._update_homebrew() return self._upgrade_all()
if self.state == 'installed': if self.casks:
return self._install_casks() if self.state == 'installed':
elif self.state == 'absent': return self._install_casks()
return self._uninstall_casks() elif self.state == 'upgraded':
return self._upgrade_casks()
elif self.state == 'absent':
return self._uninstall_casks()
if self.command: self.failed = True
return self._command() self.message = "You must select a cask to install."
raise HomebrewCaskException(self.message)
# updated -------------------------------- {{{ # updated -------------------------------- {{{
def _update_homebrew(self): def _update_homebrew(self):
@ -436,6 +483,33 @@ class HomebrewCask(object):
raise HomebrewCaskException(self.message) raise HomebrewCaskException(self.message)
# /updated ------------------------------- }}} # /updated ------------------------------- }}}
# _upgrade_all --------------------------- {{{
def _upgrade_all(self):
if self.module.check_mode:
self.changed = True
self.message = 'Casks would be upgraded.'
raise HomebrewCaskException(self.message)
rc, out, err = self.module.run_command([
self.brew_path,
'cask',
'upgrade',
])
if rc == 0:
if re.search(r'==> No Casks to upgrade', out.strip(), re.IGNORECASE):
self.message = 'Homebrew casks already upgraded.'
else:
self.changed = True
self.message = 'Homebrew casks upgraded.'
return True
else:
self.failed = True
self.message = err.strip()
raise HomebrewCaskException(self.message)
# /_upgrade_all -------------------------- }}}
# installed ------------------------------ {{{ # installed ------------------------------ {{{
def _install_current_cask(self): def _install_current_cask(self):
if not self.valid_cask(self.current_cask): if not self.valid_cask(self.current_cask):
@ -470,6 +544,12 @@ class HomebrewCask(object):
self.changed = True self.changed = True
self.message = 'Cask installed: {0}'.format(self.current_cask) self.message = 'Cask installed: {0}'.format(self.current_cask)
return True return True
elif self.accept_external_apps and re.search(r"Error: It seems there is already an App at", err):
self.unchanged_count += 1
self.message = 'Cask already installed: {0}'.format(
self.current_cask,
)
return True
else: else:
self.failed = True self.failed = True
self.message = err.strip() self.message = err.strip()
@ -483,6 +563,58 @@ class HomebrewCask(object):
return True return True
# /installed ----------------------------- }}} # /installed ----------------------------- }}}
# upgraded ------------------------------- {{{
def _upgrade_current_cask(self):
command = 'upgrade'
if not self.valid_cask(self.current_cask):
self.failed = True
self.message = 'Invalid cask: {0}.'.format(self.current_cask)
raise HomebrewCaskException(self.message)
if not self._current_cask_is_installed():
command = 'install'
if self._current_cask_is_installed() and not self._current_cask_is_outdated():
self.message = 'Cask is already upgraded: {0}'.format(
self.current_cask,
)
self.unchanged_count += 1
return True
if self.module.check_mode:
self.changed = True
self.message = 'Cask would be upgraded: {0}'.format(
self.current_cask
)
raise HomebrewCaskException(self.message)
opts = (
[self.brew_path, 'cask', command]
+ self.install_options
+ [self.current_cask]
)
cmd = [opt for opt in opts if opt]
rc, out, err = self.module.run_command(cmd)
if self._current_cask_is_installed() and not self._current_cask_is_outdated():
self.changed_count += 1
self.changed = True
self.message = 'Cask upgraded: {0}'.format(self.current_cask)
return True
else:
self.failed = True
self.message = err.strip()
raise HomebrewCaskException(self.message)
def _upgrade_casks(self):
for cask in self.casks:
self.current_cask = cask
self._upgrade_current_cask()
return True
# /upgraded ------------------------------ }}}
# uninstalled ---------------------------- {{{ # uninstalled ---------------------------- {{{
def _uninstall_current_cask(self): def _uninstall_current_cask(self):
if not self.valid_cask(self.current_cask): if not self.valid_cask(self.current_cask):
@ -526,7 +658,7 @@ class HomebrewCask(object):
self._uninstall_current_cask() self._uninstall_current_cask()
return True return True
# /uninstalled ----------------------------- }}} # /uninstalled --------------------------- }}}
# /commands ---------------------------------------------------- }}} # /commands ---------------------------------------------------- }}}
@ -547,6 +679,7 @@ def main():
default="present", default="present",
choices=[ choices=[
"present", "installed", "present", "installed",
"latest", "upgraded",
"absent", "removed", "uninstalled", "absent", "removed", "uninstalled",
], ],
), ),
@ -559,7 +692,16 @@ def main():
default=None, default=None,
aliases=['options'], aliases=['options'],
type='list', type='list',
) ),
accept_external_apps=dict(
default=False,
type='bool',
),
upgrade_all=dict(
default=False,
aliases=["upgrade"],
type='bool',
),
), ),
supports_check_mode=True, supports_check_mode=True,
) )
@ -580,17 +722,25 @@ def main():
state = p['state'] state = p['state']
if state in ('present', 'installed'): if state in ('present', 'installed'):
state = 'installed' state = 'installed'
if state in ('latest', 'upgraded'):
state = 'upgraded'
if state in ('absent', 'removed', 'uninstalled'): if state in ('absent', 'removed', 'uninstalled'):
state = 'absent' state = 'absent'
update_homebrew = p['update_homebrew'] update_homebrew = p['update_homebrew']
upgrade_all = p['upgrade_all']
p['install_options'] = p['install_options'] or [] p['install_options'] = p['install_options'] or []
install_options = ['--{0}'.format(install_option) install_options = ['--{0}'.format(install_option)
for install_option in p['install_options']] for install_option in p['install_options']]
accept_external_apps = p['accept_external_apps']
brew_cask = HomebrewCask(module=module, path=path, casks=casks, brew_cask = HomebrewCask(module=module, path=path, casks=casks,
state=state, update_homebrew=update_homebrew, state=state, update_homebrew=update_homebrew,
install_options=install_options) install_options=install_options,
accept_external_apps=accept_external_apps,
upgrade_all=upgrade_all,
)
(failed, changed, message) = brew_cask.run() (failed, changed, message) = brew_cask.run()
if failed: if failed:
module.fail_json(msg=message) module.fail_json(msg=message)

Loading…
Cancel
Save