mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
* proxmox: create a common base
Add a doc_fragment to share the documentation regarding authentication
parameters (api_host, api_user, api_password, api_token_id,
api_token_secret as well as the lone validate_certs).
Add a module_utils to hold common code such as the argument spec (again
related to authentication paramters), a helper function to convert from
Proxmox boolean representation to python and the base class
ProxmoxAnsible.
For now it only handles the connection to Proxmox VE API but more can be
added in the future.
To check if everything is well in place add three new modules:
proxmox_{domain,group,user}_info.
And finaly tests these new modules.
* Apply suggestions from code review
Co-authored-by: Felix Fontein <felix@fontein.de>
* Add tests/integration/targets/proxmox/aliases
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 51a08ea398
)
Co-authored-by: Tristan Le Guern <tleguern@bouledef.eu>
This commit is contained in:
parent
b1d1391be5
commit
d5c24e67e8
11 changed files with 784 additions and 0 deletions
3
changelogs/fragments/1331-proxmox-info-modules.yml
Normal file
3
changelogs/fragments/1331-proxmox-info-modules.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
minor_changes:
|
||||
- proxmox - extract common code and documentation (https://github.com/ansible-collections/community.general/pull/1331).
|
45
plugins/doc_fragments/proxmox.py
Normal file
45
plugins/doc_fragments/proxmox.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
# Common parameters for Proxmox VE modules
|
||||
DOCUMENTATION = r'''
|
||||
options:
|
||||
api_host:
|
||||
description:
|
||||
- Specify the target host of the Proxmox VE cluster.
|
||||
type: str
|
||||
required: true
|
||||
api_user:
|
||||
description:
|
||||
- Specify the user to authenticate with.
|
||||
type: str
|
||||
required: true
|
||||
api_password:
|
||||
description:
|
||||
- Specify the password to authenticate with.
|
||||
- You can use C(PROXMOX_PASSWORD) environment variable.
|
||||
type: str
|
||||
api_token_id:
|
||||
description:
|
||||
- Specify the token ID.
|
||||
type: str
|
||||
version_added: 1.3.0
|
||||
api_token_secret:
|
||||
description:
|
||||
- Specify the token secret.
|
||||
type: str
|
||||
version_added: 1.3.0
|
||||
validate_certs:
|
||||
description:
|
||||
- If C(no), SSL certificates will not be validated.
|
||||
- This should only be used on personally controlled sites using self-signed certificates.
|
||||
type: bool
|
||||
default: no
|
||||
requirements: [ "proxmoxer", "requests" ]
|
||||
'''
|
86
plugins/module_utils/proxmox.py
Normal file
86
plugins/module_utils/proxmox.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright: (c) 2020, Tristan Le Guern <tleguern at bouledef.eu>
|
||||
# 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
|
||||
|
||||
import atexit
|
||||
import time
|
||||
import re
|
||||
import traceback
|
||||
|
||||
PROXMOXER_IMP_ERR = None
|
||||
try:
|
||||
from proxmoxer import ProxmoxAPI
|
||||
HAS_PROXMOXER = True
|
||||
except ImportError:
|
||||
HAS_PROXMOXER = False
|
||||
PROXMOXER_IMP_ERR = traceback.format_exc()
|
||||
|
||||
|
||||
from ansible.module_utils.basic import env_fallback, missing_required_lib
|
||||
|
||||
|
||||
def proxmox_auth_argument_spec():
|
||||
return dict(
|
||||
api_host=dict(type='str',
|
||||
required=True,
|
||||
fallback=(env_fallback, ['PROXMOX_HOST'])
|
||||
),
|
||||
api_user=dict(type='str',
|
||||
required=True,
|
||||
fallback=(env_fallback, ['PROXMOX_USER'])
|
||||
),
|
||||
api_password=dict(type='str',
|
||||
no_log=True,
|
||||
fallback=(env_fallback, ['PROXMOX_PASSWORD'])
|
||||
),
|
||||
api_token_id=dict(type='str',
|
||||
no_log=False
|
||||
),
|
||||
api_token_secret=dict(type='str',
|
||||
no_log=True
|
||||
),
|
||||
validate_certs=dict(type='bool',
|
||||
default=False
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def proxmox_to_ansible_bool(value):
|
||||
'''Convert Proxmox representation of a boolean to be ansible-friendly'''
|
||||
return True if value == 1 else False
|
||||
|
||||
|
||||
class ProxmoxAnsible(object):
|
||||
"""Base class for Proxmox modules"""
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
self.proxmox_api = self._connect()
|
||||
# Test token validity
|
||||
try:
|
||||
self.proxmox_api.version.get()
|
||||
except Exception as e:
|
||||
module.fail_json(msg='%s' % e, exception=traceback.format_exc())
|
||||
|
||||
def _connect(self):
|
||||
api_host = self.module.params['api_host']
|
||||
api_user = self.module.params['api_user']
|
||||
api_password = self.module.params['api_password']
|
||||
api_token_id = self.module.params['api_token_id']
|
||||
api_token_secret = self.module.params['api_token_secret']
|
||||
validate_certs = self.module.params['validate_certs']
|
||||
|
||||
auth_args = {'user': api_user}
|
||||
if api_password:
|
||||
auth_args['password'] = api_password
|
||||
else:
|
||||
auth_args['token_name'] = api_token_id
|
||||
auth_args['token_value'] = api_token_secret
|
||||
|
||||
try:
|
||||
return ProxmoxAPI(api_host, verify_ssl=validate_certs, **auth_args)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='%s' % e, exception=traceback.format_exc())
|
133
plugins/modules/cloud/misc/proxmox_domain_info.py
Normal file
133
plugins/modules/cloud/misc/proxmox_domain_info.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright: Tristan Le Guern (@Aversiste) <tleguern at bouledef.eu>
|
||||
# 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 = '''
|
||||
---
|
||||
module: proxmox_domain_info
|
||||
short_description: Retrieve information about one or more Proxmox VE domains
|
||||
version_added: 1.3.0
|
||||
description:
|
||||
- Retrieve information about one or more Proxmox VE domains.
|
||||
options:
|
||||
domain:
|
||||
description:
|
||||
- Restrict results to a specific authentication realm.
|
||||
aliases: ['realm', 'name']
|
||||
type: str
|
||||
author: Tristan Le Guern (@Aversiste)
|
||||
extends_documentation_fragment: community.general.proxmox.documentation
|
||||
'''
|
||||
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: List existing domains
|
||||
community.general.proxmox_domain_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
register: proxmox_domains
|
||||
|
||||
- name: Retrieve information about the pve domain
|
||||
community.general.proxmox_domain_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
domain: pve
|
||||
register: proxmox_domain_pve
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
proxmox_domains:
|
||||
description: List of authentication domains.
|
||||
returned: always, but can be empty
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
comment:
|
||||
description: Short description of the realm.
|
||||
returned: on success
|
||||
type: str
|
||||
realm:
|
||||
description: Realm name.
|
||||
returned: on success
|
||||
type: str
|
||||
type:
|
||||
description: Realm type.
|
||||
returned: on success
|
||||
type: str
|
||||
digest:
|
||||
description: Realm hash.
|
||||
returned: on success, can be absent
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.community.general.plugins.module_utils.proxmox import (
|
||||
proxmox_auth_argument_spec, ProxmoxAnsible, HAS_PROXMOXER, PROXMOXER_IMP_ERR)
|
||||
|
||||
|
||||
class ProxmoxDomainInfoAnsible(ProxmoxAnsible):
|
||||
def get_domain(self, realm):
|
||||
try:
|
||||
domain = self.proxmox_api.access.domains.get(realm)
|
||||
except Exception:
|
||||
self.module.fail_json(msg="Domain '%s' does not exist" % realm)
|
||||
domain['realm'] = realm
|
||||
return domain
|
||||
|
||||
def get_domains(self):
|
||||
domains = self.proxmox_api.access.domains.get()
|
||||
return domains
|
||||
|
||||
|
||||
def proxmox_domain_info_argument_spec():
|
||||
return dict(
|
||||
domain=dict(type='str', aliases=['realm', 'name']),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module_args = proxmox_auth_argument_spec()
|
||||
domain_info_args = proxmox_domain_info_argument_spec()
|
||||
module_args.update(domain_info_args)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=module_args,
|
||||
required_one_of=[('api_password', 'api_token_id')],
|
||||
required_together=[('api_token_id', 'api_token_secret')],
|
||||
supports_check_mode=True
|
||||
)
|
||||
result = dict(
|
||||
changed=False
|
||||
)
|
||||
|
||||
if not HAS_PROXMOXER:
|
||||
module.fail_json(msg=missing_required_lib('proxmoxer'), exception=PROXMOXER_IMP_ERR)
|
||||
|
||||
proxmox = ProxmoxDomainInfoAnsible(module)
|
||||
domain = module.params['domain']
|
||||
|
||||
if domain:
|
||||
domains = [proxmox.get_domain(realm=domain)]
|
||||
else:
|
||||
domains = proxmox.get_domains()
|
||||
result['proxmox_domains'] = domains
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
143
plugins/modules/cloud/misc/proxmox_group_info.py
Normal file
143
plugins/modules/cloud/misc/proxmox_group_info.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright: Tristan Le Guern <tleguern at bouledef.eu>
|
||||
# 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 = '''
|
||||
---
|
||||
module: proxmox_group_info
|
||||
short_description: Retrieve information about one or more Proxmox VE groups
|
||||
version_added: 1.3.0
|
||||
description:
|
||||
- Retrieve information about one or more Proxmox VE groups
|
||||
options:
|
||||
group:
|
||||
description:
|
||||
- Restrict results to a specific group.
|
||||
aliases: ['groupid', 'name']
|
||||
type: str
|
||||
author: Tristan Le Guern (@Aversiste)
|
||||
extends_documentation_fragment: community.general.proxmox.documentation
|
||||
'''
|
||||
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: List existing groups
|
||||
community.general.proxmox_group_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
register: proxmox_groups
|
||||
|
||||
- name: Retrieve information about the admin group
|
||||
community.general.proxmox_group_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
group: admin
|
||||
register: proxmox_group_admin
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
proxmox_groups:
|
||||
description: List of groups.
|
||||
returned: always, but can be empty
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
comment:
|
||||
description: Short description of the group.
|
||||
returned: on success, can be absent
|
||||
type: str
|
||||
groupid:
|
||||
description: Group name.
|
||||
returned: on success
|
||||
type: str
|
||||
users:
|
||||
description: List of users in the group.
|
||||
returned: on success
|
||||
type: list
|
||||
elements: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.community.general.plugins.module_utils.proxmox import (
|
||||
proxmox_auth_argument_spec, ProxmoxAnsible, HAS_PROXMOXER, PROXMOXER_IMP_ERR)
|
||||
|
||||
|
||||
class ProxmoxGroupInfoAnsible(ProxmoxAnsible):
|
||||
def get_group(self, groupid):
|
||||
try:
|
||||
group = self.proxmox_api.access.groups.get(groupid)
|
||||
except Exception:
|
||||
self.module.fail_json(msg="Group '%s' does not exist" % groupid)
|
||||
group['groupid'] = groupid
|
||||
return ProxmoxGroup(group)
|
||||
|
||||
def get_groups(self):
|
||||
groups = self.proxmox_api.access.groups.get()
|
||||
return [ProxmoxGroup(group) for group in groups]
|
||||
|
||||
|
||||
class ProxmoxGroup:
|
||||
def __init__(self, group):
|
||||
self.group = dict()
|
||||
# Data representation is not the same depending on API calls
|
||||
for k, v in group.items():
|
||||
if k == 'users' and type(v) == str:
|
||||
self.group['users'] = v.split(',')
|
||||
elif k == 'members':
|
||||
self.group['users'] = group['members']
|
||||
else:
|
||||
self.group[k] = v
|
||||
|
||||
|
||||
def proxmox_group_info_argument_spec():
|
||||
return dict(
|
||||
group=dict(type='str', aliases=['groupid', 'name']),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module_args = proxmox_auth_argument_spec()
|
||||
group_info_args = proxmox_group_info_argument_spec()
|
||||
module_args.update(group_info_args)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=module_args,
|
||||
required_one_of=[('api_password', 'api_token_id')],
|
||||
required_together=[('api_token_id', 'api_token_secret')],
|
||||
supports_check_mode=True
|
||||
)
|
||||
result = dict(
|
||||
changed=False
|
||||
)
|
||||
|
||||
if not HAS_PROXMOXER:
|
||||
module.fail_json(msg=missing_required_lib('proxmoxer'), exception=PROXMOXER_IMP_ERR)
|
||||
|
||||
proxmox = ProxmoxGroupInfoAnsible(module)
|
||||
group = module.params['group']
|
||||
|
||||
if group:
|
||||
groups = [proxmox.get_group(group=group)]
|
||||
else:
|
||||
groups = proxmox.get_groups()
|
||||
result['proxmox_groups'] = [group.group for group in groups]
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
256
plugins/modules/cloud/misc/proxmox_user_info.py
Normal file
256
plugins/modules/cloud/misc/proxmox_user_info.py
Normal file
|
@ -0,0 +1,256 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright: Tristan Le Guern <tleguern at bouledef.eu>
|
||||
# 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 = '''
|
||||
---
|
||||
module: proxmox_user_info
|
||||
short_description: Retrieve information about one or more Proxmox VE users
|
||||
version_added: 1.3.0
|
||||
description:
|
||||
- Retrieve information about one or more Proxmox VE users
|
||||
options:
|
||||
domain:
|
||||
description:
|
||||
- Restrict results to a specific authentication realm.
|
||||
aliases: ['realm']
|
||||
type: str
|
||||
user:
|
||||
description:
|
||||
- Restrict results to a specific user.
|
||||
aliases: ['name']
|
||||
type: str
|
||||
userid:
|
||||
description:
|
||||
- Restrict results to a specific user ID, which is a concatenation of a user and domain parts.
|
||||
type: str
|
||||
author: Tristan Le Guern (@Aversiste)
|
||||
extends_documentation_fragment: community.general.proxmox.documentation
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: List existing users
|
||||
community.general.proxmox_user_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
register: proxmox_users
|
||||
|
||||
- name: List existing users in the pve authentication realm
|
||||
community.general.proxmox_user_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
domain: pve
|
||||
register: proxmox_users_pve
|
||||
|
||||
- name: Retrieve information about admin@pve
|
||||
community.general.proxmox_user_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
userid: admin@pve
|
||||
register: proxmox_user_admin
|
||||
|
||||
- name: Alternative way to retrieve information about admin@pve
|
||||
community.general.proxmox_user_info:
|
||||
api_host: helldorado
|
||||
api_user: root@pam
|
||||
api_password: "{{ password | default(omit) }}"
|
||||
api_token_id: "{{ token_id | default(omit) }}"
|
||||
api_token_secret: "{{ token_secret | default(omit) }}"
|
||||
user: admin
|
||||
domain: pve
|
||||
register: proxmox_user_admin
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
proxmox_users:
|
||||
description: List of users.
|
||||
returned: always, but can be empty
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
comment:
|
||||
description: Short description of the user.
|
||||
returned: on success
|
||||
type: str
|
||||
domain:
|
||||
description: User's authentication realm, also the right part of the user ID.
|
||||
returned: on success
|
||||
type: str
|
||||
email:
|
||||
description: User's email address.
|
||||
returned: on success
|
||||
type: str
|
||||
enabled:
|
||||
description: User's account state.
|
||||
returned: on success
|
||||
type: bool
|
||||
expire:
|
||||
description: Expiration date in seconds since EPOCH. Zero means no expiration.
|
||||
returned: on success
|
||||
type: int
|
||||
firstname:
|
||||
description: User's first name.
|
||||
returned: on success
|
||||
type: str
|
||||
groups:
|
||||
description: List of groups which the user is a member of.
|
||||
returned: on success
|
||||
type: list
|
||||
elements: str
|
||||
keys:
|
||||
description: User's two factor authentication keys.
|
||||
returned: on success
|
||||
type: str
|
||||
lastname:
|
||||
description: User's last name.
|
||||
returned: on success
|
||||
type: str
|
||||
tokens:
|
||||
description: List of API tokens associated to the user.
|
||||
returned: on success
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
comment:
|
||||
description: Short description of the token.
|
||||
returned: on success
|
||||
type: str
|
||||
expire:
|
||||
description: Expiration date in seconds since EPOCH. Zero means no expiration.
|
||||
returned: on success
|
||||
type: int
|
||||
privsep:
|
||||
description: Describe if the API token is further restricted with ACLs or is fully privileged.
|
||||
returned: on success
|
||||
type: bool
|
||||
tokenid:
|
||||
description: Token name.
|
||||
returned: on success
|
||||
type: str
|
||||
user:
|
||||
description: User's login name, also the left part of the user ID.
|
||||
returned: on success
|
||||
type: str
|
||||
userid:
|
||||
description: Proxmox user ID, represented as user@realm.
|
||||
returned: on success
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.community.general.plugins.module_utils.proxmox import (
|
||||
proxmox_auth_argument_spec, ProxmoxAnsible, proxmox_to_ansible_bool, HAS_PROXMOXER, PROXMOXER_IMP_ERR)
|
||||
|
||||
|
||||
class ProxmoxUserInfoAnsible(ProxmoxAnsible):
|
||||
def get_user(self, userid):
|
||||
try:
|
||||
user = self.proxmox_api.access.users.get(userid)
|
||||
except Exception:
|
||||
self.module.fail_json(msg="User '%s' does not exist" % userid)
|
||||
user['userid'] = userid
|
||||
return ProxmoxUser(user)
|
||||
|
||||
def get_users(self, domain=None):
|
||||
users = self.proxmox_api.access.users.get(full=1)
|
||||
users = [ProxmoxUser(user) for user in users]
|
||||
if domain:
|
||||
return [user for user in users if user.user['domain'] == domain]
|
||||
return users
|
||||
|
||||
|
||||
class ProxmoxUser:
|
||||
def __init__(self, user):
|
||||
self.user = dict()
|
||||
# Data representation is not the same depending on API calls
|
||||
for k, v in user.items():
|
||||
if k == 'enable':
|
||||
self.user['enabled'] = proxmox_to_ansible_bool(user['enable'])
|
||||
elif k == 'userid':
|
||||
self.user['user'] = user['userid'].split('@')[0]
|
||||
self.user['domain'] = user['userid'].split('@')[1]
|
||||
self.user[k] = v
|
||||
elif k in ['groups', 'tokens'] and (v == '' or v is None):
|
||||
self.user[k] = []
|
||||
elif k == 'groups' and type(v) == str:
|
||||
self.user['groups'] = v.split(',')
|
||||
elif k == 'tokens' and type(v) == list:
|
||||
for token in v:
|
||||
if 'privsep' in token:
|
||||
token['privsep'] = proxmox_to_ansible_bool(token['privsep'])
|
||||
self.user['tokens'] = v
|
||||
elif k == 'tokens' and type(v) == dict:
|
||||
self.user['tokens'] = list()
|
||||
for tokenid, tokenvalues in v.items():
|
||||
t = tokenvalues
|
||||
t['tokenid'] = tokenid
|
||||
if 'privsep' in tokenvalues:
|
||||
t['privsep'] = proxmox_to_ansible_bool(tokenvalues['privsep'])
|
||||
self.user['tokens'].append(t)
|
||||
else:
|
||||
self.user[k] = v
|
||||
|
||||
|
||||
def proxmox_user_info_argument_spec():
|
||||
return dict(
|
||||
domain=dict(type='str', aliases=['realm']),
|
||||
user=dict(type='str', aliases=['name']),
|
||||
userid=dict(type='str'),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module_args = proxmox_auth_argument_spec()
|
||||
user_info_args = proxmox_user_info_argument_spec()
|
||||
module_args.update(user_info_args)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=module_args,
|
||||
required_one_of=[('api_password', 'api_token_id')],
|
||||
required_together=[('api_token_id', 'api_token_secret')],
|
||||
mutually_exclusive=[('user', 'userid'), ('domain', 'userid')],
|
||||
supports_check_mode=True
|
||||
)
|
||||
result = dict(
|
||||
changed=False
|
||||
)
|
||||
|
||||
if not HAS_PROXMOXER:
|
||||
module.fail_json(msg=missing_required_lib('proxmoxer'), exception=PROXMOXER_IMP_ERR)
|
||||
|
||||
proxmox = ProxmoxUserInfoAnsible(module)
|
||||
domain = module.params['domain']
|
||||
user = module.params['user']
|
||||
if user and domain:
|
||||
userid = user + '@' + domain
|
||||
else:
|
||||
userid = module.params['userid']
|
||||
|
||||
if userid:
|
||||
users = [proxmox.get_user(userid=userid)]
|
||||
else:
|
||||
users = proxmox.get_users(domain=domain)
|
||||
result['proxmox_users'] = [user.user for user in users]
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
1
plugins/modules/proxmox_domain_info.py
Symbolic link
1
plugins/modules/proxmox_domain_info.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
cloud/misc/proxmox_domain_info.py
|
1
plugins/modules/proxmox_group_info.py
Symbolic link
1
plugins/modules/proxmox_group_info.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
cloud/misc/proxmox_group_info.py
|
1
plugins/modules/proxmox_user_info.py
Symbolic link
1
plugins/modules/proxmox_user_info.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
cloud/misc/proxmox_user_info.py
|
4
tests/integration/targets/proxmox/aliases
Normal file
4
tests/integration/targets/proxmox/aliases
Normal file
|
@ -0,0 +1,4 @@
|
|||
unsupported
|
||||
proxmox_domain_info
|
||||
proxmox_group_info
|
||||
proxmox_user_info
|
111
tests/integration/targets/proxmox/tasks/main.yml
Normal file
111
tests/integration/targets/proxmox/tasks/main.yml
Normal file
|
@ -0,0 +1,111 @@
|
|||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Copyright: (c) 2020, Tristan Le Guern <tleguern at bouledef.eu>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
- name: List domains
|
||||
proxmox_domain_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results is not changed
|
||||
- results.proxmox_domains is defined
|
||||
|
||||
- name: Retrieve info about pve
|
||||
proxmox_domain_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
domain: pve
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results is not changed
|
||||
- results.proxmox_domains is defined
|
||||
- results.proxmox_domains|length == 1
|
||||
- results.proxmox_domains[0].type == 'pve'
|
||||
|
||||
- name: List groups
|
||||
proxmox_group_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results is not changed
|
||||
- results.proxmox_groups is defined
|
||||
|
||||
- name: List users
|
||||
proxmox_user_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
register: results
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results is not changed
|
||||
- results.proxmox_users is defined
|
||||
|
||||
- name: Retrieve info about api_user using name and domain
|
||||
proxmox_user_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
user: "{{ user }}"
|
||||
domain: "{{ domain }}"
|
||||
register: results_user_domain
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results_user_domain is not changed
|
||||
- results_user_domain.proxmox_users is defined
|
||||
- results_user_domain.proxmox_users|length == 1
|
||||
- results_user_domain.proxmox_users[0].domain == "{{ domain }}"
|
||||
- results_user_domain.proxmox_users[0].user == "{{ user }}"
|
||||
- results_user_domain.proxmox_users[0].userid == "{{ user }}@{{ domain }}"
|
||||
|
||||
- name: Retrieve info about api_user using userid
|
||||
proxmox_user_info:
|
||||
api_host: "{{ api_host }}"
|
||||
api_user: "{{ user }}@{{ domain }}"
|
||||
api_password: "{{ api_password | default(omit) }}"
|
||||
api_token_id: "{{ api_token_id | default(omit) }}"
|
||||
api_token_secret: "{{ api_token_secret | default(omit) }}"
|
||||
validate_certs: "{{ validate_certs }}"
|
||||
userid: "{{ user }}@{{ domain }}"
|
||||
register: results_userid
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- results_userid is not changed
|
||||
- results_userid.proxmox_users is defined
|
||||
- results_userid.proxmox_users|length == 1
|
||||
- results_userid.proxmox_users[0].domain == "{{ domain }}"
|
||||
- results_userid.proxmox_users[0].user == "{{ user }}"
|
||||
- results_userid.proxmox_users[0].userid == "{{ user }}@{{ domain }}"
|
Loading…
Reference in a new issue