1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 4# (c) 2013, Raul Melo 5# Written by Raul Melo <raulmelo@gmail.com> 6# Based on yum module written by Seth Vidal <skvidal at fedoraproject.org> 7# 8# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 9 10from __future__ import absolute_import, division, print_function 11__metaclass__ = type 12 13 14DOCUMENTATION = ''' 15--- 16module: swdepot 17short_description: Manage packages with swdepot package manager (HP-UX) 18description: 19 - Will install, upgrade and remove packages with swdepot package manager (HP-UX) 20notes: [] 21author: "Raul Melo (@melodous)" 22options: 23 name: 24 description: 25 - package name. 26 aliases: [pkg] 27 required: true 28 type: str 29 state: 30 description: 31 - whether to install (C(present), C(latest)), or remove (C(absent)) a package. 32 required: true 33 choices: [ 'present', 'latest', 'absent'] 34 type: str 35 depot: 36 description: 37 - The source repository from which install or upgrade a package. 38 type: str 39''' 40 41EXAMPLES = ''' 42- name: Install a package 43 community.general.swdepot: 44 name: unzip-6.0 45 state: present 46 depot: 'repository:/path' 47 48- name: Install the latest version of a package 49 community.general.swdepot: 50 name: unzip 51 state: latest 52 depot: 'repository:/path' 53 54- name: Remove a package 55 community.general.swdepot: 56 name: unzip 57 state: absent 58''' 59 60import re 61 62from ansible.module_utils.basic import AnsibleModule 63from ansible.module_utils.six.moves import shlex_quote 64 65 66def compare_package(version1, version2): 67 """ Compare version packages. 68 Return values: 69 -1 first minor 70 0 equal 71 1 first greater """ 72 73 def normalize(v): 74 return [int(x) for x in re.sub(r'(\.0+)*$', '', v).split(".")] 75 normalized_version1 = normalize(version1) 76 normalized_version2 = normalize(version2) 77 if normalized_version1 == normalized_version2: 78 rc = 0 79 elif normalized_version1 < normalized_version2: 80 rc = -1 81 else: 82 rc = 1 83 return rc 84 85 86def query_package(module, name, depot=None): 87 """ Returns whether a package is installed or not and version. """ 88 89 cmd_list = '/usr/sbin/swlist -a revision -l product' 90 if depot: 91 rc, stdout, stderr = module.run_command("%s -s %s %s | grep %s" % (cmd_list, shlex_quote(depot), shlex_quote(name), shlex_quote(name)), 92 use_unsafe_shell=True) 93 else: 94 rc, stdout, stderr = module.run_command("%s %s | grep %s" % (cmd_list, shlex_quote(name), shlex_quote(name)), use_unsafe_shell=True) 95 if rc == 0: 96 version = re.sub(r"\s\s+|\t", " ", stdout).strip().split()[1] 97 else: 98 version = None 99 100 return rc, version 101 102 103def remove_package(module, name): 104 """ Uninstall package if installed. """ 105 106 cmd_remove = '/usr/sbin/swremove' 107 rc, stdout, stderr = module.run_command("%s %s" % (cmd_remove, name)) 108 109 if rc == 0: 110 return rc, stdout 111 else: 112 return rc, stderr 113 114 115def install_package(module, depot, name): 116 """ Install package if not already installed """ 117 118 cmd_install = '/usr/sbin/swinstall -x mount_all_filesystems=false' 119 rc, stdout, stderr = module.run_command("%s -s %s %s" % (cmd_install, depot, name)) 120 if rc == 0: 121 return rc, stdout 122 else: 123 return rc, stderr 124 125 126def main(): 127 module = AnsibleModule( 128 argument_spec=dict( 129 name=dict(aliases=['pkg'], required=True), 130 state=dict(choices=['present', 'absent', 'latest'], required=True), 131 depot=dict(default=None, required=False) 132 ), 133 supports_check_mode=True 134 ) 135 name = module.params['name'] 136 state = module.params['state'] 137 depot = module.params['depot'] 138 139 changed = False 140 msg = "No changed" 141 rc = 0 142 if (state == 'present' or state == 'latest') and depot is None: 143 output = "depot parameter is mandatory in present or latest task" 144 module.fail_json(name=name, msg=output, rc=rc) 145 146 # Check local version 147 rc, version_installed = query_package(module, name) 148 if not rc: 149 installed = True 150 msg = "Already installed" 151 152 else: 153 installed = False 154 155 if (state == 'present' or state == 'latest') and installed is False: 156 if module.check_mode: 157 module.exit_json(changed=True) 158 rc, output = install_package(module, depot, name) 159 160 if not rc: 161 changed = True 162 msg = "Package installed" 163 164 else: 165 module.fail_json(name=name, msg=output, rc=rc) 166 167 elif state == 'latest' and installed is True: 168 # Check depot version 169 rc, version_depot = query_package(module, name, depot) 170 171 if not rc: 172 if compare_package(version_installed, version_depot) == -1: 173 if module.check_mode: 174 module.exit_json(changed=True) 175 # Install new version 176 rc, output = install_package(module, depot, name) 177 178 if not rc: 179 msg = "Package upgraded, Before " + version_installed + " Now " + version_depot 180 changed = True 181 182 else: 183 module.fail_json(name=name, msg=output, rc=rc) 184 185 else: 186 output = "Software package not in repository " + depot 187 module.fail_json(name=name, msg=output, rc=rc) 188 189 elif state == 'absent' and installed is True: 190 if module.check_mode: 191 module.exit_json(changed=True) 192 rc, output = remove_package(module, name) 193 if not rc: 194 changed = True 195 msg = "Package removed" 196 else: 197 module.fail_json(name=name, msg=output, rc=rc) 198 199 if module.check_mode: 200 module.exit_json(changed=False) 201 202 module.exit_json(changed=changed, name=name, state=state, msg=msg) 203 204 205if __name__ == '__main__': 206 main() 207