#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright: (c) 2020, Andrew Klaus # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = r''' --- module: sysupgrade short_description: Manage OpenBSD system upgrades version_added: 1.1.0 description: - Manage OpenBSD system upgrades using sysupgrade. options: snapshot: description: - Apply the latest snapshot. - Otherwise release will be applied. default: no type: bool force: description: - Force upgrade (for snapshots only). default: no type: bool keep_files: description: - Keep the files under /home/_sysupgrade. - By default, the files will be deleted after the upgrade. default: no type: bool fetch_only: description: - Fetch and verify files and create /bsd.upgrade but do not reboot. - Set to C(false) if you want sysupgrade to reboot. This will cause Ansible to error, as it expects the module to exit gracefully. See the examples. default: yes type: bool installurl: description: - OpenBSD mirror top-level URL for fetching an upgrade. - By default, the mirror URL is pulled from /etc/installurl. type: str author: - Andrew Klaus (@precurse) ''' EXAMPLES = r''' - name: Upgrade to latest release community.general.sysupgrade: register: sysupgrade - name: Upgrade to latest snapshot community.general.sysupgrade: snapshot: yes installurl: https://cloudflare.cdn.openbsd.org/pub/OpenBSD register: sysupgrade - name: Reboot to apply upgrade if needed ansible.builtin.reboot: when: sysupgrade.changed # Note: Ansible will error when running this way due to how # the reboot is forcefully handled by sysupgrade: - name: Have sysupgrade automatically reboot community.general.sysupgrade: fetch_only: no ignore_errors: yes ''' RETURN = r''' rc: description: The command return code (0 means success). returned: always type: int stdout: description: Sysupgrade standard output. returned: always type: str stderr: description: Sysupgrade standard error. returned: always type: str sample: "sysupgrade: need root privileges" ''' from ansible.module_utils.basic import AnsibleModule def sysupgrade_run(module): sysupgrade_bin = module.get_bin_path('/usr/sbin/sysupgrade', required=True) cmd = [sysupgrade_bin] changed = False warnings = [] # Setup command flags if module.params['snapshot']: run_flag = ['-s'] if module.params['force']: # Force only applies to snapshots run_flag.append('-f') else: # release flag run_flag = ['-r'] if module.params['keep_files']: run_flag.append('-k') if module.params['fetch_only']: run_flag.append('-n') # installurl must be the last argument if module.params['installurl']: run_flag.append(module.params['installurl']) rc, out, err = module.run_command(cmd + run_flag) if rc != 0: module.fail_json(msg="Command %s failed rc=%d, out=%s, err=%s" % (cmd, rc, out, err)) elif out.lower().find('already on latest snapshot') >= 0: changed = False elif out.lower().find('upgrade on next reboot') >= 0: changed = True return dict( changed=changed, rc=rc, stderr=err, stdout=out, warnings=warnings ) def main(): module = AnsibleModule( argument_spec=dict( snapshot=dict(type='bool', default=False), fetch_only=dict(type='bool', default=True), force=dict(type='bool', default=False), keep_files=dict(type='bool', default=False), installurl=dict(type='str'), ), supports_check_mode=False, ) return_dict = sysupgrade_run(module) module.exit_json(**return_dict) if __name__ == '__main__': main()