diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py index bcf1905da8b4f3a5901a833fad70112740877c8b..80988ca84cadea6cb3e2b0f5597b4ae7b9748c6e 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py @@ -96,7 +96,7 @@ class InvokerManagementOperations(Resource): if res.status_code == 201: current_app.logger.info("Invoker Created") - RedisEvent("API_INVOKER_ONBOARDED", "apiInvokerIds", [str(api_invoker_id)]).send_event() + RedisEvent("API_INVOKER_ONBOARDED", ["apiInvokerIds"], [[str(api_invoker_id)]]).send_event() return res def update_apiinvokerenrolmentdetail(self, onboard_id, apiinvokerenrolmentdetail): @@ -133,7 +133,7 @@ class InvokerManagementOperations(Resource): res = make_response(object=serialize_clean_camel_case(invoker_updated), status=200) if res.status_code == 200: current_app.logger.info("Invoker Updated") - RedisEvent("API_INVOKER_UPDATED", "apiInvokerIds", [onboard_id]).send_event() + RedisEvent("API_INVOKER_UPDATED", ["apiInvokerIds"], [[onboard_id]]).send_event() return res except Exception as e: @@ -160,7 +160,7 @@ class InvokerManagementOperations(Resource): res = make_response(out, status=204) if res.status_code == 204: current_app.logger.info("Invoker Removed") - RedisEvent("API_INVOKER_OFFBOARDED", "apiInvokerIds", [onboard_id]).send_event() + RedisEvent("API_INVOKER_OFFBOARDED", ["apiInvokerIds"], [[onboard_id]]).send_event() publisher_ops.publish_message("internal-messages", f"invoker-removed:{onboard_id}") return res diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py index 1e5aa20c0d708dee31e51b2586e0295ba3ea629a..924ea9ee804609049cebbd66eea25f787f59c89f 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py @@ -59,7 +59,7 @@ class InternalServiceOps(Resource): "apiInvokerPolicies": inserted_service_acls_camel['apiInvokerPolicies'] } RedisEvent("ACCESS_CONTROL_POLICY_UPDATE", - "accCtrlPolList", accCtrlPolListExt).send_event() + ["accCtrlPolList"], [accCtrlPolListExt]).send_event() current_app.logger.info( f"Invoker ACL added for invoker: {invoker_id} for service: {service_id}") diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py index c9ac79e2cb52ab854fde8a60f15474cf4c6231a1..c1c7db19717d20ef4bce042a17268854e1474ea3 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py @@ -4,6 +4,8 @@ from .internal_event_ops import InternalEventOperations from models.event_notification import EventNotification from models.access_control_policy_list_ext import AccessControlPolicyListExt from models.capif_event_detail import CAPIFEventDetail +from models.event_subscription import EventSubscription +from models.service_api_description import ServiceAPIDescription from encoder import CustomJSONEncoder import sys import json @@ -29,11 +31,21 @@ class Notifications(): for sub in subscriptions: url = sub["notification_destination"] current_app.logger.debug(url) - event_detail=None + data = EventNotification(sub["subscription_id"], events=redis_event.get('event')) if redis_event.get('key', None) != None and redis_event.get('information', None) != None: - event_detail={redis_event.get('key'):redis_event.get('information')} - current_app.logger.debug(event_detail) - data = EventNotification(sub["subscription_id"], events=redis_event.get('event'), event_detail=event_detail) + event_detail={} + for pos, key in enumerate(redis_event.get('key', None)): + + if sub["supported_features"] is None: + if not (key == "serviceAPIDescriptions" and redis_event.get('event', None) in ["SERVICE_API_AVAILABLE", "SERVICE_API_UNAVAILABLE"]): + event_detail[key]=redis_event.get('information', None)[pos] + else: + if not (redis_event.get('event', None) in ["SERVICE_API_AVAILABLE", "SERVICE_API_UNAVAILABLE"] and key == "serviceAPIDescriptions" and not EventSubscription.return_supp_feat_dict(sub["supported_features"])["ApiStatusMonitoring"]): + event_detail[key]=redis_event.get('information', None)[pos] + + current_app.logger.debug(event_detail) + data.event_detail=event_detail + current_app.logger.debug(json.dumps(data.to_dict(),cls=CustomJSONEncoder)) asyncio.run(self.send(url, serialize_clean_camel_case(data))) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/models/event_subscription.py b/services/TS29222_CAPIF_Events_API/capif_events/models/event_subscription.py index 6660c330ecad8435fcf196d2831abfc4583cfc9b..a5f49e2969cb0e49a131851bbf15e92a3184847f 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/models/event_subscription.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/models/event_subscription.py @@ -68,6 +68,18 @@ class EventSubscription(Model): self._websock_notif_config = websock_notif_config self._supported_features = supported_features + @classmethod + def return_supp_feat_dict(cls, supp_feat): + supp_feat_in_hex = int(supp_feat, 16) + supp_feat_in_bin = bin(supp_feat_in_hex)[2:] + + return { + "NotificationTestEvent": True if supp_feat_in_bin[0] == "1" else False, + "NotificationWebsocket": True if supp_feat_in_bin[1] == "1" else False, + "EnhancedEventReport": True if supp_feat_in_bin[2] == "1" else False, + "ApiStatusMonitoring": True if supp_feat_in_bin[3] == "1" else False + } + @classmethod def from_dict(cls, dikt) -> 'EventSubscription': """Returns the dict as a model diff --git a/services/TS29222_CAPIF_Events_API/capif_events/util.py b/services/TS29222_CAPIF_Events_API/capif_events/util.py index 2ce43820e363c598c99585ab03a09a8d56cfa719..d8f55b6e51e6b17282dd3f0523de653de1055147 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/util.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/util.py @@ -24,25 +24,39 @@ def clean_empty(d): def dict_to_camel_case(my_dict): + + result = {} + for attr, value in my_dict.items(): + if len(attr.split('_')) != 1: my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) else: my_key = attr + + if my_key == "serviceApiCategory": + my_key = "serviceAPICategory" + elif my_key == "serviceApiDescriptions": + my_key = "serviceAPIDescriptions" + if isinstance(value, list): result[my_key] = list(map( lambda x: dict_to_camel_case(x) if isinstance(x, dict) else x, value )) + elif hasattr(value, "to_dict"): result[my_key] = dict_to_camel_case(value) + elif isinstance(value, dict): value = dict_to_camel_case(value) result[my_key] = value else: result[my_key] = value + return result + def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py index d2ba9eae58a72eea476d2c81ed17db6e9ca91e56..662902226b0eba8500fa6afa0025c435369b9e1c 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py @@ -99,7 +99,7 @@ class LoggingInvocationOperations(Resource): current_app.logger.info(event) invocation_log_base['logs']=[log.to_dict()] invocationLogs=[invocation_log_base] - RedisEvent(event,"invocation_logs",invocationLogs).send_event() + RedisEvent(event,["invocation_logs"],[invocationLogs]).send_event() current_app.logger.debug("After log check") diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py index c1792b4c7544bd61cf6b5eb73240de1fede51178..cddfceaba69f2becd7948b09a0c7928d7e782d78 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py @@ -9,7 +9,9 @@ from .responses import internal_server_error, forbidden_error, not_found_error, from .auth_manager import AuthManager from .redis_event import RedisEvent from .publisher import Publisher - +from ..models.service_api_description import ServiceAPIDescription +import json +from ..encoder import CustomJSONEncoder publisher_ops = Publisher() @@ -123,13 +125,34 @@ class PublishServiceOperations(Resource): if res.status_code == 201: current_app.logger.info("Service published") if serviceapidescription.api_status is None or len(serviceapidescription.api_status.aef_ids) > 0: - current_app.logger.info("Service available") - RedisEvent("SERVICE_API_AVAILABLE", "apiIds", - [str(api_id)]).send_event() + if serviceapidescription.supported_features is not None: + if serviceapidescription.return_supp_feat_dict(serviceapidescription.supported_features)["ApiStatusMonitoring"]: + current_app.logger.info(f"Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["serviceAPIDescriptions", "apiIds"], + [[clean_n_camel_case(serviceapidescription.to_dict())],[str(api_id)]]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["apiIds"], + [str(api_id)]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["apiIds"], + [str(api_id)]).send_event() else: - current_app.logger.info("Service unavailable") - RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", - [str(api_id)]).send_event() + if serviceapidescription.supported_features is not None: + if serviceapidescription.return_supp_feat_dict(serviceapidescription.supported_features)["ApiStatusMonitoring"]: + current_app.logger.info(f"Service unavailable") + RedisEvent("SERVICE_API_UNAVAILABLE", ["serviceAPIDescriptions", "apiIds"], + [[clean_n_camel_case(serviceapidescription.to_dict())],[str(api_id)]]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_UNAVAILABLE", ["apiIds"], + [str(api_id)]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_UNAVAILABLE", ["apiIds"], + [str(api_id)]).send_event() + return res except Exception as e: @@ -182,9 +205,9 @@ class PublishServiceOperations(Resource): return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} - serviceapidescription = mycol.find_one(my_query) + serviceapidescription_dict = mycol.find_one(my_query, {"_id": 0, "onboarding_date": 0, "apf_id": 0}) - if serviceapidescription is None: + if serviceapidescription_dict is None: current_app.logger.error(service_api_not_found_message) return not_found_error(detail="Service API not existing", cause="Service API id not found") @@ -195,12 +218,28 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Removed service from database") out = "The service matching api_id " + service_api_id + " was deleted." res = make_response(out, status=204) + serviceapidescription= clean_empty(dict_to_camel_case(serviceapidescription_dict)) 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}") + is_supported = serviceapidescription.get("supportedFeatures") and \ + ServiceAPIDescription.return_supp_feat_dict(serviceapidescription["supportedFeatures"]).get("ApiStatusMonitoring") + + if is_supported: + current_app.logger.info("Service unavailable") + RedisEvent( + "SERVICE_API_UNAVAILABLE", + ["serviceAPIDescriptions", "apiIds"], + [[serviceapidescription], [str(service_api_id)]] + ).send_event() + + else: + status_message = "Service available" if serviceapidescription.get("supportedFeatures") is None else "Service unavailable" + current_app.logger.info(status_message) + RedisEvent( + "SERVICE_API_UNAVAILABLE", + ["apiIds"], + [str(service_api_id)] + ).send_event() + return res except Exception as e: @@ -244,17 +283,38 @@ class PublishServiceOperations(Resource): response = make_response( object=service_api_description_updated, status=200) + service_api_description = ServiceAPIDescription.from_dict(json.dumps(service_api_description_updated, cls=CustomJSONEncoder)) if response.status_code == 200: - RedisEvent("SERVICE_API_UPDATE", "serviceAPIDescriptions", [ - service_api_description_updated]).send_event() - if "apiStatus" not in service_api_description_updated or len(service_api_description_updated["apiStatus"]["aefIds"]) > 0: - current_app.logger.info("Service available") - RedisEvent("SERVICE_API_AVAILABLE", "apiIds", - [str(service_api_id)]).send_event() + RedisEvent("SERVICE_API_UPDATE", ["serviceAPIDescriptions"], [[ + service_api_description_updated]]).send_event() + if service_api_description.api_status is None or len(service_api_description.api_status.aef_ids) > 0: + if service_api_description.supported_features is not None: + if service_api_description.return_supp_feat_dict(service_api_description.supported_features)["ApiStatusMonitoring"]: + current_app.logger.info(f"Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["serviceAPIDescriptions", "apiIds"], + [[service_api_description],[str(service_api_id)]]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["apiIds"], + [str(service_api_id)]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_AVAILABLE", ["apiIds"], + [str(service_api_id)]).send_event() else: - current_app.logger.info("Service unavailable") - RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", - [str(service_api_id)]).send_event() + if service_api_description.supported_features is not None: + if service_api_description.return_supp_feat_dict(service_api_description.supported_features)["ApiStatusMonitoring"]: + current_app.logger.info(f"Service unavailable") + RedisEvent("SERVICE_API_UNAVAILABLE", ["serviceAPIDescriptions", "apiIds"], + [[service_api_description],[str(service_api_id)]]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_UNAVAILABLE", ["apiIds"], + [str(service_api_id)]).send_event() + else: + current_app.logger.info("Service available") + RedisEvent("SERVICE_API_UNAVAILABLE", ["apiIds"], + [str(service_api_id)]).send_event() return response