diff --git a/changelogs/fragments/64989-gitlab-handle-lib-new-version.yml b/changelogs/fragments/64989-gitlab-handle-lib-new-version.yml new file mode 100644 index 00000000000..6b888c35a5f --- /dev/null +++ b/changelogs/fragments/64989-gitlab-handle-lib-new-version.yml @@ -0,0 +1,2 @@ +bugfixes: + - Fix GitLab modules authentication by handling `python-gitlab` library version >= 1.13.0 (https://github.com/ansible/ansible/issues/64770) \ No newline at end of file diff --git a/lib/ansible/module_utils/gitlab.py b/lib/ansible/module_utils/gitlab.py index 8f2ef4b6f6f..5d8a7fea2b1 100644 --- a/lib/ansible/module_utils/gitlab.py +++ b/lib/ansible/module_utils/gitlab.py @@ -6,14 +6,27 @@ from __future__ import absolute_import import json +from distutils.version import StrictVersion +from ansible.module_utils.basic import missing_required_lib from ansible.module_utils.urls import fetch_url +from ansible.module_utils._text import to_native try: from urllib import quote_plus # Python 2.X except ImportError: from urllib.parse import quote_plus # Python 3+ +import traceback + +GITLAB_IMP_ERR = None +try: + import gitlab + HAS_GITLAB_PACKAGE = True +except Exception: + GITLAB_IMP_ERR = traceback.format_exc() + HAS_GITLAB_PACKAGE = False + def request(module, api_url, project, path, access_token, private_token, rawdata='', method='GET'): url = "%s/v4/projects/%s%s" % (api_url, quote_plus(project), path) @@ -59,3 +72,33 @@ def findGroup(gitlab_instance, identifier): return None return project + + +def gitlabAuthentication(module): + gitlab_url = module.params['api_url'] + validate_certs = module.params['validate_certs'] + gitlab_user = module.params['api_username'] + gitlab_password = module.params['api_password'] + gitlab_token = module.params['api_token'] + + if not HAS_GITLAB_PACKAGE: + module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) + + try: + # python-gitlab library remove support for username/password authentication since 1.13.0 + # Changelog : https://github.com/python-gitlab/python-gitlab/releases/tag/v1.13.0 + # This condition allow to still support older version of the python-gitlab library + if StrictVersion(gitlab.__version__) < StrictVersion("1.13.0"): + gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, + private_token=gitlab_token, api_version=4) + else: + gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, private_token=gitlab_token, api_version=4) + + gitlab_instance.auth() + except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: + module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) + except (gitlab.exceptions.GitlabHttpError) as e: + module.fail_json(msg="Failed to connect to GitLab server: %s. \ + GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e)) + + return gitlab_instance diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_deploy_key.py b/lib/ansible/modules/source_control/gitlab/gitlab_deploy_key.py index d820652d830..1c8c249c6bf 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_deploy_key.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_deploy_key.py @@ -132,7 +132,7 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native -from ansible.module_utils.gitlab import findProject +from ansible.module_utils.gitlab import findProject, gitlabAuthentication class GitLabDeployKey(object): @@ -260,12 +260,6 @@ def main(): supports_check_mode=True, ) - gitlab_url = re.sub('/api.*', '', module.params['api_url']) - validate_certs = module.params['validate_certs'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] - state = module.params['state'] project_identifier = module.params['project'] key_title = module.params['title'] @@ -275,15 +269,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e)) + gitlab_instance = gitlabAuthentication(module) gitlab_deploy_key = GitLabDeployKey(module, gitlab_instance) diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_group.py b/lib/ansible/modules/source_control/gitlab/gitlab_group.py index 4f7909c2cb5..096f7b7c585 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_group.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_group.py @@ -140,7 +140,7 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native -from ansible.module_utils.gitlab import findGroup +from ansible.module_utils.gitlab import findGroup, gitlabAuthentication class GitLabGroup(object): @@ -278,12 +278,6 @@ def main(): supports_check_mode=True, ) - validate_certs = module.params['validate_certs'] - gitlab_url = module.params['api_url'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] - group_name = module.params['name'] group_path = module.params['path'] description = module.params['description'] @@ -294,15 +288,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2" % to_native(e)) + gitlab_instance = gitlabAuthentication(module) # Define default group_path based on group_name if group_path is None: diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_hook.py b/lib/ansible/modules/source_control/gitlab/gitlab_hook.py index cd5f3ae5366..7552e7fa392 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_hook.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_hook.py @@ -177,7 +177,7 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native -from ansible.module_utils.gitlab import findProject +from ansible.module_utils.gitlab import findProject, gitlabAuthentication class GitLabHook(object): @@ -326,12 +326,6 @@ def main(): supports_check_mode=True, ) - gitlab_url = re.sub('/api.*', '', module.params['api_url']) - validate_certs = module.params['validate_certs'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] - state = module.params['state'] project_identifier = module.params['project'] hook_url = module.params['hook_url'] @@ -349,15 +343,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e)) + gitlab_instance = gitlabAuthentication(module) gitlab_hook = GitLabHook(module, gitlab_instance) diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_project.py b/lib/ansible/modules/source_control/gitlab/gitlab_project.py index 910de316906..63776e2dc2b 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_project.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_project.py @@ -165,7 +165,7 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native -from ansible.module_utils.gitlab import findGroup, findProject +from ansible.module_utils.gitlab import findGroup, findProject, gitlabAuthentication class GitLabProject(object): @@ -302,12 +302,6 @@ def main(): supports_check_mode=True, ) - gitlab_url = module.params['api_url'] - validate_certs = module.params['validate_certs'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] - group_identifier = module.params['group'] project_name = module.params['name'] project_path = module.params['path'] @@ -323,15 +317,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e)) + gitlab_instance = gitlabAuthentication(module) # Set project_path to project_name if it is empty. if project_path is None: diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_project_variable.py b/lib/ansible/modules/source_control/gitlab/gitlab_project_variable.py index f846ea3c41e..f931d9eb41c 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_project_variable.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_project_variable.py @@ -122,6 +122,8 @@ except Exception: GITLAB_IMP_ERR = traceback.format_exc() HAS_GITLAB_PACKAGE = False +from ansible.module_utils.gitlab import gitlabAuthentication + class GitlabProjectVariables(object): @@ -225,8 +227,6 @@ def main(): supports_check_mode=True ) - api_url = module.params['api_url'] - gitlab_token = module.params['api_token'] purge = module.params['purge'] var_list = module.params['vars'] state = module.params['state'] @@ -234,14 +234,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=api_url, private_token=gitlab_token) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2" % to_native(e)) + gitlab_instance = gitlabAuthentication(module) this_gitlab = GitlabProjectVariables(module=module, gitlab_instance=gitlab_instance) diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_runner.py b/lib/ansible/modules/source_control/gitlab/gitlab_runner.py index b23216eeb1a..99bfe5bfe7f 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_runner.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_runner.py @@ -159,6 +159,8 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native +from ansible.module_utils.gitlab import gitlabAuthentication + try: cmp except NameError: @@ -306,12 +308,6 @@ def main(): supports_check_mode=True, ) - gitlab_url = module.params['api_url'] - validate_certs = module.params['validate_certs'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] - state = module.params['state'] runner_description = module.params['description'] runner_active = module.params['active'] @@ -325,15 +321,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2" % to_native(e)) + gitlab_instance = gitlabAuthentication(module) gitlab_runner = GitLabRunner(module, gitlab_instance) runner_exists = gitlab_runner.existsRunner(runner_description) diff --git a/lib/ansible/modules/source_control/gitlab/gitlab_user.py b/lib/ansible/modules/source_control/gitlab/gitlab_user.py index beb13cecf04..cd8d52f8fc6 100644 --- a/lib/ansible/modules/source_control/gitlab/gitlab_user.py +++ b/lib/ansible/modules/source_control/gitlab/gitlab_user.py @@ -176,7 +176,7 @@ from ansible.module_utils.api import basic_auth_argument_spec from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native -from ansible.module_utils.gitlab import findGroup +from ansible.module_utils.gitlab import findGroup, gitlabAuthentication class GitLabUser(object): @@ -431,11 +431,6 @@ def main(): ) ) - gitlab_url = module.params['api_url'] - validate_certs = module.params['validate_certs'] - gitlab_user = module.params['api_username'] - gitlab_password = module.params['api_password'] - gitlab_token = module.params['api_token'] user_name = module.params['name'] state = module.params['state'] user_username = module.params['username'].lower() @@ -452,15 +447,7 @@ def main(): if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) - try: - gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password, - private_token=gitlab_token, api_version=4) - gitlab_instance.auth() - except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s" % to_native(e)) - except (gitlab.exceptions.GitlabHttpError) as e: - module.fail_json(msg="Failed to connect to GitLab server: %s. \ - GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e)) + gitlab_instance = gitlabAuthentication(module) gitlab_user = GitLabUser(module, gitlab_instance) user_exists = gitlab_user.existsUser(user_username)