Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +22 −0 Original line number Diff line number Diff line Loading @@ -103,9 +103,31 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t """ current_app.logger.debug("Discovering service apis") if net_slice_info is None: if "net-slice-info" in request.args: raw_net_slice_info = request.args.get("net-slice-info") try: net_slice_info = json.loads(raw_net_slice_info) except (json.JSONDecodeError, TypeError) as e: current_app.logger.warning( "Failed to parse net-slice-info query parameter: %s. Raw value: %s", str(e), raw_net_slice_info ) elif "net-slice-info.snssai.sst" in request.args: net_slice_info = [{ "snssai": { "sst": int(request.args.get("net-slice-info.snssai.sst")), "sd": request.args.get("net-slice-info.snssai.sd") } }] current_app.logger.debug("Parsed dotted net-slice-info: %s", net_slice_info) 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, "net_slice_info": net_slice_info, "supported_features": supported_features} if supported_features is not None: Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +80 −2 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import json from flask import current_app from ..core.resources import Resource from ..core.responses import (internal_server_error, make_response, from ..core.responses import (bad_request_error, internal_server_error, make_response, not_found_error) from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case Loading @@ -16,6 +16,10 @@ TOTAL_FEATURES = 4 SUPPORTED_FEATURES_HEX = "2" class NetSliceInfoValidationError(Exception): pass def filter_fields(filtered_apis): key_filter = [ "api_name", "api_id", "aef_profiles", "description", Loading @@ -41,6 +45,68 @@ def return_negotiated_supp_feat_dict(supp_feat): } def _normalize_net_slice_info(net_slice_info): if net_slice_info is None: return [] if isinstance(net_slice_info, str): try: net_slice_info = json.loads(net_slice_info) except json.JSONDecodeError: return [] if isinstance(net_slice_info, dict): net_slice_info = [net_slice_info] normalized = [] for net_slice in net_slice_info: if isinstance(net_slice, dict): normalized.append(net_slice) elif hasattr(net_slice, "to_dict"): normalized.append(net_slice.to_dict()) return normalized def _build_net_slice_info_query(net_slice_info): normalized = _normalize_net_slice_info(net_slice_info) if not normalized: return None net_slice_elem_matches = [] for net_slice in normalized: elem_match = {} if net_slice.get("nsi_id") is not None: elem_match["nsi_id"] = net_slice["nsi_id"] elif net_slice.get("nsiId") is not None: elem_match["nsi_id"] = net_slice["nsiId"] if net_slice.get("ensi") is not None: elem_match["ensi"] = net_slice["ensi"] snssai = net_slice.get("snssai") if isinstance(snssai, dict): if snssai.get("sd") is not None and snssai.get("sst") is None: raise NetSliceInfoValidationError("snssai.sd requires snssai.sst") snssai_match = {} if snssai.get("sst") is not None: snssai_match["sst"] = snssai["sst"] if snssai.get("sd") is not None: snssai_match["sd"] = snssai["sd"] if snssai_match: elem_match["snssai"] = snssai_match if elem_match: net_slice_elem_matches.append({"net_slice_info": {"$elemMatch": elem_match}}) if not net_slice_elem_matches: return None return {"$or": net_slice_elem_matches} class DiscoverApisOperations(Resource): def get_discoveredapis(self, api_invoker_id, query_params): Loading Loading @@ -68,7 +134,8 @@ class DiscoverApisOperations(Resource): "data_format": '{"aef_profiles": {"$elemMatch": {"data_format":"QPV"}}}', "api_cat": "service_api_category", "supported_features": "supported_features", "api_supported_features": "api_supp_feats" "api_supported_features": "api_supp_feats", "net_slice_info": "net_slice_info" } vend_spec_query_params_n_values = {} Loading @@ -81,6 +148,10 @@ class DiscoverApisOperations(Resource): vend_param = param.split("vend-spec-")[1] attribute_path = query_params[param]["target"].split('/') vend_spec_query_params_n_values[".".join(attribute_path[1:]) + "." + vend_param] = query_params[param]["value"] elif param == "net_slice_info": net_slice_info_query = _build_net_slice_info_query(query_params[param]) if net_slice_info_query is not None: my_params.append(net_slice_info_query) elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]: my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param]))) else: Loading Loading @@ -121,6 +192,13 @@ class DiscoverApisOperations(Resource): res = make_response(object=serialize_clean_camel_case(apis_discovered), status=200) return res except NetSliceInfoValidationError as e: return bad_request_error( detail="Invalid net-slice-info query parameter", cause=str(e), invalid_params=[{"param": "net-slice-info", "reason": str(e)}] ) except Exception as e: exception = "An exception occurred in discover services" current_app.logger.error(exception + "::" + str(e)) Loading Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +22 −0 Original line number Diff line number Diff line Loading @@ -103,9 +103,31 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t """ current_app.logger.debug("Discovering service apis") if net_slice_info is None: if "net-slice-info" in request.args: raw_net_slice_info = request.args.get("net-slice-info") try: net_slice_info = json.loads(raw_net_slice_info) except (json.JSONDecodeError, TypeError) as e: current_app.logger.warning( "Failed to parse net-slice-info query parameter: %s. Raw value: %s", str(e), raw_net_slice_info ) elif "net-slice-info.snssai.sst" in request.args: net_slice_info = [{ "snssai": { "sst": int(request.args.get("net-slice-info.snssai.sst")), "sd": request.args.get("net-slice-info.snssai.sd") } }] current_app.logger.debug("Parsed dotted net-slice-info: %s", net_slice_info) 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, "net_slice_info": net_slice_info, "supported_features": supported_features} if supported_features is not None: Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +80 −2 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import json from flask import current_app from ..core.resources import Resource from ..core.responses import (internal_server_error, make_response, from ..core.responses import (bad_request_error, internal_server_error, make_response, not_found_error) from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case Loading @@ -16,6 +16,10 @@ TOTAL_FEATURES = 4 SUPPORTED_FEATURES_HEX = "2" class NetSliceInfoValidationError(Exception): pass def filter_fields(filtered_apis): key_filter = [ "api_name", "api_id", "aef_profiles", "description", Loading @@ -41,6 +45,68 @@ def return_negotiated_supp_feat_dict(supp_feat): } def _normalize_net_slice_info(net_slice_info): if net_slice_info is None: return [] if isinstance(net_slice_info, str): try: net_slice_info = json.loads(net_slice_info) except json.JSONDecodeError: return [] if isinstance(net_slice_info, dict): net_slice_info = [net_slice_info] normalized = [] for net_slice in net_slice_info: if isinstance(net_slice, dict): normalized.append(net_slice) elif hasattr(net_slice, "to_dict"): normalized.append(net_slice.to_dict()) return normalized def _build_net_slice_info_query(net_slice_info): normalized = _normalize_net_slice_info(net_slice_info) if not normalized: return None net_slice_elem_matches = [] for net_slice in normalized: elem_match = {} if net_slice.get("nsi_id") is not None: elem_match["nsi_id"] = net_slice["nsi_id"] elif net_slice.get("nsiId") is not None: elem_match["nsi_id"] = net_slice["nsiId"] if net_slice.get("ensi") is not None: elem_match["ensi"] = net_slice["ensi"] snssai = net_slice.get("snssai") if isinstance(snssai, dict): if snssai.get("sd") is not None and snssai.get("sst") is None: raise NetSliceInfoValidationError("snssai.sd requires snssai.sst") snssai_match = {} if snssai.get("sst") is not None: snssai_match["sst"] = snssai["sst"] if snssai.get("sd") is not None: snssai_match["sd"] = snssai["sd"] if snssai_match: elem_match["snssai"] = snssai_match if elem_match: net_slice_elem_matches.append({"net_slice_info": {"$elemMatch": elem_match}}) if not net_slice_elem_matches: return None return {"$or": net_slice_elem_matches} class DiscoverApisOperations(Resource): def get_discoveredapis(self, api_invoker_id, query_params): Loading Loading @@ -68,7 +134,8 @@ class DiscoverApisOperations(Resource): "data_format": '{"aef_profiles": {"$elemMatch": {"data_format":"QPV"}}}', "api_cat": "service_api_category", "supported_features": "supported_features", "api_supported_features": "api_supp_feats" "api_supported_features": "api_supp_feats", "net_slice_info": "net_slice_info" } vend_spec_query_params_n_values = {} Loading @@ -81,6 +148,10 @@ class DiscoverApisOperations(Resource): vend_param = param.split("vend-spec-")[1] attribute_path = query_params[param]["target"].split('/') vend_spec_query_params_n_values[".".join(attribute_path[1:]) + "." + vend_param] = query_params[param]["value"] elif param == "net_slice_info": net_slice_info_query = _build_net_slice_info_query(query_params[param]) if net_slice_info_query is not None: my_params.append(net_slice_info_query) elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]: my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param]))) else: Loading Loading @@ -121,6 +192,13 @@ class DiscoverApisOperations(Resource): res = make_response(object=serialize_clean_camel_case(apis_discovered), status=200) return res except NetSliceInfoValidationError as e: return bad_request_error( detail="Invalid net-slice-info query parameter", cause=str(e), invalid_params=[{"param": "net-slice-info", "reason": str(e)}] ) except Exception as e: exception = "An exception occurred in discover services" current_app.logger.error(exception + "::" + str(e)) Loading