Jakob Meng 1b38b7c500 Properly documented openstacksdk version requirements
With "extends_documentation_fragment: ['openstack.cloud.openstack']"
it is not necessary to list required Python libraries in section
'requirements' of DOCUMENTATION docstring in modules. Ansible will
merge requirements from doc fragments and DOCUMENTATION docstring
which previously resulted in duplicates such as in server module [0]:

* openstacksdk
* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

When removing the 'requirements' section from server module, then
Ansible will list openstacksdk once only:

* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

To see what documentation Ansible will produce for server module run:

  ansible-doc --type module openstack.cloud.server

[0] https://docs.ansible.com/ansible/latest/collections/openstack/\
    cloud/server_module.html

Change-Id: I727ed95ee480bb644b5a533f6a9526973677064c
2023-01-16 13:51:01 +01:00

266 lines
7.9 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = '''
---
module: identity_user
short_description: Manage OpenStack Identity Users
author: OpenStack Ansible SIG
description:
- Manage OpenStack Identity users. Users can be created,
updated or deleted using this module. A user will be updated
if I(name) matches an existing user and I(state) is present.
The value for I(name) cannot be updated without deleting and
re-creating the user.
options:
name:
description:
- Username for the user
required: true
type: str
password:
description:
- Password for the user
type: str
update_password:
required: false
choices: ['always', 'on_create']
default: on_create
description:
- C(always) will attempt to update password. C(on_create) will only
set the password for newly created users.
type: str
email:
description:
- Email address for the user
type: str
description:
description:
- Description about the user
type: str
default_project:
description:
- Project name or ID that the user should be associated with by default
type: str
domain:
description:
- Domain to create the user in if the cloud supports domains
type: str
enabled:
description:
- Is the user enabled
type: bool
default: 'yes'
state:
description:
- Should the resource be present or absent.
choices: [present, absent]
default: present
type: str
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = '''
# Create a user
- openstack.cloud.identity_user:
cloud: mycloud
state: present
name: demouser
password: secret
email: demo@example.com
domain: default
default_project: demo
# Delete a user
- openstack.cloud.identity_user:
cloud: mycloud
state: absent
name: demouser
# Create a user but don't update password if user exists
- openstack.cloud.identity_user:
cloud: mycloud
state: present
name: demouser
password: secret
update_password: on_create
email: demo@example.com
domain: default
default_project: demo
# Create a user without password
- openstack.cloud.identity_user:
cloud: mycloud
state: present
name: demouser
email: demo@example.com
domain: default
default_project: demo
'''
RETURN = '''
user:
description: Dictionary describing the user.
returned: On success when I(state) is 'present'
type: dict
contains:
default_project_id:
description: User default project ID. Only present with Keystone >= v3.
returned: success
type: str
sample: "4427115787be45f08f0ec22a03bfc735"
description:
description: The description of this user
returned: success
type: str
sample: "a user"
domain_id:
description: User domain ID. Only present with Keystone >= v3.
returned: success
type: str
sample: "default"
email:
description: User email address
returned: success
type: str
sample: "demo@example.com"
id:
description: User ID
returned: success
type: str
sample: "f59382db809c43139982ca4189404650"
is_enabled:
description: Indicates whether the user is enabled
type: bool
links:
description: The links for the user resource
returned: success
type: dict
elements: str
name:
description: Unique user name, within the owning domain
returned: success
type: str
sample: "demouser"
password:
description: Credential used during authentication
returned: success
type: str
password_expires_at:
description: The date and time when the password expires. The time zone is UTC. A none value means the password never expires
returned: success
type: str
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
class IdentityUserModule(OpenStackModule):
argument_spec = dict(
name=dict(required=True),
password=dict(no_log=True),
email=dict(),
default_project=dict(),
description=dict(),
domain=dict(),
enabled=dict(default=True, type='bool'),
state=dict(default='present', choices=['absent', 'present']),
update_password=dict(default='on_create', choices=['always', 'on_create']),
)
module_kwargs = dict()
def _needs_update(self, params_dict, user):
for k in params_dict:
# We don't get password back in the user object, so assume any supplied
# password is a change.
if k == 'password':
return True
if user[k] != params_dict[k]:
return True
return False
def _get_domain_id(self, domain):
dom_obj = self.conn.identity.find_domain(domain)
if dom_obj is None:
# Ok, let's hope the user is non-admin and passing a sane id
return domain
return dom_obj.id
def _get_default_project_id(self, default_project, domain_id):
project = self.conn.identity.find_project(default_project, domain_id=domain_id)
if not project:
self.fail_json(msg='Default project %s is not valid' % default_project)
return project['id']
def run(self):
name = self.params['name']
password = self.params.get('password')
email = self.params['email']
default_project = self.params['default_project']
domain = self.params['domain']
enabled = self.params['enabled']
state = self.params['state']
update_password = self.params['update_password']
description = self.params['description']
domain_id = None
if domain:
domain_id = self._get_domain_id(domain)
user = self.conn.identity.find_user(name, domain_id=domain_id)
changed = False
if state == 'present':
user_args = {
'name': name,
'email': email,
'domain_id': domain_id,
'description': description,
'is_enabled': enabled,
}
if default_project:
default_project_id = self._get_default_project_id(
default_project, domain_id)
user_args['default_project_id'] = default_project_id
user_args = {k: v for k, v in user_args.items() if v is not None}
changed = False
if user is None:
if password:
user_args['password'] = password
user = self.conn.identity.create_user(**user_args)
changed = True
else:
if update_password == 'always':
if not password:
self.fail_json(msg="update_password is always but a password value is missing")
user_args['password'] = password
# else we do not want to update the password
if self._needs_update(user_args, user):
user = self.conn.identity.update_user(user['id'], **user_args)
changed = True
user = user.to_dict(computed=False)
self.exit_json(changed=changed, user=user)
elif state == 'absent' and user is not None:
self.conn.identity.delete_user(user)
changed = True
self.exit_json(changed=changed)
def main():
module = IdentityUserModule()
module()
if __name__ == '__main__':
main()