Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Homebrew 1.0.0 fallout #483

Merged
merged 9 commits into from Sep 27, 2016
Next

Add homebrew_analytics module for robust disabling

Originally, a raw call to the `git.config` state was used to disable
Homebrew Analytics. However, this is fragile and recently broke with the
Homebrew 1.0.0 release, which migrated the Homebrew repository location.
Now that we have support for custom modules, add a `homebrew` execution
module to allow running arbitrary Homebrew commands, and a
`homebrew_analytics` module on top which allows robustly disabling
Homebrew Analytics by using the builtin `brew analytics` command.

The execution module is named `homebrew` because the built-in module
[`mac_brew.py`] is not available (hidden behind the `pkg`
__virtualname__), so its methods cannot be called.
  • Loading branch information
aneeshusa committed Sep 24, 2016
commit ed6fb33f45a6e71c6ec45745c7a5429734da6586
@@ -0,0 +1,89 @@
# This module is mainly comprised of new code, but also contains modified
# versions of functions from the salt/modules/mac_brew.py module from Salt
# develop (at git revision 3e5218daea73f3f24b82a3078764ccb82c2a1ec9).
# Functions taken/modified from Salt are marked, all others are original.
#
# The original copyright and licensing notice for the methods from the
# mac_brew.py module is reproduced below in the double-# comment block:
#
## Salt - Remote execution system
##
## Copyright 2014-2015 SaltStack Team
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.

'''
Module for the management of homebrew
'''
from __future__ import absolute_import

# Import python libs
import logging
import os

# Import salt libs
from salt.exceptions import CommandExecutionError
import salt.utils

# Set up logging
log = logging.getLogger(__name__)


def __virtual__():
'''
Only work if Homebrew is installed
'''
if salt.utils.which('brew'):
return True
return (
False,
'The homebrew execution module could not be loaded: brew not found'
)


def _homebrew_bin():
'''
Returns the full path to the homebrew binary in the PATH.
Taken from mac_brew.py with modifications.
'''
homebrew_dir = __salt__['cmd.run'](
'brew --prefix',
output_loglevel='trace'
)
return os.path.join(homebrew_dir, 'bin', 'brew')


def cmd_all(args):
'''
Calls brew with the specified arguments and as the correct user.
Taken from mac_brew.py with modifications.
args:
Should be a list of arguments to pass to the `brew` binary.
'''
user = __salt__['file.get_user'](_homebrew_bin())
runas = user if user != __opts__['user'] else None
ret = __salt__['cmd.run_all'](
['brew'] + args,
runas=runas,
output_loglevel='trace',
python_shell=False,
redirect_stderr=False,
)
if ret['retcode'] != 0:
raise CommandExecutionError(
'stdout: {stdout}\n'
'stderr: {stderr}\n'
'retcode: {retcode}\n'.format(**ret)
)
return ret
@@ -0,0 +1,126 @@
# This module is mainly comprised of new code, but also contains modified
# versions of functions from the salt/modules/mac_brew.py module from Salt
# develop (at git revision 3e5218daea73f3f24b82a3078764ccb82c2a1ec9).
# Functions taken/modified from Salt are marked, all others are original.
#
# The original copyright and licensing notice for the methods from the
# mac_brew.py module is reproduced below in the double-# comment block:
#
## Salt - Remote execution system
##
## Copyright 2014-2015 SaltStack Team
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.

'''
Module for the management of homebrew
'''
from __future__ import absolute_import

# Import python libs
import logging

# Import salt libs
from salt.exceptions import CommandExecutionError
import salt.utils

# Set up logging
log = logging.getLogger(__name__)


def __virtual__():
'''
Only work if Homebrew is installed
'''
if salt.utils.which('brew'):
return True
return (
False,
'The homebrew_analytics state mod could not be loaded: brew not found'
)


def _check_analytics_status():
out = __salt__['homebrew.cmd_all'](['analytics', 'state'])['stdout']
if len(out) < 1:
raise CommandExecutionError('Failed to parse brew analytics state')
status_line = out.splitlines()[0]
if 'enabled' in status_line:
return True
elif 'disabled' in status_line:
return False
raise CommandExecutionError('Failed to parse brew analytics state')


def managed(name, **kwargs):
'''
Manage Homebrew analytics state (either enabled or disabled).
name
Either 'enabled' or 'disabled'
'''
ret = {
'name': name,
'changes': {},
'result': None,
'comment': '',
}

# Var must be called 'name' due to design of Salt
wanted = None
if name == 'enabled':
wanted = True
elif name == 'disabled':
wanted = False
else:
ret['result'] = False
ret['comment'] = '`name` parameter must be `enabled` or `disabled`'
return ret
wanted_v = name[:-1] # Verb form

try:
current = _check_analytics_status()
if current == wanted:
ret['result'] = True
ret['comment'] = 'Homebrew analytics are already {}'.format(name)
return ret

if __opts__['test']:
ret['comment'] = 'Homebrew analytics need to be {}'.format(name)
return ret

state_arg = 'on' if wanted else 'off'
# Exception bubbles, so we can ignore the return value
__salt__['homebrew.cmd_all'](['analytics', state_arg])

new = _check_analytics_status()
if new == wanted:
ret['changes']['homebrew_analytics'] = {
'old': 'enabled' if current else 'disabled',
'new': name,
}
ret['result'] = True
ret['comment'] = 'Homebrew analytics was {}'.format(name)
return ret
else:
ret['result'] = False
ret['comment'] = 'Failed to {} Homebrew analytics'.format(wanted_v)
return ret

except CommandExecutionError as err:
ret['result'] = False
ret['comment'] = 'Failed to {} Homebrew analytics: {}'.format(
wanted_v,
err
)
return ret
@@ -12,14 +12,6 @@
- mode: 644
- source: salt://{{ tpldir }}/files/profile

# Disable Homebrew Analytics
# TODO: wrap this up into a proper state that uses the `brew analytics` command
# instead of directly changing the git configuration
# (requires either upstreaming this state + updating Salt,
# or Salting the Salt master)
# TODO: also ensure the `homebrew.analyticsuuid` setting is unset
disable-homebrew-analytics:
git.config:
- name: 'homebrew.analyticsdisabled'
- value: 'true'
- repo: /usr/local/Homebrew
homebrew_analytics.managed:
- name: disabled
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.