diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py index d8b6c644f1f8f06da79d7362adac6fe9175ddef3..13fd27e34627e5419aeb0910fe9c6a662e5663a5 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py @@ -14,6 +14,7 @@ from service_apis import util from ..core.discoveredapis import DiscoverApisOperations from flask import Response, request, current_app +import json discover_apis = DiscoverApisOperations() @@ -55,20 +56,28 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t :rtype: Union[DiscoveredAPIs, Tuple[DiscoveredAPIs, int], Tuple[DiscoveredAPIs, int, Dict[str, str]] """ if request.is_json: - comm_type = CommunicationType.from_dict(request.get_json()()) # noqa: E501 + comm_type = CommunicationType.from_dict(request.get_json()()) # noqa: E501 if request.is_json: - protocol = Protocol.from_dict(request.get_json()()) # noqa: E501 + protocol = Protocol.from_dict(request.get_json()()) # noqa: E501 if request.is_json: - data_format = DataFormat.from_dict(request.get_json()()) # noqa: E501 + data_format = DataFormat.from_dict(request.get_json()()) # noqa: E501 if request.is_json: - preferred_aef_loc = AefLocation.from_dict(request.get_json()()) # noqa: E501 + preferred_aef_loc = AefLocation.from_dict(request.get_json()()) # noqa: E501 if request.is_json: - ue_ip_addr = IpAddrInfo.from_dict(request.get_json()()) # noqa: E501 + ue_ip_addr = IpAddrInfo.from_dict(request.get_json()()) # noqa: E501 if request.is_json: - service_kpis = ServiceKpis.from_dict(request.get_json()()) # noqa: E501 + service_kpis = ServiceKpis.from_dict(request.get_json()()) # noqa: E501 current_app.logger.info("Discovering service apis") query_params = {"api_name":api_name, "api_version":api_version, "comm_type":comm_type, "protocol":protocol, "aef_id":aef_id, "data_format":data_format, "api_cat":api_cat, "supported_features":supported_features, "api_supported_features":api_supported_features} + + if supported_features is not None: + supp_feat_dict = DiscoveredAPIs.return_supp_feat_dict(supported_features) + if supp_feat_dict['VendSpecQueryParams']: + for q_params in request.args: + if "vend-spec" in q_params: + query_params[q_params] = json.loads(request.args[q_params]) + response = discover_apis.get_discoveredapis(api_invoker_id, query_params) return response diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py index 487ceb14b65d6b7cca68b665257e0023dbcf926d..e07e4a1fab8a746c729eb7c04f9e49622471e99b 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py @@ -4,6 +4,7 @@ from ..core.responses import internal_server_error, forbidden_error ,make_respon from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case from ..core.resources import Resource +import json class DiscoverApisOperations(Resource): @@ -23,13 +24,33 @@ class DiscoverApisOperations(Resource): my_params = [] my_query = {} - quey_params_name = {"api_name":"api_name", "api_version":"aef_profiles.0.versions.0.api_version", "comm_type":"aef_profiles.0.versions.0.resources.0.comm_type", - "protocol":"aef_profiles.0.protocol", "aef_id":"aef_profiles.0.aef_id", "data_format":"aef_profiles.0.data_format", - "api_cat":"service_api_category", "supported_features":"supported_features", "api_supported_features":"api_supp_feats"} + # QPV = Query Parameter Value + query_params_name = { + "api_name": "api_name", + "api_version": '{"aef_profiles": {"$elemMatch": {"versions" : {"$elemMatch": {"api_version": "QPV"}}}}}', + "comm_type": '{"aef_profiles": {"$elemMatch": {"versions" : {"$elemMatch": {"resources": {"$elemMatch": {"comm_type":"QPV"}}}}}}}', + "protocol": '{"aef_profiles": {"$elemMatch": {"protocol":"QPV"}}}', + "aef_id": '{"aef_profiles": {"$elemMatch": {"aef_id":"QPV"}}}', + "data_format": '{"aef_profiles": {"$elemMatch": {"data_format":"QPV"}}}', + "api_cat": "service_api_category", + "supported_features": "supported_features", + "api_supported_features": "api_supp_feats" + } for param in query_params: + current_app.logger.info(query_params[param]) if query_params[param] is not None: - my_params.append({quey_params_name[param]: query_params[param]}) + if "vend-spec" in param: + current_app.logger.info("vend-spec in param") + attribute_path = query_params[param]["target"].split('/') + attribute = "aef_profiles.0." + attribute_path[1] + "." + attribute_path[2] + my_params.append({attribute: query_params[param]["value"]}) + elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]: + current_app.logger.info(query_params_name[param]) + current_app.logger.info(query_params_name[param].replace("QPV", query_params[param])) + my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param]))) + else: + my_params.append({query_params_name[param]: query_params[param]}) if my_params: my_query = {"$and": my_params} diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py index e780b70e7d57108b72115a903180ea2d0b8da40f..a3d5e36006dfd66181253a58d56cb77744a5fcbd 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py @@ -30,6 +30,17 @@ class DiscoveredAPIs(Model): self._service_api_descriptions = service_api_descriptions + @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 { + "RNAA": True if supp_feat_in_bin[0] == "1" else False, + "VendSpecQueryParams": True if supp_feat_in_bin[1] == "1" else False, + "ApiSupportedFeatureQuery": True if supp_feat_in_bin[2] == "1" else False, + } + @classmethod def from_dict(cls, dikt) -> 'DiscoveredAPIs': """Returns the dict as a model diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py index 9cce0faea7e3445df5cac2171151eea65dc14568..699208bf19690af438d9faa7faa9a948ab462979 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py @@ -76,15 +76,25 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 :rtype: Union[ServiceAPIDescription, Tuple[ServiceAPIDescription, int], Tuple[ServiceAPIDescription, int, Dict[str, str]] """ current_app.logger.info("Publishing service") - current_app.logger.info(request.content_type) + supp_feat_dict = ServiceAPIDescription.return_supp_feat_dict(body['supportedFeatures']) + + vendor_specific = [] if request.is_json: - body = ServiceAPIDescription.from_dict(request.get_json()) # noqa: E501 + if supp_feat_dict['VendorExt']: + aef_profile_array = body['aefProfiles'] + for (profile,i) in zip(aef_profile_array, range(len(aef_profile_array))): + for key, val in profile.items(): + if 'vendorSpecific' in key: + vendor_specific.append((i, key, val)) - res = service_operations.add_serviceapidescription(apf_id, body) + body = ServiceAPIDescription.from_dict(request.get_json()) + + res = service_operations.add_serviceapidescription(apf_id, body, vendor_specific) 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 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 9d73d37bda6e5dd0f77db5bc4937da819b1b8870..c1792b4c7544bd61cf6b5eb73240de1fede51178 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 @@ -4,7 +4,7 @@ from flask import current_app, Flask, Response from .resources import Resource from datetime import datetime -from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case,clean_n_camel_case from .responses import internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response from .auth_manager import AuthManager from .redis_event import RedisEvent @@ -78,7 +78,7 @@ class PublishServiceOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def add_serviceapidescription(self, apf_id, serviceapidescription): + def add_serviceapidescription(self, apf_id, serviceapidescription, vendor_specific): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) @@ -102,7 +102,13 @@ class PublishServiceOperations(Resource): rec = dict() rec['apf_id'] = apf_id rec['onboarding_date'] = datetime.now() - rec.update(serviceapidescription.to_dict()) + serviceapidescription_dict = serviceapidescription.to_dict() + if vendor_specific: + for vend_spec in vendor_specific: + for (profile,i) in zip(serviceapidescription_dict['aef_profiles'], range(len(serviceapidescription_dict['aef_profiles']))): + if i == vend_spec[0]: + profile[vend_spec[1]] = vend_spec[2] + rec.update(serviceapidescription_dict) mycol.insert_one(rec) @@ -110,7 +116,7 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Service inserted in database") - res = make_response(object=serialize_clean_camel_case(serviceapidescription), status=201) + res = make_response(object=clean_n_camel_case(serviceapidescription_dict), status=201) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + \ str(apf_id) + "/service-apis/" + str(api_id) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/models/service_api_description.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/models/service_api_description.py index 396b9fa2a47b4c653ef502ab8c6dd5e3fb8972d0..d6a514e81fea2f57715672b4e0e15bd7620a3a9a 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/models/service_api_description.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/models/service_api_description.py @@ -93,6 +93,23 @@ class ServiceAPIDescription(Model): self._ccf_id = ccf_id self._api_prov_name = api_prov_name + @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 { + "VendorExt": True if supp_feat_in_bin[0] == "1" else False, + "RNAA": True if supp_feat_in_bin[1] == "1" else False, + "EdgeApp_2": True if supp_feat_in_bin[2] == "1" else False, + "ApiStatusMonitoring": True if supp_feat_in_bin[3] == "1" else False, + "ProtocDataFormats_Ext1": True if supp_feat_in_bin[4] == "1" else False, + "MultipleCustomOperations": True if supp_feat_in_bin[5] == "1" else False, + "ExtendedIntfDesc": True if supp_feat_in_bin[6] == "1" else False, + "PatchUpdate": True if supp_feat_in_bin[7] == "1" else False, + "ApiSupportedFeaturePublishing": True if supp_feat_in_bin[9] == "1" else False, + } + @classmethod def from_dict(cls, dikt) -> 'ServiceAPIDescription': """Returns the dict as a model diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py index f18c8d6c6692e8eef8eeff56061d0cbbe39c75a9..2c8814f532b3e06803eb09a2344e48d1a79c94a6 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py @@ -10,6 +10,11 @@ def serialize_clean_camel_case(obj): return res +def clean_n_camel_case(res): + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res def clean_empty(d): if isinstance(d, dict):