# Copyright (c) Contributors to the Ansible project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import annotations from unittest.mock import patch from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import ( AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args, ) from ansible_collections.community.general.plugins.modules import lvg_rename VGS_OUTPUT = """\ vg_data_testhost1;XKZ5gn-YhWY-NlrT-QCFN-qmMG-VGT9-7uOmex vg_sys_testhost2;xgy2SJ-YlYd-fde2-e3oG-zdXL-0xGf-ihqG2H """ class TestLvgRename(ModuleTestCase): """Tests for lvg_rename internals""" module = lvg_rename module_path = "ansible_collections.community.general.plugins.modules.lvg_rename" def setUp(self): """Prepare mocks for module testing""" super().setUp() self.mock_run_responses = {} patched_module_get_bin_path = patch(f"{self.module_path}.AnsibleModule.get_bin_path") self.mock_module_get_bin_path = patched_module_get_bin_path.start() self.mock_module_get_bin_path.return_value = "/mocpath" self.addCleanup(patched_module_get_bin_path.stop) patched_module_run_command = patch(f"{self.module_path}.AnsibleModule.run_command") self.mock_module_run_command = patched_module_run_command.start() self.addCleanup(patched_module_run_command.stop) def test_vg_not_found_by_name(self): """When the VG by the specified by vg name not found, the module should exit with error""" failed = True self.mock_module_run_command.side_effect = [(0, VGS_OUTPUT, "")] expected_msg = "Both current (vg_missing) and new (vg_data_testhost2) VG are missing." module_args = { "vg": "vg_missing", "vg_new": "vg_data_testhost2", } with set_module_args(args=module_args): with self.assertRaises(AnsibleFailJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 1) self.assertIs(result.exception.args[0]["failed"], failed) self.assertEqual(result.exception.args[0]["msg"], expected_msg) def test_vg_not_found_by_uuid(self): """When the VG by the specified vg UUID not found, the module should exit with error""" failed = True self.mock_module_run_command.side_effect = [(0, VGS_OUTPUT, "")] expected_msg = ( "Both current (Yfj4YG-c8nI-z7w5-B7Fw-i2eM-HqlF-ApFVp0) and new (vg_data_testhost2) VG are missing." ) module_args = { "vg": "Yfj4YG-c8nI-z7w5-B7Fw-i2eM-HqlF-ApFVp0", "vg_new": "vg_data_testhost2", } with set_module_args(args=module_args): with self.assertRaises(AnsibleFailJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 1) self.assertIs(result.exception.args[0]["failed"], failed) self.assertEqual(result.exception.args[0]["msg"], expected_msg) def test_vg_and_vg_new_both_exists(self): """When a VG found for both vg and vg_new options, the module should exit with error""" failed = True self.mock_module_run_command.side_effect = [(0, VGS_OUTPUT, "")] expected_msg = "The new VG name (vg_sys_testhost2) is already in use." module_args = { "vg": "vg_data_testhost1", "vg_new": "vg_sys_testhost2", } with set_module_args(args=module_args): with self.assertRaises(AnsibleFailJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 1) self.assertIs(result.exception.args[0]["failed"], failed) self.assertEqual(result.exception.args[0]["msg"], expected_msg) def test_vg_needs_renaming(self): """When the VG found for vg option and there is no VG for vg_new option, the module should call vgrename""" changed = True self.mock_module_run_command.side_effect = [ (0, VGS_OUTPUT, ""), (0, ' Volume group "vg_data_testhost1" successfully renamed to "vg_data_testhost2"', ""), ] expected_msg = ' Volume group "vg_data_testhost1" successfully renamed to "vg_data_testhost2"' module_args = { "vg": "/dev/vg_data_testhost1", "vg_new": "vg_data_testhost2", } with set_module_args(args=module_args): with self.assertRaises(AnsibleExitJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 2) self.assertIs(result.exception.args[0]["changed"], changed) self.assertEqual(result.exception.args[0]["msg"], expected_msg) def test_vg_needs_renaming_in_check_mode(self): """When running in check mode and the VG found for vg option and there is no VG for vg_new option, the module should not call vgrename""" changed = True self.mock_module_run_command.side_effect = [(0, VGS_OUTPUT, "")] expected_msg = "Running in check mode. The module would rename VG /dev/vg_data_testhost1 to vg_data_testhost2." module_args = { "vg": "/dev/vg_data_testhost1", "vg_new": "vg_data_testhost2", "_ansible_check_mode": True, } with set_module_args(args=module_args): with self.assertRaises(AnsibleExitJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 1) self.assertIs(result.exception.args[0]["changed"], changed) self.assertEqual(result.exception.args[0]["msg"], expected_msg) def test_vg_needs_no_renaming(self): """When the VG not found for vg option and the VG found for vg_new option, the module should not call vgrename""" changed = False self.mock_module_run_command.side_effect = [(0, VGS_OUTPUT, "")] expected_msg = "The new VG (vg_data_testhost1) already exists, nothing to do." module_args = { "vg": "vg_data_testhostX", "vg_new": "vg_data_testhost1", } with set_module_args(args=module_args): with self.assertRaises(AnsibleExitJson) as result: self.module.main() self.assertEqual(len(self.mock_module_run_command.mock_calls), 1) self.assertIs(result.exception.args[0]["changed"], changed) self.assertEqual(result.exception.args[0]["msg"], expected_msg)