def translator_for(fiware_service: str): backend = backend_id_for(fiware_service) if backend == CRATE_BACKEND: translator = CrateTranslatorInstance() selected = CRATE_BACKEND elif backend == TIMESCALE_BACKEND: translator = postgres_translator_instance() selected = TIMESCALE_BACKEND else: translator = CrateTranslatorInstance() selected = CRATE_BACKEND log().debug( f"Backend selected for tenant '{fiware_service}' is: {selected}") return translator
def delete_entity(entity_id, type_=None, from_date=None, to_date=None): if type_ is None: r = { "error": "Not Implemented", "description": "For now, you must always specify entity type." } return r, 400 fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) with CrateTranslatorInstance() as trans: deleted = trans.delete_entity( entity_id=entity_id, entity_type=type_, from_date=from_date, to_date=to_date, fiware_service=fiware_s, fiware_servicepath=fiware_sp, ) if deleted == 0: r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404 if deleted > 0: return '{} records successfully deleted.'.format(deleted), 204
def translator_for(fiware_service: str): backend = lookup_backend(fiware_service) backend = backend.strip().lower() if backend is not None else '' if backend == CRATE_BACKEND: translator = CrateTranslatorInstance() selected = CRATE_BACKEND elif backend == TIMESCALE_BACKEND: translator = postgres_translator_instance() selected = TIMESCALE_BACKEND else: translator = CrateTranslatorInstance() selected = CRATE_BACKEND log().info( f"Backend selected for tenant '{fiware_service}' is: {selected}") return translator
def check_crate(): """ crateDB is the default backend of QuantumLeap, so it is required by default. """ from translators.crate import CrateTranslatorInstance with CrateTranslatorInstance() as trans: crate_health = trans.get_health() return crate_health
def translator_for(fiware_service: str): reader = YamlReader(log=log().debug) config = reader.from_env_file(QL_CONFIG_ENV_VAR, defaults={}) backend = maybe_string_match(config, 'tenants', fiware_service, 'backend')\ or maybe_string_match(config, 'default-backend') backend = backend.strip().lower() if backend is not None else '' if backend == CRATE_BACKEND: translator = CrateTranslatorInstance() selected = CRATE_BACKEND elif backend == TIMESCALE_BACKEND: translator = postgres_translator_instance() selected = TIMESCALE_BACKEND else: translator = CrateTranslatorInstance() selected = CRATE_BACKEND log().info( f"Backend selected for tenant '{fiware_service}' is: {selected}") return translator
def notify(): if request.json is None: return 'Discarding notification due to lack of request body. ' \ 'Lost in a redirect maybe?', 400 if 'data' not in request.json: return 'Discarding notification due to lack of request body ' \ 'content.', 400 payload = request.json['data'] if len(payload) > 1: return 'Multiple data elements in notifications not supported yet', 400 payload = payload[0] log().info('Received payload: {}'.format(payload)) # Validate notification error = _validate_payload(payload) if error: return error, 400 # Add TIME_INDEX attribute payload[CrateTranslator.TIME_INDEX_NAME] = \ select_time_index_value_as_iso(request.headers, payload) # Add GEO-DATE if enabled add_geodata(payload) # Always normalize location if there's one normalize_location(payload) # Define FIWARE tenant fiware_s = request.headers.get('fiware-service', None) # It seems orion always sends a 'Fiware-Servicepath' header with value '/' # But this is not correctly documented in the API, so in order not to # depend on this, QL will not treat servicepath if there's no service # specified. if fiware_s: fiware_sp = request.headers.get('fiware-servicepath', None) else: fiware_sp = None # Send valid entities to translator with CrateTranslatorInstance() as trans: trans.insert([payload], fiware_s, fiware_sp) msg = 'Notification successfully processed' log().info(msg) return msg
def check_db(db=CRATE_BACKEND): """ crateDB is the default backend of QuantumLeap, so it is required by default. """ if db == CRATE_BACKEND: from translators.crate import CrateTranslatorInstance with CrateTranslatorInstance() as trans: health = trans.get_health() return health if db == TIMESCALE_BACKEND: from translators.timescale import PostgresTranslator with PostgresTranslator() as trans: health = trans.get_health() return health
def query_NTNE( limit=10000, type_=None, # In Query from_date=None, to_date=None, offset=0): """ See /entities in API Specification quantumleap.yml """ fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None try: with CrateTranslatorInstance() as trans: entities = trans.query_ids(limit=limit, entity_type=type_, from_date=from_date, to_date=to_date, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp) except NGSIUsageError as e: msg = "Bad Request Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 400 except Exception as e: msg = "Internal server Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: res = [] for entity in entities: res.append(entity) return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1TNE1A( attr_name, # In Path entity_type, id_=None, # In Query aggr_method=None, aggr_period=None, aggr_scope=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0): """ See /types/{entityType}/attrs/{attrName} in API Specification quantumleap.yml """ r, c = _validate_query_params([attr_name], aggr_period, aggr_method, aggr_scope, options) if c != 200: return r, c fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None entity_ids = None if id_: entity_ids = [s.strip() for s in id_.split(',') if s] try: with CrateTranslatorInstance() as trans: entities = trans.query( attr_names=[attr_name], entity_type=entity_type, entity_ids=entity_ids, aggr_method=aggr_method, aggr_period=aggr_period, aggr_scope=aggr_scope, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, ) except AmbiguousNGSIIdError as e: return {"error": "AmbiguousNGSIIdError", "description": str(e)}, 409 except Exception as e: # Temp workaround to debug test_not_found msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: res = _prepare_response( entities, attr_name, entity_type, entity_ids, aggr_method, aggr_period, from_date, to_date, ) return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1T1E1A(attr_name, # In Path entity_id, type_=None, # In Query aggr_method=None, aggr_period=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0): """ See /entities/{entityId}/attrs/{attrName} in API Specification quantumleap.yml """ r, c = _validate_query_params([attr_name], aggr_period, aggr_method, options=options) if c != 200: return r, c fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None try: with CrateTranslatorInstance() as trans: entities = trans.query(attr_names=[attr_name], entity_type=type_, entity_id=entity_id, aggr_method=aggr_method, aggr_period=aggr_period, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp,) except AmbiguousNGSIIdError as e: return { "error": "AmbiguousNGSIIdError", "description": str(e) }, 409 except Exception as e: # Temp workaround to debug test_not_found msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: if len(entities) > 1: import warnings warnings.warn("Not expecting more than one result for a 1T1E1A.") index = [] if aggr_method and not aggr_period else entities[0]['index'] res = { 'data': { 'entityId': entities[0]['id'], 'attrName': attr_name, 'index': index, 'values': entities[0][attr_name]['values'] } } return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_NTNENA( id_=None, # In Query attrs=None, type_=None, aggr_method=None, aggr_period=None, aggr_scope=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0, georel=None, geometry=None, coords=None): """ See /v2/attrs in API Specification quantumleap.yml """ r, c = _validate_query_params(attrs, aggr_period, aggr_method, aggr_scope, options) if c != 200: return r, c r, c, geo_query = handle_geo_query(georel, geometry, coords) if r: return r, c if attrs is not None: attrs = attrs.split(',') fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None entity_ids = None if id_: entity_ids = [s.strip() for s in id_.split(',') if s] try: with CrateTranslatorInstance() as trans: entities = trans.query(attr_names=attrs, entity_type=type_, entity_ids=entity_ids, aggr_method=aggr_method, aggr_period=aggr_period, aggr_scope=aggr_scope, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, geo_query=geo_query) except NGSIUsageError as e: msg = "Bad Request Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 400 except Exception as e: msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 attributes = [] entries = [] attrs_names = [] attrs_values = [] ignore = ('id', 'index', 'type') if entities: for e in entities: attrs = [at for at in sorted(e.keys()) if at not in ignore] for at in attrs: if at not in attrs_names: attrs_names.append(at) for at in attrs_names: entity_type = [] entity_types = [] entity_value = [] for e in entities: matched_attr = lookup_string_match(e, at) if matched_attr is not None: index = [ from_date or '', to_date or '' ] if aggr_method and not aggr_period else e['index'] entity = { 'entityId': e['id'], 'index': index, 'values': matched_attr['values'] if matched_attr else [], } if e['type'] not in entity_types: entity_value = [] entity_value.append(entity) entity_ty = { 'entityType': e['type'], 'entities': entity_value } entity_type.append(entity_ty) entity_types.append(e['type']) else: entity_value.append(entity) entity_type.pop() entity_ty = { 'entityType': e['type'], 'entities': entity_value } entity_type.append(entity_ty) attrs_value = {'attrName': at, 'types': entity_type} attrs_values.append(attrs_value) res = {'attrs': attrs_values} return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1T1ENA(entity_id, # In Path type_=None, # In Query attrs=None, aggr_method=None, aggr_period=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0, georel=None, geometry=None, coords=None): """ See /entities/{entityId}/attrs/{attrName} in API Specification quantumleap.yml """ r, c = _validate_query_params(attrs, aggr_period, aggr_method, options=options) if c != 200: return r, c r, c, geo_query = handle_geo_query(georel, geometry, coords) if r: return r, c if attrs is not None: attrs = attrs.split(',') fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None try: with CrateTranslatorInstance() as trans: entities = trans.query(attr_names=attrs, entity_type=type_, entity_id=entity_id, aggr_method=aggr_method, aggr_period=aggr_period, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, geo_query=geo_query) except AmbiguousNGSIIdError as e: return { "error": "AmbiguousNGSIIdError", "description": str(e) }, 409 except Exception as e: # Temp workaround to debug test_not_found msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: if len(entities) > 1: import warnings warnings.warn("Not expecting more than one result for a 1T1ENA.") attributes = [] ignore = ('type', 'id', 'index') attrs = [at for at in sorted(entities[0].keys()) if at not in ignore] for at in attrs: attributes.append({ 'attrName': at, 'values': entities[0][at]['values'] }) index = [] if aggr_method and not aggr_period else entities[0]['index'] res = { 'entityId': entity_id, 'index': index, 'attributes': attributes } return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1TNENA( entity_type=None, # In Path id_=None, # In Query attrs=None, aggr_method=None, aggr_period=None, aggr_scope=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0, georel=None, geometry=None, coords=None): """ See /types/{entityType} in API Specification quantumleap.yml """ r, c = _validate_query_params(attrs, aggr_period, aggr_method, aggr_scope, options) if c != 200: return r, c r, c, geo_query = handle_geo_query(georel, geometry, coords) if r: return r, c if attrs is not None: attrs = attrs.split(',') fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None entity_ids = None if id_: entity_ids = [s.strip() for s in id_.split(',') if s] try: with CrateTranslatorInstance() as trans: entities = trans.query(attr_names=attrs, entity_type=entity_type, entity_ids=entity_ids, aggr_method=aggr_method, aggr_period=aggr_period, aggr_scope=aggr_scope, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, geo_query=geo_query) except NGSIUsageError as e: return {"error": "{}".format(type(e)), "description": str(e)}, 400 except Exception as e: msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: res = _prepare_response( entities, attrs, entity_type, entity_ids, aggr_method, aggr_period, from_date, to_date, ) return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1T1ENA(entity_id, # In Path type_=None, # In Query attrs=None, aggr_method=None, aggr_period=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0): """ See /entities/{entityId}/attrs/{attrName} in API Specification quantumleap.yml """ if type_ is None: r = { "error": "Not Implemented", "description": "For now, you must always specify entity type." } return r, 400 if options or aggr_period: import warnings warnings.warn("Unimplemented query parameters: options, aggrPeriod") if aggr_method and not attrs: msg = "Specified aggrMethod = {} but missing attrs parameter." return msg.format(aggr_method), 400 if attrs is not None: attrs = attrs.split(',') fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None with CrateTranslatorInstance() as trans: entities = trans.query(attr_names=attrs, entity_type=type_, entity_id=entity_id, aggr_method=aggr_method, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp,) if entities: if aggr_method: index = [] else: index = [str(e[CrateTranslator.TIME_INDEX_NAME]) for e in entities] ignore = ('type', 'id', CrateTranslator.TIME_INDEX_NAME) attrs = [at for at in sorted(entities[0].keys()) if at not in ignore] attributes = [] for at in attrs: attributes.append({ 'attrName': at, 'values': [] }) for i, at in enumerate(attrs): for e in entities: attributes[i]['values'].append(e[at]['value']) res = { 'data': { 'entityId': entity_id, 'index': index, 'attributes': attributes } } return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1T1ENA( entity_id, # In Path type_=None, # In Query attrs=None, aggr_method=None, aggr_period=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0): """ See /entities/{entityId}/attrs/{attrName} in API Specification quantumleap.yml """ r, c = _validate_query_params(aggr_period, aggr_method, attrs, options) if c != 200: return r, c if attrs is not None: attrs = attrs.split(',') fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None try: with CrateTranslatorInstance() as trans: entities = trans.query( attr_names=attrs, entity_type=type_, entity_id=entity_id, aggr_method=aggr_method, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, ) except AmbiguousNGSIIdError as e: return {"error": "AmbiguousNGSIIdError", "description": str(e)}, 409 except Exception as e: # Temp workaround to debug test_not_found msg = "Something went wrong with QL. Error: {}".format(e) logging.getLogger().error(msg, exc_info=True) return msg, 500 if entities: if aggr_method: index = [] else: index = [str(e[CrateTranslator.TIME_INDEX_NAME]) for e in entities] ignore = ('type', 'id', CrateTranslator.TIME_INDEX_NAME) attrs = [at for at in sorted(entities[0].keys()) if at not in ignore] attributes = [] for at in attrs: attributes.append({'attrName': at, 'values': []}) for i, at in enumerate(attrs): for e in entities: attributes[i]['values'].append(e[at]['value']) res = { 'data': { 'entityId': entity_id, 'index': index, 'attributes': attributes } } return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404
def query_1T1E1A( attr_name, # In Path entity_id, type_=None, # In Query aggr_method=None, aggr_period=None, options=None, from_date=None, to_date=None, last_n=None, limit=10000, offset=0): """ See /entities/{entityId}/attrs/{attrName} in API Specification quantumleap.yml """ if type_ is None: r = { "error": "Not Implemented", "description": "For now, you must always specify entity type." } return r, 400 if options or aggr_period: import warnings warnings.warn("Unimplemented query parameters: options, aggrPeriod") fiware_s = request.headers.get('fiware-service', None) fiware_sp = request.headers.get('fiware-servicepath', None) entities = None with CrateTranslatorInstance() as trans: entities = trans.query( attr_names=[attr_name], entity_type=type_, entity_id=entity_id, aggr_method=aggr_method, from_date=from_date, to_date=to_date, last_n=last_n, limit=limit, offset=offset, fiware_service=fiware_s, fiware_servicepath=fiware_sp, ) if entities: if aggr_method: index = [] else: index = [str(e[CrateTranslator.TIME_INDEX_NAME]) for e in entities] res = { 'data': { 'entityId': entity_id, 'attrName': attr_name, 'index': index, 'values': [e[attr_name]['value'] for e in entities] } } return res r = { "error": "Not Found", "description": "No records were found for such query." } return r, 404