def setUpClass(cls): super(ClassesDaoTests, cls).setUpClass() # Make that instances of classs and instances dao point the mocks cls.dao_mock = ServiceClassDao() cls.dao = ServiceClassDao() # monkey patching daos for the execution of this class cls.patcher_coll = patch.object(cls.dao_mock, 'dbcoll', cls.mock_coll) # @UndefinedVariable cls.patcher_coll.start()
class UserAdminService(BaseService): def __init__(self): self.dao = UserAdminDao() self.classes_dao = ServiceClassDao() def get_all_users(self): return self.dao.find_all() @return_obj_or_raise_not_found def get_user(self, username): return self.dao.find(username) def validate_classes(self, classes): """ Check that the given classes exist in SD """ for class_ in classes: if self.classes_dao.find(class_) is None: raise UnsupportedParameterValueException( class_, 'existing-class') def create(self, user): self.validate_classes(user.get('classes', ())) try: return self.dao.create(user['_id'], make_password(user['password']), user.get('is_admin', False), user.get('classes', ()), user.get('origins', ())) except DuplicateKeyError: raise UnsupportedParameterValueException(user['_id'], 'non-existing-user') def update(self, user, auth_username): # user exist validation in serializer # Can not update himself if user['_id'] == auth_username: raise PermissionDenied('Admin user can not update himself.') self.validate_classes(user.get('classes', ())) if self.dao.update( user ): # if OperationFailure is raised, the exception mapper will translate return user else: raise GenericServiceError('User update failed') def delete(self, username, auth_username): # Ensure user exists self.get_user(username) if username == settings.SD_USERNAME: raise PermissionDenied('default user can not be deleted.') elif username == auth_username: raise PermissionDenied('Admin user can not delete himself.') if self.dao.delete(username) is False: raise GenericServiceError('User update failed')
def setUp(self): self.class_ = { '_id': 'test', 'description': 'Descripcion test', 'default_version': "1.0" } self.instance = { 'uri': 'http://test', 'version': '1.0', 'class_name': 'test' } self.instance_new = { 'uri': 'http://testNew', 'version': '1.0', 'class_name': 'test' } self.dao = ServiceInstanceDao() self.classes_dao = ServiceClassDao() self.classes_dao.create(self.class_) self.dao.create(self.instance) super(InstancesDaoTests, self).setUp()
class ServiceClassService(BaseService): """ Service to handle ServiceClass objects with mongodb and provide all business logic needed to views layer """ def __init__(self): self.class_dao = ServiceClassDao() self.instance_dao = ServiceInstanceDao() def get_all_service_classes(self): return list(self.class_dao.find_all()) def create(self, obj): try: return self.class_dao.create(obj) except DuplicateKeyError: raise UnsupportedParameterValueException(obj['_id'], 'non-existing-class') @return_obj_or_raise_not_found def get(self, class_name): return self.class_dao.find(class_name) def update(self, obj): # raise not found if not existing class if self.class_dao.update( obj): # When OperationFailure, Exception mapper will translate return obj else: raise GenericServiceError('Class update failed') def delete(self, class_name): class_obj = self.class_dao.find(class_name) if class_obj: try: self.instance_dao.delete_by_class_name(class_name) except OperationFailure: raise GenericServiceError('The class delete process failed.') if self.class_dao.delete(class_name): return else: raise GenericServiceError('The class delete process failed.') raise NotFoundException(class_name)
class InstancesDaoTests(TestCase): def setUp(self): self.class_ = { '_id': 'test', 'description': 'Descripcion test', 'default_version': "1.0" } self.instance = { 'uri': 'http://test', 'version': '1.0', 'class_name': 'test' } self.instance_new = { 'uri': 'http://testNew', 'version': '1.0', 'class_name': 'test' } self.dao = ServiceInstanceDao() self.classes_dao = ServiceClassDao() self.classes_dao.create(self.class_) self.dao.create(self.instance) super(InstancesDaoTests, self).setUp() def tearDown(self): self.dao.delete(self.instance['_id']) self.classes_dao.delete(self.class_['_id']) def test_add_new_instance_should_work(self): self.dao.create(self.instance_new) created_instance = self.dao.find(self.instance_new['_id']) self.assertEquals(created_instance, self.instance_new) # Removing created instance self.dao.delete(created_instance['_id']) def test_find_existing_instance_should_work(self): # _id is an objectId but we convert to str representation existing_instance = self.dao.find(str(self.instance['_id'])) self.assertEquals(existing_instance, self.instance) def test_find_instance_by_class_name_and_id_invalid_id_should_return_none( self): # _id is an objectId but we convert to str representation res = self.dao.find_by_class_name_and_id('test', 'invalid_id') self.assertEquals(None, res) def test_find_all_existing_instance_should_work(self): # _id is an objectId but we convert to str representation instances_list = self.dao.find_all('test') self.assertEquals(1, len(list(instances_list))) def test_add_existing_instance_should_raiseException(self): """ We check than uri, version and class_name are unique for instances collection """ # We don't use self.instance as _id will be populated by setUp method # We want ton ensure unique index is being managed self.assertRaises(DuplicateKeyError, self.dao.create, { 'uri': 'http://test', 'version': '1.0', 'class_name': 'test' }) def test_modify_existing_instance_should_return_true(self): self.instance['ob'] = 'oba' res = self.dao.update(self.instance) self.assertEquals(True, res, 'ob param not added') def test_modify_invalid_instance_id_should_return_false(self): self.instance_new['_id'] = '8989_nonExisting' res = self.dao.update(self.instance_new) self.assertEquals( False, res, 'Non existing instance was modified and it shouldnt') def test_modify_non_existing_instance_should_return_false(self): self.instance_new['_id'] = '5555b1d2f26ba3088459ffff' res = self.dao.update(self.instance_new) self.assertEquals( False, res, 'Non existing instance was modified and it shouldnt') def test_modify_existing_instance_matching_another_should_return_DuplicateKeyException( self): instance_new = self.dao.create(self.instance_new) instance_new['uri'] = self.instance['uri'] instance_new['version'] = self.instance['version'] self.assertRaises(DuplicateKeyError, self.dao.update, instance_new) def test_delete_invalid_instance_id_should_return_false(self): res = self.dao.delete('non_exitings_id') self.assertEquals(res, False, 'Delete not existing instance didnt return false') def test_delete_unexisting_instance_id_should_return_false(self): res = self.dao.delete('5555b1d2f26ba3088459ffff') self.assertEquals(res, False, 'Delete not existing instance didnt return false')
def __init__(self): self.binding_dao = BindingDao() self.class_dao = ServiceClassDao() self.instance_dao = ServiceInstanceDao()
class BindingService(BaseService): """ Service to handle Bindings objects with mongodb and provide all business logic needed to views layer """ def __init__(self): self.binding_dao = BindingDao() self.class_dao = ServiceClassDao() self.instance_dao = ServiceInstanceDao() @return_obj_or_raise_not_found def get_binding_by_id(self, binding_id): return self.binding_dao.find(binding_id) def get_all_bindings(self, query_params): return self.binding_dao.find_bindings(query_params) def create_binding(self, binding): if not self.class_dao.find(binding['class_name']): raise NotFoundException(binding['class_name']) try: self.check_binding_rules_in_class(binding) return self.binding_dao.create(binding) except DuplicateKeyError: raise UnsupportedParameterValueException( '{0}-{1}'.format(binding['class_name'], binding['origin']), 'non-duplicated-origin') def check_binding_rules_in_class(self, binding): for binding_rule in binding['binding_rules']: for binding_instance in binding_rule['bindings']: if not self.instance_dao.find_by_class_name_and_id( binding['class_name'], binding_instance): raise UnsupportedParameterValueException( binding_instance, "instances of {0}".format(binding['class_name'])) def update_binding(self, binding): if not self.class_dao.find(binding['class_name']): raise NotFoundException(binding['class_name']) # if not binding is found, not found is already launched in serializers try: self.check_binding_rules_in_class(binding) if self.binding_dao.update_binding(binding): return binding else: raise GenericServiceError('The binding update process failed.') except DuplicateKeyError: raise UnsupportedParameterValueException( '{0}-{1}'.format(binding['class_name'], binding['origin']), 'non-duplicated-origin') def delete_binding(self, binding_id): if not self.binding_dao.delete(binding_id, ): raise GenericServiceError('The binding delete process failed.') def get_binding_instance(self, params): try: class_name = params.pop('class_name') except KeyError: raise MissingMandatoryParameterException('class_name') class_ = self.class_dao.find(class_name) if not class_: raise NotFoundException(class_name) origin = params.get('origin', 'default') binding = self.binding_dao.find_by_class_and_origin(class_name, origin) if binding is None: # when rules are null in database rules = () else: rules = binding['binding_rules'] # perform the binding_instance operation if rules: binding_instances = self.get_binding_instances_by_rules( rules, params) if binding_instances is None: raise NotMatchingRuleException(class_name, origin) else: # Although we only return one binding_instance, in future this can deal # with several bindings and return the first binding alive if len(binding_instances) == 0: raise NotBindingInstanceException(class_name, origin) binding_instance = self.instance_dao.find(binding_instances[0]) if binding_instance: return binding_instance else: raise DeletedInstanceException(binding_instances[0]) else: # No rules defined for the search raise NotBindingDefinedException(class_name, origin) def get_binding_instances_by_rules(self, rules, context): """ Performs an ordered search over rules to return a tuple with the binding_instances and the input_key_param that first match with the context specified. :param rules and ordered array of rules for class_origins, defining also the binding_instances :param context The request query parameters to be applied as input of the rules :return the (instances, keys) that first match with the rules If any rule is matched, ((), ()) will be returned If no rules for search are found, None will be returned """ # Apply rules by priority for binding_rule in rules: # Check rule matches with context params matched_rule = True for rule in binding_rule['group_rules']: if not self.execute_rule(rule, context): matched_rule = False break if matched_rule: # rule matched, return bindings and keys return binding_rule['bindings'] # No binding_rules found at all return None def execute_rule(self, rule, context): """ Check if rule applied over context param is executed, that means the rule operand applied on the input param of context for the rule value is matched: input operand value is True :param rule a dict with operand, input_context_param and value :param context a dict with input context params value :return True if the rule can be executed for the context """ try: left_operand = context[rule['input_context_param']] right_operand = rule['value'] if rule['operation'] == 'eq': left_operand = convert_str_to_type(left_operand, type(right_operand[0])) return left_operand == right_operand[0] elif rule['operation'] == 'regex': pattern = re.compile(right_operand[0]) return pattern.match(left_operand) elif rule['operation'] == 'range': if type(right_operand[0]) != type(right_operand[1]): logger.error( "Bad rule definition for range, min and max must be of same type" ) raise GenericServiceError("Range rule defined is invalid") else: left_operand_c = convert_str_to_type( left_operand, type(right_operand[0])) if left_operand_c is None: raise UnsupportedParameterValueException( left_operand, pretty_type(right_operand[0])) return left_operand_c >= right_operand[ 0] and left_operand_c <= right_operand[1] elif rule['operation'] == 'in': left_operand_c = convert_str_to_type(left_operand, type(right_operand[0])) if left_operand_c is None: raise UnsupportedParameterValueException( left_operand, pretty_type(right_operand[0])) return left_operand_c in right_operand else: msg = "Unsupported operand for rule {0}".format( rule['operation']) logger.error(msg) raise GenericServiceError(msg) except (AttributeError, KeyError) as e: logger.debug(str(e)) return False
class ServiceInstanceService(BaseService): """ Service to handle ServiceInstance objects with mongodb and provide all business logic needed to views layer """ def __init__(self): self.instance_dao = ServiceInstanceDao() self.class_dao = ServiceClassDao() self.binding_dao = BindingDao() def create(self, obj): if not self.class_dao.find(obj['class_name']): raise NotFoundException(obj['class_name']) try: return self.instance_dao.create(obj) except DuplicateKeyError: raise UnsupportedParameterValueException( '{0}-{1}-{2}'.format(obj['class_name'], obj['uri'], obj['version']), 'non-duplicated-instance') def get_service_instance(self, class_name, instance_id): class_obj = self.class_dao.find(class_name) if class_obj: instance = self.instance_dao.find(instance_id) if instance: if instance['class_name'] == class_name: return instance else: raise UnsupportedParameterValueException( '{0}-{1}'.format(class_name, instance_id), 'instances-of-class') else: raise NotFoundException(instance_id) else: raise NotFoundException(class_name) def update(self, obj): # if not instance is found, not found would be raised in serializers try: if self.instance_dao.update(obj): return obj else: raise GenericServiceError( 'The instance update process failed.') except DuplicateKeyError: raise UnsupportedParameterValueException( '{0}-{1}-{2}'.format(obj['class_name'], obj['uri'], obj['version']), 'non-duplicated-instance') def delete(self, class_name, instance_id): class_obj = self.class_dao.find(class_name) if class_obj: instance = self.instance_dao.find(instance_id) if instance: if instance['class_name'] == class_name: if self.instance_dao.delete(instance_id): return else: raise GenericServiceError( 'The instance delete process failed.') else: raise UnsupportedParameterValueException( '{0}-{1}'.format(class_name, instance_id), 'instances-of-class') else: raise NotFoundException(instance_id) raise NotFoundException(class_name) def discover_service_instances(self, class_name, params): if 'class_name' in params: raise BadParameterException('class_name') class_obj = self.class_dao.find(class_name) if not class_obj: raise NotFoundException(class_name) params['class_name'] = class_name return self.instance_dao.find_instances(params)
def __init__(self): self.dao = UserAdminDao() self.classes_dao = ServiceClassDao()