Skip to content

Commit 43a5fb9

Browse files
Add storagebox_subaccount_info module (#162)
* Add `storagebox_subaccount_info` module * typos * ci retrigger * Update plugins/modules/storagebox_subaccount_info.py Co-authored-by: Felix Fontein <[email protected]> --------- Co-authored-by: Felix Fontein <[email protected]>
1 parent 3c63b8a commit 43a5fb9

File tree

4 files changed

+253
-0
lines changed

4 files changed

+253
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ If you use the Ansible package and do not update collections independently, use
7171
- `community.hrobot.storagebox_snapshot_info` module
7272
- `community.hrobot.storagebox_snapshot_plan` module
7373
- `community.hrobot.storagebox_snapshot_plan_info` module
74+
- `community.hrobot.storagebox_subaccount_info` module
7475
- `community.hrobot.v_switch` module
7576
- `community.hrobot.robot` inventory plugin
7677

meta/runtime.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ action_groups:
2525
- storagebox_snapshot_info
2626
- storagebox_snapshot_plan
2727
- storagebox_snapshot_plan_info
28+
- storagebox_subaccount_info
2829
- v_switch
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright (c) 2025 Victor LEFEBVRE <[email protected]>
5+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
6+
# SPDX-License-Identifier: GPL-3.0-or-later
7+
8+
from __future__ import absolute_import, division, print_function
9+
10+
__metaclass__ = type
11+
12+
13+
DOCUMENTATION = r"""
14+
module: storagebox_subaccount_info
15+
short_description: Query the subaccounts for a storage box
16+
version_added: 2.4.0
17+
author:
18+
- Victor LEFEBVRE (@vic1707)
19+
description:
20+
- Query the subaccounts for a storage box.
21+
extends_documentation_fragment:
22+
- community.hrobot.robot
23+
- community.hrobot.attributes
24+
- community.hrobot.attributes.actiongroup_robot
25+
- community.hrobot.attributes.idempotent_not_modify_state
26+
- community.hrobot.attributes.info_module
27+
28+
options:
29+
storagebox_id:
30+
description:
31+
- The ID of the storage box to query.
32+
type: int
33+
required: true
34+
"""
35+
36+
EXAMPLES = r"""
37+
---
38+
- name: Query the subaccounts
39+
community.hrobot.storagebox_subaccount_info:
40+
hetzner_user: foo
41+
hetzner_password: bar
42+
storage_box_id: 123
43+
register: result
44+
45+
- name: Output data
46+
ansible.builtin.debug:
47+
msg: "Username of the first subaccount: {{ result.subaccounts[0].username }}"
48+
"""
49+
50+
RETURN = r"""
51+
subaccounts:
52+
description:
53+
- The storage box's info.
54+
- All date and time parameters are in UTC.
55+
returned: success
56+
type: list
57+
elements: dict
58+
contains:
59+
username:
60+
description:
61+
- Username of the sub-account.
62+
type: str
63+
sample: "u2342-sub1"
64+
returned: success
65+
accountid:
66+
description:
67+
- Username of the main user.
68+
type: str
69+
sample: "u2342"
70+
returned: success
71+
server:
72+
description:
73+
- Server on which the sub-account resides.
74+
type: str
75+
sample: "sb1234.your-storagebox.de"
76+
returned: success
77+
homedirectory:
78+
description:
79+
- Homedirectory of the sub-account.
80+
type: str
81+
sample: "/home/u2342-sub1"
82+
returned: success
83+
samba:
84+
description:
85+
- Status of Samba support.
86+
type: bool
87+
sample: true
88+
returned: success
89+
ssh:
90+
description:
91+
- Status of SSH support.
92+
type: bool
93+
sample: true
94+
returned: success
95+
external_reachability:
96+
description:
97+
- Status of external reachability.
98+
type: bool
99+
sample: false
100+
returned: success
101+
webdav:
102+
description:
103+
- Status of WebDAV support.
104+
type: bool
105+
sample: true
106+
returned: success
107+
readonly:
108+
description:
109+
- Indicates if the sub-account is in readonly mode.
110+
type: bool
111+
sample: false
112+
returned: success
113+
createtime:
114+
description:
115+
- Timestamp when the sub-account was created.
116+
type: str
117+
sample: "2023-08-25T14:23:05Z"
118+
returned: success
119+
comment:
120+
description:
121+
- Custom comment for the sub-account.
122+
type: str
123+
sample: "This is a subaccount"
124+
returned: success
125+
"""
126+
127+
from ansible.module_utils.basic import AnsibleModule
128+
129+
from ansible_collections.community.hrobot.plugins.module_utils.robot import (
130+
BASE_URL,
131+
ROBOT_DEFAULT_ARGUMENT_SPEC,
132+
fetch_url_json,
133+
)
134+
135+
136+
def main():
137+
argument_spec = dict(
138+
storagebox_id=dict(type="int", required=True),
139+
)
140+
argument_spec.update(ROBOT_DEFAULT_ARGUMENT_SPEC)
141+
module = AnsibleModule(
142+
argument_spec=argument_spec,
143+
supports_check_mode=True,
144+
)
145+
146+
storagebox_id = module.params["storagebox_id"]
147+
148+
url = "{0}/storagebox/{1}/subaccount".format(BASE_URL, storagebox_id)
149+
result, error = fetch_url_json(module, url, accept_errors=["STORAGEBOX_NOT_FOUND"])
150+
if error:
151+
module.fail_json(
152+
msg="Storagebox with ID {0} does not exist".format(storagebox_id)
153+
)
154+
155+
module.exit_json(
156+
changed=False,
157+
subaccounts=[item["subaccount"] for item in result],
158+
)
159+
160+
161+
if __name__ == "__main__": # pragma: no cover
162+
main() # pragma: no cover
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Copyright (c) 2025 Victor LEFEBVRE <[email protected]>
2+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
from __future__ import absolute_import, division, print_function
6+
7+
__metaclass__ = type
8+
9+
10+
from ansible_collections.community.internal_test_tools.tests.unit.utils.fetch_url_module_framework import (
11+
FetchUrlCall,
12+
BaseTestModule,
13+
)
14+
15+
from ansible_collections.community.hrobot.plugins.module_utils.robot import BASE_URL
16+
from ansible_collections.community.hrobot.plugins.modules import (
17+
storagebox_subaccount_info,
18+
)
19+
20+
STORAGEBOX_SUBACCOUNTS = [
21+
{
22+
"subaccount": {
23+
"username": "u2342-sub1",
24+
"accountid": "u2342",
25+
"server": "u12345-sub1.your-storagebox.de",
26+
"homedirectory": "test",
27+
"samba": True,
28+
"ssh": True,
29+
"external_reachability": True,
30+
"webdav": False,
31+
"readonly": False,
32+
"createtime": "2017-05-24 00:00:00",
33+
"comment": "Test account",
34+
}
35+
},
36+
{
37+
"subaccount": {
38+
"username": "u2342-sub2",
39+
"accountid": "u2342",
40+
"server": "u12345-sub2.your-storagebox.de",
41+
"homedirectory": "test2",
42+
"samba": False,
43+
"ssh": True,
44+
"external_reachability": True,
45+
"webdav": True,
46+
"readonly": False,
47+
"createtime": "2025-01-24 00:00:00",
48+
"comment": "Test account 2",
49+
}
50+
},
51+
]
52+
53+
54+
class TestHetznerStorageboxSubbacountInfo(BaseTestModule):
55+
MOCK_ANSIBLE_MODULEUTILS_BASIC_ANSIBLEMODULE = 'ansible_collections.community.hrobot.plugins.modules.storagebox_subaccount_info.AnsibleModule'
56+
MOCK_ANSIBLE_MODULEUTILS_URLS_FETCH_URL = 'ansible_collections.community.hrobot.plugins.module_utils.robot.fetch_url'
57+
58+
def test_subaccounts(self, mocker):
59+
result = self.run_module_success(mocker, storagebox_subaccount_info, {
60+
'hetzner_user': 'test',
61+
'hetzner_password': 'hunter2',
62+
'storagebox_id': 23}, [
63+
FetchUrlCall('GET', 200)
64+
.expect_basic_auth('test', 'hunter2')
65+
.expect_force_basic_auth(True)
66+
.result_json(STORAGEBOX_SUBACCOUNTS)
67+
.expect_url(BASE_URL + '/storagebox/23/subaccount')
68+
])
69+
assert result['changed'] is False
70+
assert len(result['subaccounts']) == 2
71+
assert result['subaccounts'][0] == STORAGEBOX_SUBACCOUNTS[0]['subaccount']
72+
73+
def test_storagebox_id_unknown(self, mocker):
74+
result = self.run_module_failed(mocker, storagebox_subaccount_info, {
75+
'hetzner_user': '',
76+
'hetzner_password': '',
77+
'storagebox_id': 23
78+
}, [
79+
FetchUrlCall('GET', 404)
80+
.result_json({
81+
'error': {
82+
'status': 404,
83+
'code': 'STORAGEBOX_NOT_FOUND',
84+
'message': 'Storage Box with ID 23 does not exist',
85+
}
86+
})
87+
.expect_url(BASE_URL + '/storagebox/23/subaccount')
88+
])
89+
assert result['msg'] == 'Storagebox with ID 23 does not exist'

0 commit comments

Comments
 (0)