def test_module_should_fail_when_ftd_configuration_error( self, resource_mock): operation_name = 'test name' msg = 'Foo error.' resource_mock.side_effect = FtdConfigurationError(msg) result = self._run_module_with_fail_json({'operation': operation_name}) assert result['failed'] assert 'Failed to execute %s operation because of the configuration error: %s' % (operation_name, msg) == \ result['msg']
def test_upsert_object_succesfully_edited(self, extract_model_mock, edit_mock, add_mock, get_operation_mock, is_upsert_supported_mock): op_name = mock.MagicMock() params = mock.MagicMock() is_upsert_supported_mock.return_value = True error = FtdConfigurationError("Obj duplication error") error.obj = mock.MagicMock() add_mock.side_effect = error result = self._resource.upsert_object(op_name, params) assert result == edit_mock.return_value is_upsert_supported_mock.assert_called_once_with(op_name) extract_model_mock.assert_called_once_with(op_name) get_operation_mock.assert_called_once_with(extract_model_mock.return_value) add_mock.assert_called_once_with(get_operation_mock.return_value, params) edit_mock.assert_called_once_with(get_operation_mock.return_value, error.obj, params)
def test_upsert_object_neither_added_nor_edited(self, extract_model_mock, edit_mock, add_mock, get_operation_mock, is_upsert_supported_mock): op_name = mock.MagicMock() params = mock.MagicMock() is_upsert_supported_mock.return_value = True error = FtdConfigurationError("Obj duplication error") error.obj = mock.MagicMock() add_mock.side_effect = error edit_mock.side_effect = FtdConfigurationError("Some object edit error") self.assertRaises( FtdConfigurationError, self._resource.upsert_object, op_name, params ) is_upsert_supported_mock.assert_called_once_with(op_name) extract_model_mock.assert_called_once_with(op_name) get_operation_mock.assert_called_once_with(extract_model_mock.return_value) add_mock.assert_called_once_with(get_operation_mock.return_value, params) edit_mock.assert_called_once_with(get_operation_mock.return_value, error.obj, params)
def edit_object(self, operation_name, params): data, _, path_params = _get_user_params(params) model_name = self.get_operation_spec(operation_name)[OperationField.MODEL_NAME] get_operation = self._find_get_operation(model_name) if get_operation: existing_object = self.send_general_request(get_operation, {ParamName.PATH_PARAMS: path_params}) if not existing_object: raise FtdConfigurationError('Referenced object does not exist') elif equal_objects(existing_object, data): return existing_object return self.send_general_request(operation_name, params)
def _check_if_the_same_object(self, operation_name, params, e): """ Special check used in the scope of 'add_object' operation, which can be requested as a standalone operation or in the scope of 'upsert_object' operation. This method executed in case 'add_object' failed and should try to find the object that caused "object duplicate" error. In case single object found and it's equal to one we are trying to create - the existing object will be returned (attempt to have kind of idempotency for add action). In the case when we got more than one object returned as a result of the request to API - it will be hard to find exact duplicate so the exception will be raised. """ model_name = self.get_operation_spec(operation_name)[ OperationField.MODEL_NAME] get_list_operation = self._find_get_list_operation(model_name) if get_list_operation: data = params[ParamName.DATA] if not params.get(ParamName.FILTERS): params[ParamName.FILTERS] = {'name': data['name']} existing_obj = None existing_objs = self.get_objects_by_filter(get_list_operation, params) for i, obj in enumerate(existing_objs): if i > 0: raise FtdConfigurationError( MULTIPLE_DUPLICATES_FOUND_ERROR) existing_obj = obj if existing_obj is not None: if equal_objects(existing_obj, data): return existing_obj else: raise FtdConfigurationError( 'Cannot add new object. ' 'An object with the same name but different parameters already exists.', existing_obj) raise e
def _find_object_matching_params(self, model_name, params): get_list_operation = self._find_get_list_operation(model_name) if not get_list_operation: return None data = params[ParamName.DATA] if not params.get(ParamName.FILTERS): params[ParamName.FILTERS] = {'name': data['name']} obj = None filtered_objs = self.get_objects_by_filter(get_list_operation, params) for i, obj in enumerate(filtered_objs): if i > 0: raise FtdConfigurationError(MULTIPLE_DUPLICATES_FOUND_ERROR) obj = obj return obj
def test_upsert_object_with_fatal_error_during_add(self, edit_mock, add_mock, find_object, get_operation_mock, is_upsert_supported_mock): params = mock.MagicMock() is_upsert_supported_mock.return_value = True find_object.return_value = None error = FtdConfigurationError("Obj duplication error") add_mock.side_effect = error self.assertRaises( FtdConfigurationError, self._resource.upsert_object, 'upsertFoo', params ) is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value) self._conn.get_model_spec.assert_called_once_with('Foo') get_operation_mock.assert_called_once_with('Foo') find_object.assert_called_once_with('Foo', params) add_mock.assert_called_once_with(get_operation_mock.return_value, params) edit_mock.assert_not_called()
def test_upsert_object_with_fatal_error_during_edit(self, edit_mock, add_mock, find_object, get_operation_mock, is_upsert_supported_mock, equal_objects_mock): params = mock.MagicMock() existing_obj = mock.MagicMock() is_upsert_supported_mock.return_value = True find_object.return_value = existing_obj equal_objects_mock.return_value = False edit_mock.side_effect = FtdConfigurationError("Some object edit error") self.assertRaises( FtdConfigurationError, self._resource.upsert_object, 'upsertFoo', params ) is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value) self._conn.get_model_spec.assert_called_once_with('Foo') get_operation_mock.assert_called_once_with('Foo') find_object.assert_called_once_with('Foo', params) add_mock.assert_not_called() edit_mock.assert_called_once_with(get_operation_mock.return_value, existing_obj, params)
def _check_equality_with_existing_object(self, operation_name, params, e): """ Looks for an existing object that caused "object duplicate" error and checks whether it corresponds to the one specified in `params`. In case a single object is found and it is equal to one we are trying to create, the existing object is returned. When the existing object is not equal to the object being created or several objects are returned, an exception is raised. """ model_name = self.get_operation_spec(operation_name)[OperationField.MODEL_NAME] existing_obj = self._find_object_matching_params(model_name, params) if existing_obj is not None: if equal_objects(existing_obj, params[ParamName.DATA]): return existing_obj else: raise FtdConfigurationError(DUPLICATE_ERROR, existing_obj) raise e
def _add_upserted_object(self, model_operations, params): add_op_name = self._get_operation_name( self._operation_checker.is_add_operation, model_operations) if not add_op_name: raise FtdConfigurationError(ADD_OPERATION_NOT_SUPPORTED_ERROR) return self.add_object(add_op_name, params)
def _get_operation_name(checker, operations): for operation_name, op_spec in operations.items(): if checker(operation_name, op_spec): return operation_name raise FtdConfigurationError("Operation is not supported")