Repository: ansible/ansible

Issue:
Ansible gitlab module should fail if importing the repo of url_import is failing
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Name of the module, plugin, task or feature
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
gitlab_project

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.2.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Red Hat Enterprise Linux Server release 7.2 (Maipo)

##### SUMMARY
<!--- Explain the problem briefly -->

I have this task which creates a GIT repo:
```yaml
- name: Create Git repo
  gitlab_project:
    server_url: "http://myhost.com/gitlab"
    validate_certs: True
    login_user: "my_git_user }}"
    login_password: "{{ my_git_password }}"
    name: "{{ my_repo_name }}"
    group: "{{ my_repo_group }}"
    public: True
    visibility_level: 20
    issues_enabled: False
    wiki_enabled: True
    snippets_enabled: True
    import_url: "http://myhost.com/gitlab/gitrepothatdoesnotexist.git"
    state: present
```

Then ansible succeeds in the step, but when I go to the gitlab web interface at the URL of the created git repo, it throws an error like:

" Import repository
The repository could not be imported.

Error importing repository http://myhost.com/gitlab/gitrepothatdoesnotexist.git into my_git_repo - Cloning into bare repository '[REPOS PATH]/mygitrepo.git'...
fatal: repository 'http://myhost.com/gitlab/gitrepothatdoesnotexist.git' not found

"

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Create Git repo
  gitlab_project:
    server_url: "http://myhost.com/gitlab"
    validate_certs: True
    login_user: "{{ my_git_user }}"
    login_password: "{{ my_git_password }}"
    name: "{{ my_repo_name }}"
    group: "{{ my_repo_group }}"
    public: True
    visibility_level: 20
    issues_enabled: False
    wiki_enabled: True
    snippets_enabled: True
    import_url: "http://myhost.com/gitlab/gitrepothatdoesnotexist.git"
    state: present
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

Gitlab should show an error when you visit the URL of the created repo.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```

Ansible gitlab module should fail if importing the repo of url_import is failing
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Name of the module, plugin, task or feature
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
gitlab_project

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.2.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Red Hat Enterprise Linux Server release 7.2 (Maipo)

##### SUMMARY
<!--- Explain the problem briefly -->

I have this task which creates a GIT repo:
```yaml
- name: Create Git repo
  gitlab_project:
    server_url: "http://myhost.com/gitlab"
    validate_certs: True
    login_user: "my_git_user }}"
    login_password: "{{ my_git_password }}"
    name: "{{ my_repo_name }}"
    group: "{{ my_repo_group }}"
    public: True
    visibility_level: 20
    issues_enabled: False
    wiki_enabled: True
    snippets_enabled: True
    import_url: "http://myhost.com/gitlab/gitrepothatdoesnotexist.git"
    state: present
```

Then ansible succeeds in the step, but when I go to the gitlab web interface at the URL of the created git repo, it throws an error like:

" Import repository
The repository could not be imported.

Error importing repository http://myhost.com/gitlab/gitrepothatdoesnotexist.git into my_git_repo - Cloning into bare repository '[REPOS PATH]/mygitrepo.git'...
fatal: repository 'http://myhost.com/gitlab/gitrepothatdoesnotexist.git' not found

"

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Create Git repo
  gitlab_project:
    server_url: "http://myhost.com/gitlab"
    validate_certs: True
    login_user: "{{ my_git_user }}"
    login_password: "{{ my_git_password }}"
    name: "{{ my_repo_name }}"
    group: "{{ my_repo_group }}"
    public: True
    visibility_level: 20
    issues_enabled: False
    wiki_enabled: True
    snippets_enabled: True
    import_url: "http://myhost.com/gitlab/gitrepothatdoesnotexist.git"
    state: present
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

Gitlab should show an error when you visit the URL of the created repo.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
Files identified in the description:
* [lib/ansible/modules/source_control/gitlab_project.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/source_control/gitlab_project.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @dj-wasabi
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Files identified in the description:
* [lib/ansible/modules/source_control/gitlab_project.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/source_control/gitlab_project.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @dj-wasabi
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/source_control/gitlab_project.py b/lib/ansible/modules/source_control/gitlab_project.py
--- a/lib/ansible/modules/source_control/gitlab_project.py
+++ b/lib/ansible/modules/source_control/gitlab_project.py
@@ -187,10 +187,15 @@ def createOrUpdateProject(self, project_exists, group_name, import_url, argument
 
     def createProject(self, is_user, user_id, import_url, arguments):
         if is_user:
-            return self._gitlab.createprojectuser(user_id=user_id, import_url=import_url, **arguments)
+            result = self._gitlab.createprojectuser(user_id=user_id, import_url=import_url, **arguments)
         else:
             group_id = user_id
-            return self._gitlab.createproject(namespace_id=group_id, import_url=import_url, **arguments)
+            result = self._gitlab.createproject(namespace_id=group_id, import_url=import_url, **arguments)
+
+        if not result:
+            self._module.fail_json(msg="Failed to create project %r" % arguments['name'])
+
+        return result
 
     def deleteProject(self, group_name, project_name):
         if self.existsGroup(group_name):


Test patch:
diff --git a/test/units/modules/source_control/__init__.py b/test/units/modules/source_control/__init__.py
new file mode 100644
diff --git a/test/units/modules/source_control/test_gitlab_project.py b/test/units/modules/source_control/test_gitlab_project.py
new file mode 100644
--- /dev/null
+++ b/test/units/modules/source_control/test_gitlab_project.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018 Pierre-Louis Bonicoli <pierre-louis@libregerbil.fr>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import json
+
+from ansible.compat.tests.mock import MagicMock
+from ansible.modules.source_control import gitlab_project
+
+import pytest
+
+
+@pytest.fixture
+def patch_gitlab_project(mocker):
+    mocker.patch.object(gitlab_project, 'HAS_GITLAB_PACKAGE', mocker.PropertyMock(return_value=True))
+
+
+@pytest.mark.parametrize('patch_ansible_module', [{}], indirect=['patch_ansible_module'])
+@pytest.mark.usefixtures('patch_ansible_module')
+def test_without_required_parameters(capfd):
+    """Failure must occurs when all parameters are missing"""
+
+    with pytest.raises(SystemExit):
+        gitlab_project.main()
+    out, err = capfd.readouterr()
+    results = json.loads(out)
+    assert results['failed']
+    assert 'missing required arguments' in results['msg']
+
+
+TEST_CASES = [
+    [
+        {
+            'server_url': 'http://gitlab.test/gitlab',
+            'validate_certs': True,
+            'login_user': 'john',
+            'login_token': 'TOKEN',
+            'name': 'new_test_repo',
+            'group': 'my_repo_group',
+            'public': True,
+            'visibility_level': 20,
+            'issues_enabled': False,
+            'wiki_enabled': True,
+            'snippets_enabled': True,
+            'import_url': 'http://gitlab.test/gitlab/gitrepothatdoesnotexist.git',
+            'state': 'present'
+        },
+        {
+            'msg': "Failed to create project 'new_test_repo'",
+            'failed': True,
+        }
+    ],
+]
+
+
+@pytest.mark.parametrize('patch_ansible_module, testcase', TEST_CASES, indirect=['patch_ansible_module'])
+@pytest.mark.usefixtures('patch_ansible_module')
+def test_fail_if_url_import_doesnt_exist(mocker, capfd, patch_gitlab_project, testcase):
+    """ Test for #36495
+
+    Ensure errors are reported (meaning task report a failure),
+    for example when url_import doesn't exist, an error must occur.
+    """
+
+    git = MagicMock()
+    git.createprojectuser.return_value = False
+
+    gitlab = MagicMock()
+    gitlab.Gitlab.return_value = git
+    gitlab_project.gitlab = gitlab
+
+    with pytest.raises(SystemExit):
+        gitlab_project.main()
+
+    # Check that 1. createprojectuser method has been called 2. with expected parameter
+    assert git.createprojectuser.call_count == 1
+    assert git.createprojectuser.call_args[1]['import_url'] == 'http://gitlab.test/gitlab/gitrepothatdoesnotexist.git'
+
+    out, err = capfd.readouterr()
+    results = json.loads(out)
+    assert results.get('failed') == testcase.get('failed')
+    assert results['msg'] == testcase['msg']