import unittest from unittest.mock import patch, MagicMock from ansible.module_utils.basic import AnsibleModule from ansible_collections.ednz_cloud.infomaniak.plugins.modules import ( public_cloud_config_info, ) class TestPublicCloudConfigInfoModule(unittest.TestCase): """ Unit tests for the public_cloud_config_info Ansible module. """ @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_successful_retrieval(self, mock_client_class, mock_ansible_module): """ Test a successful retrieval of public cloud configuration. """ # Mock API response data api_response_data = { "result": "success", "data": { "free_tier": 300, "free_tier_used": 24.34, "account_resource_level": 2, "valid_from": 1707584356, "valid_to": 1717192799, "project_count": 2, }, } # Mock the InfomaniakAPIClient instance mock_client_instance = MagicMock() mock_client_instance.get.return_value = api_response_data mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_module_instance.check_mode = False # Simulate non-check mode mock_ansible_module.return_value = mock_module_instance # Mock exit_json to prevent actual exit mock_module_instance.exit_json = MagicMock() # Execute the run_module function public_cloud_config_info.run_module() # Assert that the InfomaniakAPIClient was initialized with the correct token mock_client_class.assert_called_with( api_version="1", api_token="mock_api_token" ) # Assert that the correct API call was made mock_client_instance.get.assert_called_once_with( "/public_clouds/config", params={"account_id": "mock_account_id"} ) # Assert exit_json is called once with the expected data mock_module_instance.exit_json.assert_called_once_with( changed=False, config=api_response_data["data"] ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_api_failure(self, mock_client_class, mock_ansible_module): """ Test failure scenario where API returns an error result. """ # Mock API failure response mock_client_instance = MagicMock() mock_client_instance.get.side_effect = Exception( "API request failed with result: error" ) mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "invalid_account_id", } mock_module_instance.check_mode = False # Simulate non-check mode mock_ansible_module.return_value = mock_module_instance # Mock fail_json to prevent actual exit mock_module_instance.fail_json = MagicMock() # Execute the run_module function public_cloud_config_info.run_module() # Assert fail_json was called with the expected error message mock_module_instance.fail_json.assert_called_once_with( msg="API request failed with result: error" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) def test_missing_required_params(self, mock_ansible_module): """ Test behavior when required parameters are missing. """ # Mock the AnsibleModule instance mock_module_instance = MagicMock() # Simulate missing 'api_token' in the parameters mock_module_instance.params = { "account_id": "mock_account_id", # Missing api_token } # Simulate Ansible behavior: fail_json should be called when 'api_token' is missing mock_ansible_module.return_value = mock_module_instance # Execute the run_module function and expect KeyError with self.assertRaises(KeyError): public_cloud_config_info.run_module() @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_empty_api_response(self, mock_client_class, mock_ansible_module): """ Test behavior when the API returns an empty response. """ # Mock API response data api_response_data = {"result": "success", "data": {}} # Empty data # Mock the InfomaniakAPIClient instance mock_client_instance = MagicMock() mock_client_instance.get.return_value = api_response_data mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_module_instance.check_mode = False # Simulate non-check mode mock_ansible_module.return_value = mock_module_instance # Execute the run_module function public_cloud_config_info.run_module() # Assert exit_json is called once with empty config data mock_module_instance.exit_json.assert_called_once_with(changed=False, config={}) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_unexpected_api_response_format( self, mock_client_class, mock_ansible_module ): """ Test behavior when the API response format is unexpected. """ # Mock an unexpected API response (missing 'result') api_response_data = { "data": { "free_tier": 300, } } # Mock the InfomaniakAPIClient instance mock_client_instance = MagicMock() mock_client_instance.get.return_value = api_response_data mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_ansible_module.return_value = mock_module_instance # Execute the run_module function public_cloud_config_info.run_module() # Assert fail_json is called with an appropriate error mock_module_instance.fail_json.assert_called_once_with( msg="API request failed with result: None" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) def test_check_mode(self, mock_ansible_module): """ Test behavior when check_mode is enabled. """ # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_module_instance.check_mode = True # Simulate check mode mock_ansible_module.return_value = mock_module_instance # Execute the run_module function public_cloud_config_info.run_module() # Assert exit_json is called with the check_mode message mock_module_instance.exit_json.assert_called_once_with( changed=False, msg="Check mode: No changes made, would retrieve public cloud config.", ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_network_timeout(self, mock_client_class, mock_ansible_module): """ Test behavior when a network timeout occurs. """ # Simulate a network timeout error mock_client_instance = MagicMock() mock_client_instance.get.side_effect = Exception("Request timeout") mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_ansible_module.return_value = mock_module_instance # Execute the run_module function public_cloud_config_info.run_module() # Assert fail_json is called with the timeout error message mock_module_instance.fail_json.assert_called_once_with(msg="Request timeout") @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule" ) @patch( "ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient" ) def test_invalid_json_response(self, mock_client_class, mock_ansible_module): """ Test behavior when the API returns an invalid JSON response. """ # Mock the InfomaniakAPIClient instance to raise a JSONDecodeError mock_client_instance = MagicMock() mock_client_instance.get.side_effect = Exception("Invalid JSON response") mock_client_class.return_value = mock_client_instance # Mock AnsibleModule parameters mock_module_instance = MagicMock() mock_module_instance.params = { "api_token": "mock_api_token", "account_id": "mock_account_id", } mock_ansible_module.return_value = mock_module_instance # Execute the run_module function public_cloud_config_info.run_module() # Assert fail_json is called with the appropriate error message mock_module_instance.fail_json.assert_called_once_with( msg="Invalid JSON response" ) if __name__ == "__main__": unittest.main()