From 0247cad7ad38e5bdd7393d28d6f01647c2da3b8b Mon Sep 17 00:00:00 2001 From: Stavros Charismiadis Date: Wed, 20 Nov 2024 13:28:25 +0200 Subject: [PATCH 1/6] fix vendor extensibility issues --- .../controllers/default_controller.py | 8 +- .../service_apis/core/discoveredapis.py | 18 +++-- .../service_apis/models/discovered_apis.py | 7 +- .../service_apis/vendor_specific.py | 76 +++++++++++++++++++ .../controllers/default_controller.py | 8 +- .../core/serviceapidescriptions.py | 12 ++- .../models/service_api_description.py | 20 ++--- .../published_apis/vendor_specific.py | 55 ++++++++++++++ 8 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/vendor_specific.py 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 13fd27e..6caef6a 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 @@ -68,12 +68,14 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t if request.is_json: 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} + # supported_features was removed from query_params + 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, "api_supported_features": api_supported_features} if supported_features is not None: supp_feat_dict = DiscoveredAPIs.return_supp_feat_dict(supported_features) + current_app.logger.info(supp_feat_dict) if supp_feat_dict['VendSpecQueryParams']: for q_params in request.args: if "vend-spec" in q_params: 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 e07e4a1..37c113e 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 @@ -5,6 +5,7 @@ from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case from ..core.resources import Resource import json +from ..vendor_specific import find_attribute_in_body, filter_apis_with_vendor_specific_params class DiscoverApisOperations(Resource): @@ -37,17 +38,14 @@ class DiscoverApisOperations(Resource): "api_supported_features": "api_supp_feats" } + vend_spec_query_params_n_values = {} for param in query_params: - current_app.logger.info(query_params[param]) if query_params[param] is not None: if "vend-spec" in param: - current_app.logger.info("vend-spec in param") + vend_param = param.split("vend-spec-")[1] 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"]}) + vend_spec_query_params_n_values[attribute_path[1] + "." + vend_param] = 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]}) @@ -55,10 +53,14 @@ class DiscoverApisOperations(Resource): if my_params: my_query = {"$and": my_params} - discoved_apis = services.find(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}) + discoved_apis = services.find(my_query, {"_id":0}) json_docs = [] for discoved_api in discoved_apis: - json_docs.append(discoved_api) + vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') + if vend_spec_query_params_n_values and vendor_specific_fields_path: + json_docs.append(filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path)) + else: + json_docs.append(discoved_api) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") 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 a3d5e36..cce0ff8 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 @@ -32,13 +32,14 @@ class DiscoveredAPIs(Model): @classmethod def return_supp_feat_dict(cls, supp_feat): + TOTAL_FEATURES = 3 supp_feat_in_hex = int(supp_feat, 16) - supp_feat_in_bin = bin(supp_feat_in_hex)[2:] + supp_feat_in_bin = bin(supp_feat_in_hex)[2:].zfill(TOTAL_FEATURES)[::-1] return { - "RNAA": True if supp_feat_in_bin[0] == "1" else False, + "ApiSupportedFeatureQuery": 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, + "RNAA": True if supp_feat_in_bin[2] == "1" else False } @classmethod diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py new file mode 100644 index 0000000..84e8c36 --- /dev/null +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py @@ -0,0 +1,76 @@ +import re + +def find_attribute_in_body(test, path): + f_key = [] + if type(test) == dict: + for k, v in test.items(): + if 'vendorSpecific' in k: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + f_key.append(temp_path) + elif type(v) == dict: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + f_key += find_attribute_in_body(v, temp_path) + elif type(v) == list: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + for i, val in enumerate(v): + f_key += find_attribute_in_body(val, temp_path + "." + str(i)) + return f_key + + +def vendor_specific_key_n_value(vendor_specific_fields, body): + vendor_specific = {} + for field in vendor_specific_fields: + parts = field.split('.') + tmp_body = body + for part in parts: + if part.isnumeric(): + part = int(part) + v = tmp_body[part] + tmp_body = v + vendor_specific[field] = v + return vendor_specific + +def add_vend_spec_fields(vendor_specific, serviceapidescription_dict): + pattern = re.compile(r'(?>>>>>> Stashed changes publisher_ops = Publisher() @@ -105,11 +110,10 @@ class PublishServiceOperations(Resource): rec['apf_id'] = apf_id rec['onboarding_date'] = datetime.now() 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] + serviceapidescription_dict = add_vend_spec_fields(vendor_specific, serviceapidescription_dict) + rec.update(serviceapidescription_dict) mycol.insert_one(rec) 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 d6a514e..945060f 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 @@ -95,19 +95,21 @@ class ServiceAPIDescription(Model): @classmethod def return_supp_feat_dict(cls, supp_feat): + TOTAL_FEATURES = 9 supp_feat_in_hex = int(supp_feat, 16) - supp_feat_in_bin = bin(supp_feat_in_hex)[2:] + supp_feat_in_bin = bin(supp_feat_in_hex)[2:].zfill(TOTAL_FEATURES)[::-1] + 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, + "ApiSupportedFeaturePublishing": True if supp_feat_in_bin[0] == "1" else False, + "PatchUpdate": True if supp_feat_in_bin[1] == "1" else False, + "ExtendedIntfDesc": True if supp_feat_in_bin[2] == "1" else False, + "MultipleCustomOperations": 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, + "ApiStatusMonitoring": True if supp_feat_in_bin[5] == "1" else False, + "EdgeApp_2": True if supp_feat_in_bin[6] == "1" else False, + "RNAA": True if supp_feat_in_bin[7] == "1" else False, + "VendorExt": True if supp_feat_in_bin[8] == "1" else False } @classmethod diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/vendor_specific.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/vendor_specific.py new file mode 100644 index 0000000..2bd2aab --- /dev/null +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/vendor_specific.py @@ -0,0 +1,55 @@ +import re + +def find_attribute_in_body(test, path): + f_key = [] + if type(test) == dict: + for k, v in test.items(): + if 'vendorSpecific' in k: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + f_key.append(temp_path) + elif type(v) == dict: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + f_key += find_attribute_in_body(v, temp_path) + elif type(v) == list: + if path == '': + temp_path = k + else: + temp_path = path + "." + k + for i, val in enumerate(v): + f_key += find_attribute_in_body(val, temp_path + "." + str(i)) + return f_key + + +def vendor_specific_key_n_value(vendor_specific_fields, body): + vendor_specific = {} + for field in vendor_specific_fields: + parts = field.split('.') + tmp_body = body + for part in parts: + if part.isnumeric(): + part = int(part) + v = tmp_body[part] + tmp_body = v + vendor_specific[field] = v + return vendor_specific + +def add_vend_spec_fields(vendor_specific, serviceapidescription_dict): + pattern = re.compile(r'(? Date: Wed, 20 Nov 2024 14:25:48 +0200 Subject: [PATCH 2/6] fix merge conflict --- .../published_apis/core/serviceapidescriptions.py | 3 --- 1 file changed, 3 deletions(-) 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 40f8219..80ba9e1 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,14 +9,11 @@ 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 -<<<<<<< Updated upstream from ..models.service_api_description import ServiceAPIDescription import json from ..encoder import CustomJSONEncoder -======= from ..vendor_specific import add_vend_spec_fields ->>>>>>> Stashed changes publisher_ops = Publisher() -- GitLab From b8e665021928af1a3defe9a49b6d9750976174df Mon Sep 17 00:00:00 2001 From: Stavros-Anastasios Charismiadis Date: Wed, 20 Nov 2024 15:10:02 +0200 Subject: [PATCH 3/6] take into consideration case of vend-spec parameter not existing in target --- .../service_apis/core/discoveredapis.py | 4 +++- .../service_apis/vendor_specific.py | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) 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 37c113e..6ab0c45 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 @@ -58,7 +58,9 @@ class DiscoverApisOperations(Resource): for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if vend_spec_query_params_n_values and vendor_specific_fields_path: - json_docs.append(filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path)) + vs_filtered_apis = filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path) + if vs_filtered_apis: + json_docs.append(vs_filtered_apis) else: json_docs.append(discoved_api) diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py index 84e8c36..d30faf3 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py @@ -69,8 +69,7 @@ def filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params v_2 = tmp_body[path_piece] tmp_body = v_2 # Check if parameter exists in the field attributes!!!! - if tmp_body[vs_field][parts[1]] == v: - json_docs.append(discoved_api) - else: - continue + if parts[1] in tmp_body[vs_field].keys(): + if tmp_body[vs_field][parts[1]] == v: + json_docs.append(discoved_api) return json_docs \ No newline at end of file -- GitLab From 4bb65e7829f78ba521a06e11d0c69697b8cb2be9 Mon Sep 17 00:00:00 2001 From: Stavros-Anastasios Charismiadis Date: Thu, 21 Nov 2024 17:41:44 +0200 Subject: [PATCH 4/6] substitute mongo projection in Discover with dictionary filtering --- .../service_apis/core/discoveredapis.py | 18 ++++++++++++++++-- .../service_apis/vendor_specific.py | 10 +++++----- 2 files changed, 21 insertions(+), 7 deletions(-) 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 6ab0c45..f406a1e 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 @@ -8,6 +8,18 @@ import json from ..vendor_specific import find_attribute_in_body, filter_apis_with_vendor_specific_params +def filter_fields(vs_filtered_apis): + key_filter = [ + "api_name", "api_id", "aef_profiles", "description", + "supported_features", "shareable_info", "service_api_category", + "api_supp_feats", "pub_api_path", "ccf_id" + ] + field_filtered_api = {} + for key in vs_filtered_apis.keys(): + if key in key_filter or 'vendorSpecific' in key: + field_filtered_api[key] = vs_filtered_apis[key] + return field_filtered_api + class DiscoverApisOperations(Resource): def get_discoveredapis(self, api_invoker_id, query_params): @@ -56,17 +68,19 @@ class DiscoverApisOperations(Resource): discoved_apis = services.find(my_query, {"_id":0}) json_docs = [] for discoved_api in discoved_apis: + current_app.logger.debug(discoved_api) vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if vend_spec_query_params_n_values and vendor_specific_fields_path: vs_filtered_apis = filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path) if vs_filtered_apis: - json_docs.append(vs_filtered_apis) + json_docs.append(filter_fields(vs_filtered_apis)) else: - json_docs.append(discoved_api) + json_docs.append(filter_fields(discoved_api)) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") + apis_discovered = DiscoveredAPIs(service_api_descriptions=json_docs) res = make_response(object=serialize_clean_camel_case(apis_discovered), status=200) return res diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py index d30faf3..0bb9553 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py @@ -55,7 +55,6 @@ def add_vend_spec_fields(vendor_specific, serviceapidescription_dict): return tmp_body def filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path): - json_docs = [] for k, v in vend_spec_query_params_n_values.items(): parts = k.split('.') for path in vendor_specific_fields_path: @@ -68,8 +67,9 @@ def filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params path_piece = int(path_piece) v_2 = tmp_body[path_piece] tmp_body = v_2 - # Check if parameter exists in the field attributes!!!! if parts[1] in tmp_body[vs_field].keys(): - if tmp_body[vs_field][parts[1]] == v: - json_docs.append(discoved_api) - return json_docs \ No newline at end of file + if tmp_body[vs_field][parts[1]] != v: + return {} + else: + return {} + return discoved_api \ No newline at end of file -- GitLab From 2f4ee34246071cd9b0387413d4d39ac06fc01784 Mon Sep 17 00:00:00 2001 From: Stavros-Anastasios Charismiadis Date: Thu, 28 Nov 2024 11:54:30 +0200 Subject: [PATCH 5/6] Add case where vend-ext feature is disabled in the supp-feat --- .../service_apis/core/discoveredapis.py | 5 +++++ 1 file changed, 5 insertions(+) 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 e7bd8a7..d82e8c7 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 @@ -87,6 +87,11 @@ class DiscoverApisOperations(Resource): json_docs.append(filter_fields(vs_filtered_apis)) else: json_docs.append(filter_fields(discoved_api)) + else: + for discoved_api in discoved_apis: + vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') + if not vendor_specific_fields_path: + json_docs.append(filter_fields(discoved_api)) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") -- GitLab From fa32f64f0e2f3dab78418e85dc906ed3a49ce454 Mon Sep 17 00:00:00 2001 From: Stavros Date: Thu, 28 Nov 2024 17:47:32 +0200 Subject: [PATCH 6/6] Add filtering in case with no supp-feat --- .../service_apis/core/discoveredapis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d82e8c7..8ac986a 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 @@ -74,7 +74,7 @@ class DiscoverApisOperations(Resource): if supp_feat is None: for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') - json_docs.append(remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path)) + json_docs.append(filter_fields(remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path))) else: supported_features = DiscoveredAPIs.return_supp_feat_dict(supp_feat) if supported_features['VendSpecQueryParams']: -- GitLab