#!/usr/bin/python -tt # -*- coding: utf-8 -*- # (c) 2013, Patrick Callahan <pmc@patrickcallahan.com> # based on # openbsd_pkg # (c) 2013 # Patrik Lundin <patrik.lundin.swe@gmail.com> # # yum # (c) 2012, Red Hat, Inc # Written by Seth Vidal <skvidal at fedoraproject.org> # # This file is part of Ansible # # Ansible 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. # # Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. import re DOCUMENTATION = ''' --- module: zypper author: Patrick Callahan version_added: "1.2" short_description: Manage packages on SuSE and openSuSE description: - Manage packages on SuSE and openSuSE using the zypper and rpm tools. options: name: description: - package name or package specifier wth version C(name) or C(name-1.0). required: true aliases: [ 'pkg' ] state: description: - C(present) will make sure the package is installed. C(latest) will make sure the latest version of the package is installed. C(absent) will make sure the specified package is not installed. required: false choices: [ present, latest, absent ] default: "present" disable_gpg_check: description: - Whether to disable to GPG signature checking of the package signature being installed. Has an effect only if state is I(present) or I(latest). required: false default: "no" choices: [ "yes", "no" ] aliases: [] notes: [] # informational: requirements for nodes requirements: [ zypper, rpm ] author: Patrick Callahan ''' EXAMPLES = ''' # Install "nmap" - zypper: name=nmap state=present # Remove the "nmap" package - zypper: name=nmap state=absent ''' # Function used for getting the name of a currently installed package. def get_current_name(m, name): cmd = '/bin/rpm -q --qf \'%{NAME}-%{VERSION}\'' (rc, stdout, stderr) = m.run_command("%s %s" % (cmd, name)) if rc != 0: return (rc, stdout, stderr) syntax = "%s" for line in stdout.splitlines(): if syntax % name in line: current_name = line.split()[0] return current_name # Function used to find out if a package is currently installed. def get_package_state(m, name): cmd = ['/bin/rpm', '--query', '--info', name] rc, stdout, stderr = m.run_command(cmd, check_rc=False) if rc == 0: return True else: return False # Function used to make sure a package is present. def package_present(m, name, installed_state, disable_gpg_check): if installed_state is False: cmd = ['/usr/bin/zypper', '--non-interactive'] # add global options before zypper command if disable_gpg_check: cmd.append('--no-gpg-check') cmd.extend(['install', '--auto-agree-with-licenses']) cmd.append(name) rc, stdout, stderr = m.run_command(cmd, check_rc=False) if rc == 0: changed=True else: changed=False else: rc = 0 stdout = '' stderr = '' changed=False return (rc, stdout, stderr, changed) # Function used to make sure a package is the latest available version. def package_latest(m, name, installed_state, disable_gpg_check): if installed_state is True: cmd = ['/usr/bin/zypper', '--non-interactive', 'update', '--auto-agree-with-licenses', name] pre_upgrade_name = '' post_upgrade_name = '' # Compare the installed package before and after to know if we changed anything. pre_upgrade_name = get_current_name(m, name) rc, stdout, stderr = m.run_command(cmd, check_rc=False) post_upgrade_name = get_current_name(m, name) if pre_upgrade_name == post_upgrade_name: changed = False else: changed = True return (rc, stdout, stderr, changed) else: # If package was not installed at all just make it present. return package_present(m, name, installed_state, disable_gpg_check) # Function used to make sure a package is not installed. def package_absent(m, name, installed_state): if installed_state is True: cmd = ['/usr/bin/zypper', '--non-interactive', 'remove', name] rc, stdout, stderr = m.run_command(cmd) if rc == 0: changed=True else: changed=False else: rc = 0 stdout = '' stderr = '' changed=False return (rc, stdout, stderr, changed) # =========================================== # Main control flow def main(): module = AnsibleModule( argument_spec = dict( name = dict(required=True, aliases=['pkg']), state = dict(required=False, default='present', choices=['absent', 'installed', 'latest', 'present', 'removed']), disable_gpg_check = dict(required=False, default='no', type='bool'), ), supports_check_mode = False ) params = module.params name = params['name'] state = params['state'] disable_gpg_check = params['disable_gpg_check'] rc = 0 stdout = '' stderr = '' result = {} result['name'] = name result['state'] = state # Get package state installed_state = get_package_state(module, name) # Perform requested action if state in ['installed', 'present']: (rc, stdout, stderr, changed) = package_present(module, name, installed_state, disable_gpg_check) elif state in ['absent', 'removed']: (rc, stdout, stderr, changed) = package_absent(module, name, installed_state) elif state == 'latest': (rc, stdout, stderr, changed) = package_latest(module, name, installed_state, disable_gpg_check) if rc != 0: if stderr: module.fail_json(msg=stderr) else: module.fail_json(msg=stdout) result['changed'] = changed module.exit_json(**result) # import module snippets from ansible.module_utils.basic import * main()