From de05060049c8bcd1ae07de94c952da53df121d18 Mon Sep 17 00:00:00 2001 From: Dimitri Savineau Date: Wed, 28 Jul 2021 12:27:00 -0400 Subject: [PATCH] library: exit on user creation failure When the ceph dashboard user creation fails then the issue is hidden as we don't check the return code and don't print the error message in the module output. This ends up with a failure on the ceph dashboard set roles command saying that the user doesn't exist. By failing on the user creation, we will have an explicit explaination of the issue (like weak password). Closes: #6197 Signed-off-by: Dimitri Savineau (cherry picked from commit 17784624e0fb02080e14d15b4105ef92a78ec8c4) --- library/ceph_dashboard_user.py | 12 ++++++ tests/library/test_ceph_dashboard_user.py | 52 +++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/library/ceph_dashboard_user.py b/library/ceph_dashboard_user.py index ba94f83bb..801f0db40 100644 --- a/library/ceph_dashboard_user.py +++ b/library/ceph_dashboard_user.py @@ -109,6 +109,16 @@ EXAMPLES = ''' RETURN = '''# ''' +def fatal(message, module): + ''' + Report a fatal error and exit + ''' + if module: + module.fail_json(msg=message, rc=1) + else: + raise(Exception(message)) + + def container_exec(binary, container_image, interactive=False): ''' Build the docker CLI to run a command inside a container @@ -360,6 +370,8 @@ def run_module(): rc, cmd, out, err = exec_commands(module, set_password(module, container_image=container_image), stdin=stdin) # noqa: E501 else: rc, cmd, out, err = exec_commands(module, create_user(module, container_image=container_image), stdin=stdin) # noqa: E501 + if rc != 0: + fatal(err, module) rc, cmd, out, err = exec_commands(module, set_roles(module, container_image=container_image)) # noqa: E501 changed = True diff --git a/tests/library/test_ceph_dashboard_user.py b/tests/library/test_ceph_dashboard_user.py index b3f4e4303..89bd622a9 100644 --- a/tests/library/test_ceph_dashboard_user.py +++ b/tests/library/test_ceph_dashboard_user.py @@ -1,5 +1,8 @@ import os from mock.mock import patch, MagicMock +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes +import json import pytest import ceph_dashboard_user @@ -7,6 +10,32 @@ fake_container_binary = 'podman' fake_container_image = 'docker.io/ceph/daemon:latest' +def set_module_args(args): + if '_ansible_remote_tmp' not in args: + args['_ansible_remote_tmp'] = '/tmp' + if '_ansible_keep_remote_files' not in args: + args['_ansible_keep_remote_files'] = False + + args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + raise AnsibleFailJson(kwargs) + + class TestCephDashboardUserModule(object): def setup_method(self): self.fake_params = [] @@ -255,3 +284,26 @@ class TestCephDashboardUserModule(object): assert _cmd == expected_cmd assert _err == stderr assert _out == stdout + + @patch('ansible.module_utils.basic.AnsibleModule.fail_json') + @patch('ansible.module_utils.basic.AnsibleModule.run_command') + def test_create_user_fail_with_weak_password(self, m_run_command, m_fail_json): + set_module_args(self.fake_params) + m_fail_json.side_effect = fail_json + get_rc = 2 + get_stderr = 'Error ENOENT: User {} does not exist.'.format(self.fake_user) + get_stdout = '' + create_rc = 22 + create_stderr = 'Error EINVAL: Password is too weak.' + create_stdout = '' + m_run_command.side_effect = [ + (get_rc, get_stdout, get_stderr), + (create_rc, create_stdout, create_stderr) + ] + + with pytest.raises(AnsibleFailJson) as result: + ceph_dashboard_user.main() + + result = result.value.args[0] + assert result['msg'] == create_stderr + assert result['rc'] == 1 -- 2.39.5