-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adding types to sysupgrade documentation * Apply suggestions from code review * Adding installurl flag. Changing wording in example. * Use None for installurl by default * Changing word case in description * sysupgrade: use module structure recommended by Ansible unit test docs * Adding unit test for sysupgrade Signed-off-by: Andrew Klaus <andrew@aklaus.ca> Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com> Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com> Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> Co-authored-by: Felix Fontein <felix@fontein.de>
- Loading branch information
1 parent
0ae3d0a
commit 2aabf5e
Showing
3 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#!/usr/bin/python | ||
|
||
# Copyright: (c) 2020, Andrew Klaus <andrewklaus@gmail.com> | ||
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
system/sysupgrade.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# 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 | ||
|
||
from ansible.module_utils import basic | ||
from ansible_collections.community.general.tests.unit.compat.mock import patch | ||
from ansible_collections.community.general.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase | ||
from ansible_collections.community.general.plugins.modules.system import sysupgrade | ||
|
||
|
||
class TestSysupgradeModule(ModuleTestCase): | ||
|
||
def setUp(self): | ||
super(TestSysupgradeModule, self).setUp() | ||
self.module = sysupgrade | ||
self.mock_get_bin_path = (patch('ansible.module_utils.basic.AnsibleModule.get_bin_path')) | ||
self.get_bin_path = self.mock_get_bin_path.start() | ||
|
||
def tearDown(self): | ||
super(TestSysupgradeModule, self).tearDown() | ||
self.mock_get_bin_path.stop() | ||
|
||
def test_upgrade_success(self): | ||
""" Upgrade was successful """ | ||
|
||
rc = 0 | ||
stdout = """ | ||
SHA256.sig 100% |*************************************| 2141 00:00 | ||
Signature Verified | ||
INSTALL.amd64 100% |************************************| 43512 00:00 | ||
base67.tgz 100% |*************************************| 238 MB 02:16 | ||
bsd 100% |*************************************| 18117 KB 00:24 | ||
bsd.mp 100% |*************************************| 18195 KB 00:17 | ||
bsd.rd 100% |*************************************| 10109 KB 00:14 | ||
comp67.tgz 100% |*************************************| 74451 KB 00:53 | ||
game67.tgz 100% |*************************************| 2745 KB 00:03 | ||
man67.tgz 100% |*************************************| 7464 KB 00:04 | ||
xbase67.tgz 100% |*************************************| 22912 KB 00:30 | ||
xfont67.tgz 100% |*************************************| 39342 KB 00:28 | ||
xserv67.tgz 100% |*************************************| 16767 KB 00:24 | ||
xshare67.tgz 100% |*************************************| 4499 KB 00:06 | ||
Verifying sets. | ||
Fetching updated firmware. | ||
Will upgrade on next reboot | ||
""" | ||
stderr = "" | ||
|
||
with patch.object(basic.AnsibleModule, "run_command") as run_command: | ||
run_command.return_value = (rc, stdout, stderr) | ||
with self.assertRaises(AnsibleExitJson) as result: | ||
self.module.main() | ||
self.assertTrue(result.exception.args[0]['changed']) | ||
|
||
def test_upgrade_failed(self): | ||
""" Upgrade failed """ | ||
|
||
rc = 1 | ||
stdout = "" | ||
stderr = "sysupgrade: need root privileges" | ||
|
||
with patch.object(basic.AnsibleModule, "run_command") as run_command_mock: | ||
run_command_mock.return_value = (rc, stdout, stderr) | ||
with self.assertRaises(AnsibleFailJson) as result: | ||
self.module.main() | ||
self.assertTrue(result.exception.args[0]['failed']) | ||
self.assertIn('need root', result.exception.args[0]['msg']) |