def on_put(self, req, resp, id=None): req_data = req.media or {} resp_data, valid = Code_Request_Schema( many=is_list(req_data), partial=True, method=HTTP_Method.PUT).validate(data=req.media, id=id) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for data in req_data_wrap: id, code, interface, metrics = item_getter( 'id', 'code', 'interface', 'metrics')(data) if all([id, code, interface]): if is_list(code): code = '\n'.join(code) pc = self.polycube.update(cube=id, code=code, interface=interface, metrics=metrics) if not pc.get('error', False): msg = f'Code with the id={id} correctly updated' resp_data = Ok_Response(msg) else: msg = f'Not possible to update code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.update(**pc) else: msg = f'Not possible to update code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.apply(resp) else: msg = 'No content to update code with the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def validate(self, data, response_type=Ok_Response, id=None): try: if id is not None: if is_list(data): msg = 'When the id is present in the request uri only one record can be managed.' raise Validation_Error({'id': msg}) elif id in data: msg = 'Present in the request uri.' raise Validation_Error({'id': msg}) else: data.update(id=id) if self.check_unique_id and is_list( data) and not Unique_List.apply('id')(data): msg = 'Same id present multiple times in the request.' raise Validation_Error({'id': msg}) self.load(data) return response_type(data), True except Validation_Error as val_err: def __norm(block): for field in block.keys(): if is_list(block[field]): block[field] = block[field].pop() elif is_dict(block[field]): __norm(block[field]) return block msg = __norm(val_err.normalized_messages()) return Not_Acceptable_Response(msg), False
def add(self, resp): if is_list(resp): resp.append(self.__data()) else: if not is_list(resp.media): resp.media = [] resp.media.append(self.__data()) resp_code = int(resp.status.split()[0]) if self.code is not None and HTTP_Status.lt(resp_code, self.code): resp.status = f'{self.code} {self.status()}'
def on_post(self, req, resp): req_data = req.media or {} resp_data, valid = Config_Request_Schema( many=is_list(req_data), method=HTTP_Method.POST).validate(data=req_data) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for config in req_data_wrap: for cfg, cfg_list in config.items(): for data in wrap(cfg_list): if cfg == 'actions': output = self.__actions(data) schema = Config_Action_Response_Schema elif cfg == 'parameters': output = self.__parameters(data) schema = Config_Parameter_Response_Schema elif cfg == 'resources': output = self.__resources(data) schema = Config_Resource_Response_Schema output.update(id=data.get('id', None), timestamp=datetime_to_str()) resp_data, valid = schema( many=False, method=HTTP_Method.POST).validate(data=output) if valid: Content_Response(output).add(resp) else: resp_data.add(resp) else: msg = f'No content to apply configurations with the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def on_delete(self, req, resp, id=None): req_data = req.media or {} resp_data, valid = Code_Request_Schema(many=is_list(req_data), partial=True, method=HTTP_Method.DELETE).validate(data=req.media, id=id) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for data in req_data_wrap: id = data.get('id', None) if id is not None: pc = self.polycube.delete(cube=id) if not pc.get('error', False): msg = f'Code with the id={id} correctly deleted' resp_data = Reset_Content_Response(msg) else: msg = f'Not possible to delete code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.update(**pc) else: msg = f'Not possible to update code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.apply(resp) else: msg = f'No content to delete code with the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def __norm(block): for field in block.keys(): if is_list(block[field]): block[field] = block[field].pop() elif is_dict(block[field]): __norm(block[field]) return block
def on_base_put(self, req, resp, id=None): so = self.doc.Status_Operation req_data = req.media or {} resp_data, valid = self.schema(many=is_list(req_data), unknown='INCLUDE', partial=True, method=HTTP_Method.PUT).validate( data=req_data, id=id) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for req_data in req_data_wrap: req_data_lcp = deepcopy(req_data) req_data_id = req_data.pop('id', id) try: if len(req_data) == 0: msg = f'Update for {self.name} with id={req_data_id} not necessary' Not_Modified_Response(msg).add(resp) else: self.rm_ignore_fields(req_data) obj = self.doc.get(id=req_data_id) resp_data_lcp = [] hndl = self.get_lcp_handler(HTTP_Method.PUT) modified = hndl(instance=obj, req=req_data_lcp, resp=resp_data_lcp) resp_data = Ok_Response( f'{self.name.capitalize()} with the id={req_data_id} correctly updated' ) if len(resp_data_lcp) > 0: for rdl in resp_data_lcp: if rdl['error']: msg = f'Not possible to update a {self.name} with the id={req_data_id}' resp_data = Unprocessable_Entity_Response( msg) break resp_data.update(lcp_response=resp_data_lcp) force = req_data.get('force', False) if (not resp_data.error or force) and len(req_data) > 0: res = obj.update(**req_data) if res == so.UPDATED: modified = True if force: msg = f'Some errors occur but the {self.name} with the id={req_data_id} forcedly updated' resp_data = Unprocessable_Entity_Response( msg) if not resp_data.error and not modified: msg = f'{self.name.capitalize()} with the id={req_data_id} no need to update' resp_data = Not_Modified_Response(msg) resp_data.add(resp) except Exception as e: msg = f'Not possible to update a {self.name} with the id={req_data_id}' Unprocessable_Entity_Response(msg, exception=e).add(resp) else: msg = f'No content to update {self.name} based on the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def on_post(self, req, resp, id=None): req_data = req.media or {} resp_data, valid = Code_Request_Schema(many=is_list(req_data), method=HTTP_Method.POST).validate(data=req.media, id=id) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for data in req_data_wrap: id, code, interface, metrics = item_getter('id', 'code', 'interface', 'metrics')(data) if all([id, code, interface]): pc = self.polycube.create(cube=id, code=code, interface=interface, metrics=metrics) if not pc.get('error', False): self.cubes.append(id) msg = f'Code with the id={id} correctly injected' resp_data = Created_Response(msg) else: msg = f'Not possible to inject code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.update(pc) else: msg = f'Not possible to inject code with the id={id}' resp_data = Unprocessable_Entity_Response(msg) resp_data.add(resp) else: msg = f'No content to create code with the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def on_base_post(self, req, resp, id=None): req_data = req.media or {} resp_data, valid = self.schema(many=is_list(req_data), unknown='INCLUDE', method=HTTP_Method.POST).validate( data=req_data, id=id) if valid: req_data_wrap = wrap(req_data) if len(req_data_wrap) > 0: for req_data in req_data_wrap: req_data_lcp = deepcopy(req_data) req_data_id = req_data.pop('id', id) try: self.rm_ignore_fields(req_data) obj = self.doc(meta={'id': req_data_id}, **req_data) resp_data_lcp = [] resp_data = Created_Response( f'{self.name.capitalize()} with the id={req_data_id} correctly created' ) hndl = self.get_lcp_handler(HTTP_Method.POST) hndl(instance=obj, req=req_data_lcp, resp=resp_data_lcp) if len(resp_data_lcp) > 0: for rdl in resp_data_lcp: if rdl['error']: msg = f'Not possible to create a {self.name} with the id={req_data_id}' resp_data = Unprocessable_Entity_Response( msg) break resp_data.update(lcp_response=resp_data_lcp) force = req_data.get('force', False) if not resp_data.error or force: obj.save() if force: msg = f'Some errors occur but the {self.name} with the id={req_data_id} forcedly created' resp_data = Unprocessable_Entity_Response(msg) resp_data.add(resp) except Exception as e: msg = f'Not possible to create a {self.name} with the id={req_data_id}' Unprocessable_Entity_Response(msg, exception=e).add(resp) else: msg = f'No content to create {self.names} based the {{request}}' No_Content_Response(msg, request=req_data).apply(resp) else: resp_data.apply(resp)
def __where(self, query, id=None): q = None for op, clause in query.get('where', {}).items(): if op == 'and': if is_dict(clause): for sub_op, sub_clause in clause.items(): if q is None: q = self.__where({'where': {sub_op: sub_clause}}) else: q = q & self.__where( {'where': { sub_op: sub_clause }}) elif is_list(clause): for sub_clause in clause: if q is None: q = self.__where({'where': sub_clause}) else: q = q & self.__where({'where': sub_clause}) elif op == 'or': if is_dict(clause): for sub_op, sub_clause in clause.items(): if q is None: q = self.__where({'where': {sub_op: sub_clause}}) else: q = q | self.__where( {'where': { sub_op: sub_clause }}) elif is_list(clause): for sub_clause in clause: if q is None: q = self.__where({'where': sub_clause}) else: q = q | self.__where({'where': sub_clause}) elif op == 'not': q = ~self.__where(clause) else: prop = self.__fix_target(clause.get('target', None)) expr = clause.get('expr', None) if prop is not None and expr is not None: if op == 'equals': q = Q('match_phrase', **{prop: expr}) elif op == 'reg_exp': q = Q('regexp', **{prop: {'value': expr}}) elif op == 'wildcard': q = Q('wildcard', **{prop: {'value': expr}}) elif op in ['lt', 'lte', 'gt', 'gte']: q = Q('range', **{prop: {op: expr}}) else: raise HTTP_Bad_Request(title='Operation unknown', description=f'{op} unknown') else: raise HTTP_Bad_Request( title='Request not valid', description=f'{op} clause with not valid/missing data') if id is not None: if q is None: q = Q('term', _id=id) else: q = q & Q('term', _id=id) return q if q is not None else Q()