From b304b9bbf10efed3dba69e616b12492c8a664358 Mon Sep 17 00:00:00 2001 From: Werner Dijkerman Date: Tue, 29 May 2018 08:43:40 +0200 Subject: [PATCH] Make use of a better python module for gitlab_group (#40764) * Make use of a python module that is not deprecated anymore * Updating version_added: "2.6" to version_added: "2.7" * Added missing line * Added notification about using different python module --- .../modules/source_control/gitlab_group.py | 199 ++++++++++-------- 1 file changed, 108 insertions(+), 91 deletions(-) diff --git a/lib/ansible/modules/source_control/gitlab_group.py b/lib/ansible/modules/source_control/gitlab_group.py index f63961804b..e3f26ff0b3 100644 --- a/lib/ansible/modules/source_control/gitlab_group.py +++ b/lib/ansible/modules/source_control/gitlab_group.py @@ -5,23 +5,22 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - DOCUMENTATION = ''' --- module: gitlab_group short_description: Creates/updates/deletes Gitlab Groups description: - When the group does not exist in Gitlab, it will be created. - - When the group does exists and state=absent, the group will be deleted. + - When the group does exist and state=absent, the group will be deleted. + - As of Ansible version 2.7, this module make use of a different python module and thus some arguments are deprecated. version_added: "2.1" author: "Werner Dijkerman (@dj-wasabi)" requirements: - - pyapi-gitlab python module + - python-gitlab python module options: server_url: description: @@ -30,18 +29,25 @@ options: validate_certs: description: - When using https if SSL certificate needs to be verified. + required: false default: true aliases: - verify_ssl login_user: description: - Gitlab user name. + required: false + default: null login_password: description: - Gitlab password for login_user + required: false + default: null login_token: description: - Gitlab token for logging in. + required: false + default: null name: description: - Name of the group you want to create. @@ -50,34 +56,43 @@ options: description: - The path of the group you want to create, this will be server_url/group_path - If not supplied, the group_name will be used. + required: false + default: null + description: + description: + - A description for the group. + required: false + default: null + version_added: "2.7" state: description: - create or delete group. - Possible values are present and absent. + required: false default: "present" choices: ["present", "absent"] ''' EXAMPLES = ''' -- name: Delete Gitlab Group - gitlab_group: - server_url: http://gitlab.example.com - validate_certs: False - login_token: WnUzDsxjy8230-Dy_k - name: my_first_group - state: absent - delegate_to: localhost +- name: "Delete Gitlab Group" + local_action: + gitlab_group: + server_url: http://gitlab.dj-wasabi.local + validate_certs: False + login_token: WnUzDsxjy8230-Dy_k + name: my_first_group + state: absent -- name: Create Gitlab Group - gitlab_group: - server_url: https://gitlab.example.com - validate_certs: True - login_user: dj-wasabi - login_password: MySecretPassword - name: my_first_group - path: my_first_group - state: present - delegate_to: localhost +- name: "Create Gitlab Group" + local_action: + gitlab_group: + server_url: https://gitlab.dj-wasabi.local" + validate_certs: True + login_user: dj-wasabi + login_password: "MySecretPassword" + name: my_first_group + path: my_first_group + state: present ''' RETURN = '''# ''' @@ -96,116 +111,118 @@ class GitLabGroup(object): def __init__(self, module, git): self._module = module self._gitlab = git + self.groupObject = None - def createGroup(self, group_name, group_path): - if self._module.check_mode: - self._module.exit_json(changed=True) - return self._gitlab.creategroup(group_name, group_path) + def createOrUpdateGroup(self, name, path, description): + changed = False + if self.groupObject is None: + group = self._gitlab.groups.create({'name': name, 'path': path}) + changed = True + else: + group = self.groupObject - def deleteGroup(self, group_name): - is_group_empty = True - group_id = self.idGroup(group_name) + if description is not None: + if group.description != description: + group.description = description + changed = True - for project in self._gitlab.getall(self._gitlab.getprojects): - owner = project['namespace']['name'] - if owner == group_name: - is_group_empty = False + if changed: + if self._module.check_mode: + self._module.exit_json(changed=True, result="Group should have updated.") + try: + group.save() + except Exception as e: + self._module.fail_json(msg="Failed to create or update a group: %s " % e) + return True + else: + return False - if is_group_empty: + def deleteGroup(self): + group = self.groupObject + if len(group.projects.list()) >= 1: + self._module.fail_json( + msg="There are still projects in this group. These needs to be moved or deleted before this group can be removed.") + else: if self._module.check_mode: self._module.exit_json(changed=True) - return self._gitlab.deletegroup(group_id) - else: - self._module.fail_json(msg="There are still projects in this group. These needs to be moved or deleted before this group can be removed.") + try: + group.delete() + except Exception as e: + self._module.fail_json(msg="Failed to delete a group: %s " % e) + return True - def existsGroup(self, group_name): - for group in self._gitlab.getall(self._gitlab.getgroups): - if group['name'] == group_name: - return True - return False - - def idGroup(self, group_name): - for group in self._gitlab.getall(self._gitlab.getgroups): - if group['name'] == group_name: - return group['id'] + def existsGroup(self, name): + """When group/user exists, object will be stored in self.groupObject.""" + groups = self._gitlab.groups.list(search=name) + if len(groups) == 1: + self.groupObject = groups[0] + return True def main(): module = AnsibleModule( argument_spec=dict( - server_url=dict(required=True), + server_url=dict(required=True, type='str'), validate_certs=dict(required=False, default=True, type='bool', aliases=['verify_ssl']), - login_user=dict(required=False, no_log=True), - login_password=dict(required=False, no_log=True), - login_token=dict(required=False, no_log=True), - name=dict(required=True), - path=dict(required=False), + login_user=dict(required=False, no_log=True, type='str'), + login_password=dict(required=False, no_log=True, type='str'), + login_token=dict(required=False, no_log=True, type='str'), + name=dict(required=True, type='str'), + path=dict(required=False, type='str'), + description=dict(required=False, type='str'), state=dict(default="present", choices=["present", "absent"]), ), + mutually_exclusive=[ + ['login_user', 'login_token'], + ['login_password', 'login_token'] + ], + required_together=[ + ['login_user', 'login_password'] + ], + required_one_of=[ + ['login_user', 'login_token'] + ], supports_check_mode=True ) if not HAS_GITLAB_PACKAGE: - module.fail_json(msg="Missing required gitlab module (check docs or " - "install with: pip install pyapi-gitlab") + module.fail_json(msg="Missing requried gitlab module (check docs or install with: pip install python-gitlab") server_url = module.params['server_url'] - verify_ssl = module.params['validate_certs'] + validate_certs = module.params['validate_certs'] login_user = module.params['login_user'] login_password = module.params['login_password'] login_token = module.params['login_token'] group_name = module.params['name'] group_path = module.params['path'] + description = module.params['description'] state = module.params['state'] - # We need both login_user and login_password or login_token, otherwise we fail. - if login_user is not None and login_password is not None: - use_credentials = True - elif login_token is not None: - use_credentials = False - else: - module.fail_json(msg="No login credentials are given. Use login_user with login_password, or login_token") + try: + git = gitlab.Gitlab(url=server_url, ssl_verify=validate_certs, email=login_user, password=login_password, + private_token=login_token, api_version=4) + git.auth() + except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: + module.fail_json(msg='Failed to connect to Gitlab server: %s' % to_native(e)) - # Set group_path to group_name if it is empty. if group_path is None: group_path = group_name.replace(" ", "_") - # Lets make an connection to the Gitlab server_url, with either login_user and login_password - # or with login_token - try: - if use_credentials: - git = gitlab.Gitlab(host=server_url, verify_ssl=verify_ssl) - git.login(user=login_user, password=login_password) - else: - git = gitlab.Gitlab(server_url, token=login_token, verify_ssl=verify_ssl) - except Exception as e: - module.fail_json(msg="Failed to connect to Gitlab server: %s " % to_native(e)) - - # Check if user is authorized or not before proceeding to any operations - # if not, exit from here - auth_msg = git.currentuser().get('message', None) - if auth_msg is not None and auth_msg == '401 Unauthorized': - module.fail_json(msg='User unauthorized', - details="User is not allowed to access Gitlab server " - "using login_token. Please check login_token") - - # Validate if group exists and take action based on "state" group = GitLabGroup(module, git) group_name = group_name.lower() group_exists = group.existsGroup(group_name) if group_exists and state == "absent": - group.deleteGroup(group_name) - module.exit_json(changed=True, result="Successfully deleted group %s" % group_name) + if group.deleteGroup(): + module.exit_json(changed=True, result="Successfully deleted group %s" % group_name) else: if state == "absent": - module.exit_json(changed=False, result="Group deleted or does not exist") + module.exit_json(changed=False, result="Group deleted or does not exists") else: - if group_exists: - module.exit_json(changed=False) + if group.createOrUpdateGroup(name=group_name, path=group_path, description=description): + module.exit_json(changed=True, result="Successfully created or updated the group %s" % group_name) else: - if group.createGroup(group_name, group_path): - module.exit_json(changed=True, result="Successfully created or updated the group %s" % group_name) + module.exit_json(changed=False, result="No need to update the group %s" % group_name) if __name__ == '__main__':