generated from ansible-collections/collection_template
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add reset_info module. * Increase coverage.
- Loading branch information
1 parent
e974ca8
commit fd2cbbc
Showing
4 changed files
with
270 additions
and
2 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 |
---|---|---|
|
@@ -12,6 +12,7 @@ action_groups: | |
- firewall | ||
- firewall_info | ||
- reset | ||
- reset_info | ||
- reverse_dns | ||
- server | ||
- server_info | ||
|
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
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,141 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright (c) 2019 Felix Fontein <felix@fontein.de> | ||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
from __future__ import absolute_import, division, print_function | ||
__metaclass__ = type | ||
|
||
|
||
DOCUMENTATION = r""" | ||
module: reset_info | ||
short_description: Query information on the resetter of a dedicated server | ||
version_added: 2.2.0 | ||
author: | ||
- Felix Fontein (@felixfontein) | ||
description: | ||
- Query information on the resetter of a dedicated server. | ||
seealso: | ||
- module: community.hrobot.reset | ||
description: Reset dedicated server. | ||
extends_documentation_fragment: | ||
- community.hrobot.robot | ||
- community.hrobot.attributes | ||
- community.hrobot.attributes.actiongroup_robot | ||
- community.hrobot.attributes.idempotent_not_modify_state | ||
- community.hrobot.attributes.info_module | ||
options: | ||
server_number: | ||
description: | ||
- The server number of the server to query its resetter. | ||
type: int | ||
required: true | ||
""" | ||
|
||
EXAMPLES = r""" | ||
- name: Query resetter information for server 1234 | ||
community.hrobot.reset_info: | ||
hetzner_user: foo | ||
hetzner_password: bar | ||
server_number: 1234 | ||
register: result | ||
- name: Show reset methods | ||
ansible.builtin.debug: | ||
msg: "{{ result.reset.type }}" | ||
""" | ||
|
||
RETURN = r""" | ||
reset: | ||
description: | ||
- Information on the server's resetter. | ||
type: dict | ||
returned: success | ||
contains: | ||
server_ip: | ||
description: | ||
- The primary IPv4 address of the server. | ||
type: str | ||
returned: success | ||
sample: 123.123.123.123 | ||
server_ipv6_net: | ||
description: | ||
- The primary IPv6 network of the server. | ||
type: str | ||
returned: success | ||
sample: "2a01:4f8:111:4221::" | ||
server_number: | ||
description: | ||
- The server's ID. | ||
type: int | ||
returned: success | ||
sample: 321 | ||
type: | ||
description: | ||
- The reset types supported by the resetter. | ||
- "Can be used for the O(community.hrobot.reset#module:reset_type) option of the M(community.hrobot.reset) module." | ||
type: list | ||
elements: str | ||
returned: success | ||
sample: [software, hardware, manual] | ||
choices: | ||
- software | ||
- hardware | ||
- power | ||
- manual | ||
operating_status: | ||
description: | ||
- The server's operating status. | ||
type: str | ||
returned: success | ||
sample: not supported | ||
""" | ||
|
||
from ansible.module_utils.basic import AnsibleModule | ||
|
||
from ansible_collections.community.hrobot.plugins.module_utils.robot import ( | ||
BASE_URL, | ||
ROBOT_DEFAULT_ARGUMENT_SPEC, | ||
fetch_url_json, | ||
) | ||
|
||
|
||
def main(): | ||
argument_spec = dict( | ||
server_number=dict(type='int', required=True), | ||
) | ||
argument_spec.update(ROBOT_DEFAULT_ARGUMENT_SPEC) | ||
module = AnsibleModule( | ||
argument_spec=argument_spec, | ||
supports_check_mode=True, | ||
) | ||
|
||
server_number = module.params['server_number'] | ||
|
||
url = "{0}/reset/{1}".format(BASE_URL, server_number) | ||
result, error = fetch_url_json(module, url, accept_errors=['SERVER_NOT_FOUND', 'RESET_NOT_AVAILABLE']) | ||
if error == 'SERVER_NOT_FOUND': | ||
module.fail_json(msg='This server does not exist, or you do not have access rights for it') | ||
if error == 'RESET_NOT_AVAILABLE': | ||
module.fail_json(msg='The server has no reset option available') | ||
|
||
reset = dict(result['reset']) | ||
|
||
reset_types = reset.get('type') | ||
if isinstance(reset_types, list): | ||
translation = { | ||
'sw': 'software', | ||
'hw': 'hardware', | ||
'power': 'power', | ||
'man': 'manual', | ||
} | ||
reset['type'] = [translation.get(elt, elt) for elt in reset_types] | ||
|
||
module.exit_json(reset=reset, changed=True) | ||
|
||
|
||
if __name__ == '__main__': # pragma: no cover | ||
main() # pragma: no cover |
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,122 @@ | ||
# Copyright (c) 2025 Felix Fontein <felix@fontein.de> | ||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
from __future__ import (absolute_import, division, print_function) | ||
__metaclass__ = type | ||
|
||
|
||
from ansible_collections.community.internal_test_tools.tests.unit.utils.fetch_url_module_framework import ( | ||
FetchUrlCall, | ||
BaseTestModule, | ||
) | ||
|
||
from ansible_collections.community.hrobot.plugins.module_utils.robot import BASE_URL | ||
from ansible_collections.community.hrobot.plugins.modules import reset_info | ||
|
||
|
||
class TestHetznerResetInfo(BaseTestModule): | ||
MOCK_ANSIBLE_MODULEUTILS_BASIC_ANSIBLEMODULE = 'ansible_collections.community.hrobot.plugins.modules.reset_info.AnsibleModule' | ||
MOCK_ANSIBLE_MODULEUTILS_URLS_FETCH_URL = 'ansible_collections.community.hrobot.plugins.module_utils.robot.fetch_url' | ||
|
||
def test_valid(self, mocker): | ||
result = self.run_module_success(mocker, reset_info, { | ||
'hetzner_user': 'test', | ||
'hetzner_password': 'hunter2', | ||
'server_number': 23, | ||
}, [ | ||
FetchUrlCall('GET', 200) | ||
.expect_basic_auth('test', 'hunter2') | ||
.expect_force_basic_auth(True) | ||
.result_json({ | ||
'reset': { | ||
'server_ip': '123.123.123.123', | ||
'server_ipv6_net': '2a01:4f8:111:4221::', | ||
'server_number': 23, | ||
'type': [ | ||
'sw', | ||
'hw', | ||
'man', | ||
], | ||
'operating_status': 'not supported', | ||
}, | ||
}) | ||
.expect_url('{0}/reset/23'.format(BASE_URL)), | ||
]) | ||
assert result['changed'] is True | ||
assert result['reset'] == { | ||
'server_ip': '123.123.123.123', | ||
'server_ipv6_net': '2a01:4f8:111:4221::', | ||
'server_number': 23, | ||
'type': [ | ||
'software', | ||
'hardware', | ||
'manual', | ||
], | ||
'operating_status': 'not supported', | ||
} | ||
|
||
def test_valid_no_type(self, mocker): | ||
result = self.run_module_success(mocker, reset_info, { | ||
'hetzner_user': 'test', | ||
'hetzner_password': 'hunter2', | ||
'server_number': 23, | ||
}, [ | ||
FetchUrlCall('GET', 200) | ||
.expect_basic_auth('test', 'hunter2') | ||
.expect_force_basic_auth(True) | ||
.result_json({ | ||
'reset': { | ||
'server_ip': '123.123.123.123', | ||
'server_ipv6_net': '2a01:4f8:111:4221::', | ||
'server_number': 23, | ||
'operating_status': 'not supported', | ||
}, | ||
}) | ||
.expect_url('{0}/reset/23'.format(BASE_URL)), | ||
]) | ||
assert result['changed'] is True | ||
assert result['reset'] == { | ||
'server_ip': '123.123.123.123', | ||
'server_ipv6_net': '2a01:4f8:111:4221::', | ||
'server_number': 23, | ||
'operating_status': 'not supported', | ||
} | ||
|
||
# Errors | ||
|
||
def test_server_not_found(self, mocker): | ||
result = self.run_module_failed(mocker, reset_info, { | ||
'hetzner_user': '', | ||
'hetzner_password': '', | ||
'server_number': 23, | ||
}, [ | ||
FetchUrlCall('GET', 404) | ||
.result_json({ | ||
'error': { | ||
'status': 404, | ||
'code': 'SERVER_NOT_FOUND', | ||
'message': 'Server not found', | ||
}, | ||
}) | ||
.expect_url('{0}/reset/23'.format(BASE_URL)), | ||
]) | ||
assert result['msg'] == 'This server does not exist, or you do not have access rights for it' | ||
|
||
def test_reset_not_available(self, mocker): | ||
result = self.run_module_failed(mocker, reset_info, { | ||
'hetzner_user': '', | ||
'hetzner_password': '', | ||
'server_number': 23, | ||
}, [ | ||
FetchUrlCall('GET', 404) | ||
.result_json({ | ||
'error': { | ||
'status': 404, | ||
'code': 'RESET_NOT_AVAILABLE', | ||
'message': 'The server has no reset option', | ||
}, | ||
}) | ||
.expect_url('{0}/reset/23'.format(BASE_URL)), | ||
]) | ||
assert result['msg'] == 'The server has no reset option available' |