Loading services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +17 −24 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ from ..core import serviceapidescriptions from ..core.serviceapidescriptions import PublishServiceOperations from ..core.publisher import Publisher import json from flask import Response, request, current_app from flask_jwt_extended import jwt_required, get_jwt_identity from flask import current_app Loading @@ -14,15 +13,12 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps import pymongo from ..core.redis_event import RedisEvent service_operations = PublishServiceOperations() publisher_ops = Publisher() valid_user = ControlAccess() def cert_validation(): def _cert_validation(f): @wraps(f) Loading @@ -32,13 +28,16 @@ def cert_validation(): cert_tmp = request.headers['X-Ssl-Client-Cert'] cert_raw = cert_tmp.replace('\t', '') cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend()) cert = x509.load_pem_x509_certificate( str.encode(cert_raw), default_backend()) cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip() cn = cert.subject.get_attributes_for_oid( x509.OID_COMMON_NAME)[0].value.strip() if cn != "superadmin": cert_signature = cert.signature.hex() result = valid_user.validate_user_cert(args["apfId"], args["serviceApiId"], cert_signature) result = valid_user.validate_user_cert( args["apfId"], args["serviceApiId"], cert_signature) if result is not None: return result Loading @@ -48,6 +47,7 @@ def cert_validation(): return __cert_validation return _cert_validation def apf_id_service_apis_get(apf_id): # noqa: E501 """apf_id_service_apis_get Loading Loading @@ -83,13 +83,9 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 res = service_operations.add_serviceapidescription(apf_id, body) if res.status_code == 201: current_app.logger.info("Service published") api_id=res.headers['Location'].split('/')[-1] RedisEvent("SERVICE_API_AVAILABLE", "apiIds", [api_id] ).send_event() return res @cert_validation() def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_delete Loading @@ -105,15 +101,12 @@ def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: """ current_app.logger.info("Removing service published") res = service_operations.delete_serviceapidescription(service_api_id, apf_id) if res.status_code == 204: current_app.logger.info("Removed service published") RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", [service_api_id] ).send_event() publisher_ops.publish_message("internal-messages", f"service-removed:{service_api_id}") res = service_operations.delete_serviceapidescription( service_api_id, apf_id) return res @cert_validation() def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_get Loading @@ -133,6 +126,7 @@ def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E50 return res @cert_validation() def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noqa: E501 """apf_id_service_apis_service_api_id_put Loading @@ -149,14 +143,13 @@ def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noq :rtype: ServiceAPIDescription """ current_app.logger.info("Updating service api id with id: " + service_api_id) current_app.logger.info( "Updating service api id with id: " + service_api_id) if connexion.request.is_json: body = ServiceAPIDescription.from_dict(connexion.request.get_json()) # noqa: E501 response = service_operations.update_serviceapidescription(service_api_id, apf_id, body) if response.status_code == 200: publisher_ops.publish_message("events", "SERVICE_API_UPDATE") response = service_operations.update_serviceapidescription( service_api_id, apf_id, body) return response services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +48 −22 Original line number Diff line number Diff line Loading @@ -17,23 +17,30 @@ from ..util import dict_to_camel_case, clean_empty from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response from bson import json_util from .auth_manager import AuthManager from .redis_event import RedisEvent from .publisher import Publisher publisher_ops = Publisher() service_api_not_found_message = "Service API not found" class PublishServiceOperations(Resource): def __check_apf(self, apf_id): providers_col = self.db.get_col_by_name(self.db.capif_provider_col) current_app.logger.debug("Checking apf id") provider = providers_col.find_one({"api_prov_funcs.api_prov_func_id": apf_id}) provider = providers_col.find_one( {"api_prov_funcs.api_prov_func_id": apf_id}) if provider is None: current_app.logger.error("Publisher not exist") return unauthorized_error(detail="Publisher not existing", cause="Publisher id not found") list_apf_ids = [func["api_prov_func_id"] for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] list_apf_ids = [func["api_prov_func_id"] for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] if apf_id not in list_apf_ids: current_app.logger.debug("This id not belongs to APF") return unauthorized_error(detail="You are not a publisher", cause="This API is only available for publishers") Loading @@ -57,7 +64,8 @@ class PublishServiceOperations(Resource): if result != None: return result service = mycol.find({"apf_id": apf_id}, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) service = mycol.find({"apf_id": apf_id}, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) current_app.logger.debug(service) if service is None: current_app.logger.error("Not found services for this apf id") Loading Loading @@ -92,9 +100,11 @@ class PublishServiceOperations(Resource): if result != None: return result service = mycol.find_one({"api_name": serviceapidescription.api_name}) service = mycol.find_one( {"api_name": serviceapidescription.api_name}) if service is not None: current_app.logger.error("Service already registered with same api name") current_app.logger.error( "Service already registered with same api name") return forbidden_error(detail="Already registered service with same api name", cause="Found service with same api name") api_id = secrets.token_hex(15) Loading @@ -110,8 +120,13 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Service inserted in database") res = make_response(object=serviceapidescription, status=201) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + str(apf_id) + "/service-apis/" + str(api_id) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + \ str(apf_id) + "/service-apis/" + str(api_id) if res.status_code == 201: current_app.logger.info("Service published") RedisEvent("SERVICE_API_AVAILABLE", "apiIds", [str(api_id)]).send_event() return res except Exception as e: Loading @@ -119,26 +134,25 @@ class PublishServiceOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) def get_one_serviceapi(self, service_api_id, apf_id): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: current_app.logger.debug("Geting service api with id: " + service_api_id) current_app.logger.debug( "Geting service api with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} service_api = mycol.find_one(my_query, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) service_api = mycol.find_one(my_query, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) if service_api is None: current_app.logger.error(service_api_not_found_message) return not_found_error(detail=service_api_not_found_message, cause="No Service with specific credentials exists") my_service_api = dict_to_camel_case(service_api) my_service_api = clean_empty(my_service_api) Loading @@ -157,7 +171,8 @@ class PublishServiceOperations(Resource): try: current_app.logger.debug("Removing api service with id: " + service_api_id) current_app.logger.debug( "Removing api service with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: Loading @@ -176,21 +191,28 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Removed service from database") out = "The service matching api_id " + service_api_id + " was deleted." return make_response(out, status=204) res = make_response(out, status=204) if res.status_code == 204: current_app.logger.info("Removed service published") RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", [service_api_id]).send_event() publisher_ops.publish_message( "internal-messages", f"service-removed:{service_api_id}") return res except Exception as e: exception = "An exception occurred in delete service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) def update_serviceapidescription(self, service_api_id, apf_id, service_api_description): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: current_app.logger.debug("Updating service api with id: " + service_api_id) current_app.logger.debug( "Updating service api with id: " + service_api_id) result = self.__check_apf(apf_id) Loading @@ -207,18 +229,22 @@ class PublishServiceOperations(Resource): service_api_description = service_api_description.to_dict() service_api_description = clean_empty(service_api_description) result = mycol.find_one_and_update(serviceapidescription, {"$set":service_api_description}, projection={"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(serviceapidescription, {"$set": service_api_description}, projection={"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) current_app.logger.debug("Updated service api") service_api_description_updated = dict_to_camel_case(result) response = make_response(object=dict_to_camel_case(result), status=200) response = make_response( object=service_api_description_updated, status=200) if response.status_code == 200: RedisEvent("SERVICE_API_UPDATE", "serviceAPIDescriptions", [ service_api_description_updated]).send_event() return response except Exception as e: exception = "An exception occurred in update service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) services/run_capif_tests.sh +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ CAPIF_VAULT_PORT=8200 # CAPIF_VAULT_TOKEN=dev-only-token CAPIF_VAULT_TOKEN=read-ca-token MOCK_SERVER_URL=http://10.95.115.22:9090 MOCK_SERVER_URL=http://192.168.0.119:9090 echo "CAPIF_HOSTNAME = $CAPIF_HOSTNAME" Loading tests/features/CAPIF Api Events/capif_events_api.robot +81 −0 Original line number Diff line number Diff line Loading @@ -311,3 +311,84 @@ Invoker subscribe to Service API Available and Unavailable events Length Should Be ${notification_events_on_mock_server} 2 List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected_removed} List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected_created} Invoker subscribe to Service API Update [Tags] capif_api_events-8 mockserver # Start Mock server Check Mock Server Clean Mock Server # Register APF ${register_user_info_provider}= Provider Default Registration # Publish one api ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Subscribe to events ${events_list}= Create List SERVICE_API_UPDATE ${aef_ids}= Create List ${register_user_info_provider['aef_id']} ${event_filter}= Create Capif Event Filter aefIds=${aef_ids} ${event_filters}= Create List ${event_filter} ${request_body}= Create Events Subscription ... events=@{events_list} ... notificationDestination=${MOCK_SERVER_URL}/testing ... eventFilters=${event_filters} ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions ... json=${request_body} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} # Check Results Check Response Variable Type And Values ${resp} 201 EventSubscription ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} # Update Service API ${request_body_modified}= Create Service Api Description service_1_modified ${resp}= Put Request Capif ... ${resource_url.path} ... json=${request_body_modified} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${APF_PROVIDER_USERNAME} Check Response Variable Type And Values ${resp} 200 ServiceAPIDescription ... apiName=service_1_modified # Check Results Sleep 3s # Get from Mock server the EventNotification Messages sent to callback setup on event subscription. ${resp}= Get Mock Server Messages ${notification_events_on_mock_server}= Set Variable ${resp.json()} # Check if message follow EventNotification definition. Check Variable ${notification_events_on_mock_server} EventNotification # Create Notification Events expected to be received ${api_id}= Fetch From Right ${resource_url.path} / Set To Dictionary ${request_body_modified} apiId=${api_id} ${notification_event_expected}= Create Notification Event ... ${subscription_id} ... SERVICE_API_UPDATE ... serviceAPIDescriptions=${request_body_modified} Check Variable ${notification_event_expected} EventNotification # Check results Length Should Be ${notification_events_on_mock_server} 1 List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected} tests/libraries/api_events/bodyRequests.py +2 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ def create_notification_event(subscriptionId, event, serviceAPIDescriptions=None } count=0 if serviceAPIDescriptions != None: if isinstance(serviceAPIDescriptions,list()): if isinstance(serviceAPIDescriptions,list): result['eventDetail']['serviceAPIDescriptions']=serviceAPIDescriptions else: result['eventDetail']['serviceAPIDescriptions']=[serviceAPIDescriptions] Loading Loading @@ -83,7 +83,7 @@ def create_notification_event(subscriptionId, event, serviceAPIDescriptions=None result['eventDetail']['invocationLogs']=[invocationLogs] count=count+1 if apiTopoHide != None: if isinstance(apiTopoHide): if isinstance(apiTopoHide,list): result['eventDetail']['apiTopoHide']=apiTopoHide else: result['eventDetail']['apiTopoHide']=[apiTopoHide] Loading Loading
services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +17 −24 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ from ..core import serviceapidescriptions from ..core.serviceapidescriptions import PublishServiceOperations from ..core.publisher import Publisher import json from flask import Response, request, current_app from flask_jwt_extended import jwt_required, get_jwt_identity from flask import current_app Loading @@ -14,15 +13,12 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps import pymongo from ..core.redis_event import RedisEvent service_operations = PublishServiceOperations() publisher_ops = Publisher() valid_user = ControlAccess() def cert_validation(): def _cert_validation(f): @wraps(f) Loading @@ -32,13 +28,16 @@ def cert_validation(): cert_tmp = request.headers['X-Ssl-Client-Cert'] cert_raw = cert_tmp.replace('\t', '') cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend()) cert = x509.load_pem_x509_certificate( str.encode(cert_raw), default_backend()) cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip() cn = cert.subject.get_attributes_for_oid( x509.OID_COMMON_NAME)[0].value.strip() if cn != "superadmin": cert_signature = cert.signature.hex() result = valid_user.validate_user_cert(args["apfId"], args["serviceApiId"], cert_signature) result = valid_user.validate_user_cert( args["apfId"], args["serviceApiId"], cert_signature) if result is not None: return result Loading @@ -48,6 +47,7 @@ def cert_validation(): return __cert_validation return _cert_validation def apf_id_service_apis_get(apf_id): # noqa: E501 """apf_id_service_apis_get Loading Loading @@ -83,13 +83,9 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 res = service_operations.add_serviceapidescription(apf_id, body) if res.status_code == 201: current_app.logger.info("Service published") api_id=res.headers['Location'].split('/')[-1] RedisEvent("SERVICE_API_AVAILABLE", "apiIds", [api_id] ).send_event() return res @cert_validation() def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_delete Loading @@ -105,15 +101,12 @@ def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: """ current_app.logger.info("Removing service published") res = service_operations.delete_serviceapidescription(service_api_id, apf_id) if res.status_code == 204: current_app.logger.info("Removed service published") RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", [service_api_id] ).send_event() publisher_ops.publish_message("internal-messages", f"service-removed:{service_api_id}") res = service_operations.delete_serviceapidescription( service_api_id, apf_id) return res @cert_validation() def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_get Loading @@ -133,6 +126,7 @@ def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E50 return res @cert_validation() def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noqa: E501 """apf_id_service_apis_service_api_id_put Loading @@ -149,14 +143,13 @@ def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noq :rtype: ServiceAPIDescription """ current_app.logger.info("Updating service api id with id: " + service_api_id) current_app.logger.info( "Updating service api id with id: " + service_api_id) if connexion.request.is_json: body = ServiceAPIDescription.from_dict(connexion.request.get_json()) # noqa: E501 response = service_operations.update_serviceapidescription(service_api_id, apf_id, body) if response.status_code == 200: publisher_ops.publish_message("events", "SERVICE_API_UPDATE") response = service_operations.update_serviceapidescription( service_api_id, apf_id, body) return response
services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +48 −22 Original line number Diff line number Diff line Loading @@ -17,23 +17,30 @@ from ..util import dict_to_camel_case, clean_empty from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response from bson import json_util from .auth_manager import AuthManager from .redis_event import RedisEvent from .publisher import Publisher publisher_ops = Publisher() service_api_not_found_message = "Service API not found" class PublishServiceOperations(Resource): def __check_apf(self, apf_id): providers_col = self.db.get_col_by_name(self.db.capif_provider_col) current_app.logger.debug("Checking apf id") provider = providers_col.find_one({"api_prov_funcs.api_prov_func_id": apf_id}) provider = providers_col.find_one( {"api_prov_funcs.api_prov_func_id": apf_id}) if provider is None: current_app.logger.error("Publisher not exist") return unauthorized_error(detail="Publisher not existing", cause="Publisher id not found") list_apf_ids = [func["api_prov_func_id"] for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] list_apf_ids = [func["api_prov_func_id"] for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] if apf_id not in list_apf_ids: current_app.logger.debug("This id not belongs to APF") return unauthorized_error(detail="You are not a publisher", cause="This API is only available for publishers") Loading @@ -57,7 +64,8 @@ class PublishServiceOperations(Resource): if result != None: return result service = mycol.find({"apf_id": apf_id}, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) service = mycol.find({"apf_id": apf_id}, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) current_app.logger.debug(service) if service is None: current_app.logger.error("Not found services for this apf id") Loading Loading @@ -92,9 +100,11 @@ class PublishServiceOperations(Resource): if result != None: return result service = mycol.find_one({"api_name": serviceapidescription.api_name}) service = mycol.find_one( {"api_name": serviceapidescription.api_name}) if service is not None: current_app.logger.error("Service already registered with same api name") current_app.logger.error( "Service already registered with same api name") return forbidden_error(detail="Already registered service with same api name", cause="Found service with same api name") api_id = secrets.token_hex(15) Loading @@ -110,8 +120,13 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Service inserted in database") res = make_response(object=serviceapidescription, status=201) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + str(apf_id) + "/service-apis/" + str(api_id) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + \ str(apf_id) + "/service-apis/" + str(api_id) if res.status_code == 201: current_app.logger.info("Service published") RedisEvent("SERVICE_API_AVAILABLE", "apiIds", [str(api_id)]).send_event() return res except Exception as e: Loading @@ -119,26 +134,25 @@ class PublishServiceOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) def get_one_serviceapi(self, service_api_id, apf_id): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: current_app.logger.debug("Geting service api with id: " + service_api_id) current_app.logger.debug( "Geting service api with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} service_api = mycol.find_one(my_query, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) service_api = mycol.find_one(my_query, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) if service_api is None: current_app.logger.error(service_api_not_found_message) return not_found_error(detail=service_api_not_found_message, cause="No Service with specific credentials exists") my_service_api = dict_to_camel_case(service_api) my_service_api = clean_empty(my_service_api) Loading @@ -157,7 +171,8 @@ class PublishServiceOperations(Resource): try: current_app.logger.debug("Removing api service with id: " + service_api_id) current_app.logger.debug( "Removing api service with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: Loading @@ -176,21 +191,28 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Removed service from database") out = "The service matching api_id " + service_api_id + " was deleted." return make_response(out, status=204) res = make_response(out, status=204) if res.status_code == 204: current_app.logger.info("Removed service published") RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", [service_api_id]).send_event() publisher_ops.publish_message( "internal-messages", f"service-removed:{service_api_id}") return res except Exception as e: exception = "An exception occurred in delete service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) def update_serviceapidescription(self, service_api_id, apf_id, service_api_description): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: current_app.logger.debug("Updating service api with id: " + service_api_id) current_app.logger.debug( "Updating service api with id: " + service_api_id) result = self.__check_apf(apf_id) Loading @@ -207,18 +229,22 @@ class PublishServiceOperations(Resource): service_api_description = service_api_description.to_dict() service_api_description = clean_empty(service_api_description) result = mycol.find_one_and_update(serviceapidescription, {"$set":service_api_description}, projection={"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(serviceapidescription, {"$set": service_api_description}, projection={"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) current_app.logger.debug("Updated service api") service_api_description_updated = dict_to_camel_case(result) response = make_response(object=dict_to_camel_case(result), status=200) response = make_response( object=service_api_description_updated, status=200) if response.status_code == 200: RedisEvent("SERVICE_API_UPDATE", "serviceAPIDescriptions", [ service_api_description_updated]).send_event() return response except Exception as e: exception = "An exception occurred in update service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e))
services/run_capif_tests.sh +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ CAPIF_VAULT_PORT=8200 # CAPIF_VAULT_TOKEN=dev-only-token CAPIF_VAULT_TOKEN=read-ca-token MOCK_SERVER_URL=http://10.95.115.22:9090 MOCK_SERVER_URL=http://192.168.0.119:9090 echo "CAPIF_HOSTNAME = $CAPIF_HOSTNAME" Loading
tests/features/CAPIF Api Events/capif_events_api.robot +81 −0 Original line number Diff line number Diff line Loading @@ -311,3 +311,84 @@ Invoker subscribe to Service API Available and Unavailable events Length Should Be ${notification_events_on_mock_server} 2 List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected_removed} List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected_created} Invoker subscribe to Service API Update [Tags] capif_api_events-8 mockserver # Start Mock server Check Mock Server Clean Mock Server # Register APF ${register_user_info_provider}= Provider Default Registration # Publish one api ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Subscribe to events ${events_list}= Create List SERVICE_API_UPDATE ${aef_ids}= Create List ${register_user_info_provider['aef_id']} ${event_filter}= Create Capif Event Filter aefIds=${aef_ids} ${event_filters}= Create List ${event_filter} ${request_body}= Create Events Subscription ... events=@{events_list} ... notificationDestination=${MOCK_SERVER_URL}/testing ... eventFilters=${event_filters} ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions ... json=${request_body} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} # Check Results Check Response Variable Type And Values ${resp} 201 EventSubscription ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} # Update Service API ${request_body_modified}= Create Service Api Description service_1_modified ${resp}= Put Request Capif ... ${resource_url.path} ... json=${request_body_modified} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${APF_PROVIDER_USERNAME} Check Response Variable Type And Values ${resp} 200 ServiceAPIDescription ... apiName=service_1_modified # Check Results Sleep 3s # Get from Mock server the EventNotification Messages sent to callback setup on event subscription. ${resp}= Get Mock Server Messages ${notification_events_on_mock_server}= Set Variable ${resp.json()} # Check if message follow EventNotification definition. Check Variable ${notification_events_on_mock_server} EventNotification # Create Notification Events expected to be received ${api_id}= Fetch From Right ${resource_url.path} / Set To Dictionary ${request_body_modified} apiId=${api_id} ${notification_event_expected}= Create Notification Event ... ${subscription_id} ... SERVICE_API_UPDATE ... serviceAPIDescriptions=${request_body_modified} Check Variable ${notification_event_expected} EventNotification # Check results Length Should Be ${notification_events_on_mock_server} 1 List Should Contain Value ${notification_events_on_mock_server} ${notification_event_expected}
tests/libraries/api_events/bodyRequests.py +2 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ def create_notification_event(subscriptionId, event, serviceAPIDescriptions=None } count=0 if serviceAPIDescriptions != None: if isinstance(serviceAPIDescriptions,list()): if isinstance(serviceAPIDescriptions,list): result['eventDetail']['serviceAPIDescriptions']=serviceAPIDescriptions else: result['eventDetail']['serviceAPIDescriptions']=[serviceAPIDescriptions] Loading Loading @@ -83,7 +83,7 @@ def create_notification_event(subscriptionId, event, serviceAPIDescriptions=None result['eventDetail']['invocationLogs']=[invocationLogs] count=count+1 if apiTopoHide != None: if isinstance(apiTopoHide): if isinstance(apiTopoHide,list): result['eventDetail']['apiTopoHide']=apiTopoHide else: result['eventDetail']['apiTopoHide']=[apiTopoHide] Loading