homebrew 5.12 KB
Newer Older
Andrew Dunham committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#!/usr/bin/python
# -*- coding: utf-8 -*-

# (c) 2013, Andrew Dunham <andrew@du.nham.ca>
# Based on macports (Jimmy Tang <jcftang@gmail.com>)
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software.  If not, see <http://www.gnu.org/licenses/>.

DOCUMENTATION = '''
---
module: homebrew
author: Andrew Dunham
short_description: Package manager for Homebrew
description:
    - Manages Homebrew packages
27
version_added: "1.4"
Andrew Dunham committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
options:
    name:
        description:
            - name of package to install/remove
        required: true
    state:
        description:
            - state of the package
        choices: [ 'present', 'absent' ]
        required: false
        default: present
    update_homebrew:
        description:
            - update homebrew itself first
        required: false
        default: "no"
        choices: [ "yes", "no" ]
45 46 47 48
    install_options:
        description:
            - options flags to install a package
        required: false
49
        default: null
Andrew Dunham committed
50 51 52
notes:  []
'''
EXAMPLES = '''
53 54 55 56
- homebrew: name=foo state=present
- homebrew: name=foo state=present update_homebrew=yes
- homebrew: name=foo state=absent
- homebrew: name=foo,bar state=absent
57
- homebrew: name=foo state=present install_options=with-baz,enable-debug
Andrew Dunham committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
'''


def update_homebrew(module, brew_path):
    """ Updates packages list. """

    rc, out, err = module.run_command("%s update" % brew_path)

    if rc != 0:
        module.fail_json(msg="could not update homebrew")


def query_package(module, brew_path, name, state="present"):
    """ Returns whether a package is installed or not. """

    if state == "present":
74
        rc, out, err = module.run_command("%s list %s" % (brew_path, name))
Andrew Dunham committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
        if rc == 0:
            return True

        return False


def remove_packages(module, brew_path, packages):
    """ Uninstalls one or more packages if installed. """

    removed_count = 0

    # Using a for loop incase of error, we can report the package that failed
    for package in packages:
        # Query the package first, to see if we even need to remove.
        if not query_package(module, brew_path, package):
            continue

        if module.check_mode:
            module.exit_json(changed=True)
        rc, out, err = module.run_command([brew_path, 'remove', package])

        if query_package(module, brew_path, package):
            module.fail_json(msg="failed to remove %s: %s" % (package, out.strip()))

        removed_count += 1

    if removed_count > 0:
        module.exit_json(changed=True, msg="removed %d package(s)" % removed_count)

    module.exit_json(changed=False, msg="package(s) already absent")


107
def install_packages(module, brew_path, packages, options):
Andrew Dunham committed
108 109 110 111 112 113 114 115 116 117
    """ Installs one or more packages if not already installed. """

    installed_count = 0

    for package in packages:
        if query_package(module, brew_path, package):
            continue

        if module.check_mode:
            module.exit_json(changed=True)
118

119
        cmd = [brew_path, 'install', package]
120
        if options:
121 122
            cmd.extend(options)
        rc, out, err = module.run_command(cmd)
Andrew Dunham committed
123 124

        if not query_package(module, brew_path, package):
125
            module.fail_json(msg="failed to install %s: '%s' %s" % (package, cmd, out.strip()))
Andrew Dunham committed
126 127 128 129 130 131 132 133

        installed_count += 1

    if installed_count > 0:
        module.exit_json(changed=True, msg="installed %d package(s)" % (installed_count,))

    module.exit_json(changed=False, msg="package(s) already present")

134
def generate_options_string(install_options):
135
    if install_options is None:
136
        return None
137

138
    options = []
139 140

    for option in install_options:
141
        options.append('--%s' % option)
142

143
    return options
144

Andrew Dunham committed
145 146 147 148 149 150

def main():
    module = AnsibleModule(
        argument_spec = dict(
            name = dict(aliases=["pkg"], required=True),
            state = dict(default="present", choices=["present", "installed", "absent", "removed"]),
151
            update_homebrew = dict(default="no", aliases=["update-brew"], type='bool'),
152
            install_options = dict(default=None, aliases=["options"], type='list')
Andrew Dunham committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166
        ),
        supports_check_mode=True
    )

    brew_path = module.get_bin_path('brew', True, ['/usr/local/bin'])

    p = module.params

    if p["update_homebrew"]:
        update_homebrew(module, brew_path)

    pkgs = p["name"].split(",")

    if p["state"] in ["present", "installed"]:
167 168
        opt = generate_options_string(p["install_options"])
        install_packages(module, brew_path, pkgs, opt)
Andrew Dunham committed
169 170 171 172

    elif p["state"] in ["absent", "removed"]:
        remove_packages(module, brew_path, pkgs)

173
# import module snippets
174
from ansible.module_utils.basic import *
Andrew Dunham committed
175 176

main()