Esempio n. 1
0
    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
Esempio n. 2
0
    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)
Esempio n. 3
0
    def add_object(self, url_path, body_params, path_params=None, query_params=None, update_if_exists=False):
        def is_duplicate_name_error(err):
            return err.code == UNPROCESSABLE_ENTITY_STATUS and DUPLICATE_NAME_ERROR_MESSAGE in str(err)

        def update_existing_object(obj):
            new_path_params = {} if path_params is None else path_params
            new_path_params['objId'] = obj['id']
            return self.send_request(url_path=url_path + '/{objId}',
                                     http_method=HTTPMethod.PUT,
                                     body_params=copy_identity_properties(obj, body_params),
                                     path_params=new_path_params,
                                     query_params=query_params)

        try:
            return self.send_request(url_path=url_path, http_method=HTTPMethod.POST, body_params=body_params,
                                     path_params=path_params, query_params=query_params)
        except FtdServerError as e:
            if is_duplicate_name_error(e):
                existing_obj = self.get_object_by_name(url_path, body_params['name'], path_params)
                if equal_objects(existing_obj, body_params):
                    return existing_obj
                elif update_if_exists:
                    return update_existing_object(existing_obj)
                else:
                    raise FtdConfigurationError(
                        'Cannot add new object. An object with the same name but different parameters already exists.')
            else:
                raise e
Esempio n. 4
0
    def test_module_should_fail_when_operation_raises_configuration_error(self, connection_mock, resource_mock):
        connection_mock.get_operation_spec.return_value = {'method': HTTPMethod.GET, 'url': '/test'}
        resource_mock.send_request.side_effect = FtdConfigurationError('Foo error.')

        result = self._run_module_with_fail_json({'operation': 'failure'})
        assert result['failed']
        assert 'Failed to execute failure operation because of the configuration error: Foo error.' == result['msg']
Esempio n. 5
0
    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']
Esempio n. 6
0
    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)
Esempio n. 7
0
    def edit_object(self, url_path, body_params, path_params=None, query_params=None):
        existing_object = self.send_request(url_path=url_path, http_method=HTTPMethod.GET, path_params=path_params)

        if not existing_object:
            raise FtdConfigurationError('Referenced object does not exist')
        elif equal_objects(existing_object, body_params):
            return existing_object
        else:
            return self.send_request(url_path=url_path, http_method=HTTPMethod.PUT, body_params=body_params,
                                     path_params=path_params, query_params=query_params)
Esempio n. 8
0
    def edit_object(self, operation_name, params):
        data, dummy, 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)
Esempio n. 9
0
    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)
Esempio n. 12
0
    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
Esempio n. 13
0
 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)
Esempio n. 14
0
 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")