From 2658576d80c8f2f2e9e729a2a2aef30d3f271170 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 18:37:19 +0300 Subject: [PATCH 01/20] new SDK class responsible for onboarding Exposers to CAPIF --- evolved5g/cli_helper.py | 32 ++-- evolved5g/sdk.py | 173 ++++++++++++++++-- examples/capif_connector_examples.py | 39 ---- .../api_provider_domain.json | 17 ++ .../service_api_description.json | 63 +++++++ examples/nef_capif_connector_examples.py | 31 ++++ examples/netapp_capif_connector_examples.py | 39 ++++ 7 files changed, 326 insertions(+), 68 deletions(-) delete mode 100644 examples/capif_connector_examples.py create mode 100644 examples/capif_exposer_sample_files/api_provider_domain.json create mode 100644 examples/capif_exposer_sample_files/service_api_description.json create mode 100644 examples/nef_capif_connector_examples.py create mode 100644 examples/netapp_capif_connector_examples.py diff --git a/evolved5g/cli_helper.py b/evolved5g/cli_helper.py index 8d09ef5..188722e 100644 --- a/evolved5g/cli_helper.py +++ b/evolved5g/cli_helper.py @@ -4,7 +4,7 @@ import json.decoder import logging from click import echo -from evolved5g.sdk import CAPIFConnector +from evolved5g.sdk import CAPIFInvokerConnector import traceback class CLI_helper: @@ -115,21 +115,21 @@ def register_and_onboard_to_capif(self, folder_to_store_certificates: str, csr_country_name, csr_email_address)->None: - capif_connector = CAPIFConnector(folder_to_store_certificates, - capif_host, - capif_http_port, - capif_https_port, - capif_netapp_username, - capif_netapp_password, - capif_callback_url, - description, - csr_common_name, - csr_organizational_unit, - csr_organization, - crs_locality, - csr_state_or_province_name, - csr_country_name, - csr_email_address) + capif_connector = CAPIFInvokerConnector(folder_to_store_certificates, + capif_host, + capif_http_port, + capif_https_port, + capif_netapp_username, + capif_netapp_password, + capif_callback_url, + description, + csr_common_name, + csr_organizational_unit, + csr_organization, + crs_locality, + csr_state_or_province_name, + csr_country_name, + csr_email_address) try: capif_connector.register_and_onboard_netapp() echo("Your netApp has been successfully registered and onboarded to the CAPIF server." + diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 94f8e63..cdf22f5 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -687,9 +687,9 @@ def delete_subscription(self, netapp_id: str, subscription_id: str): subscription_id) -class CAPIFConnector: +class CAPIFInvokerConnector: """ - Τhis class is responsbile for onboarding to CAPIF + Τhis class is responsbile for onboarding an Invoker (ex. a NetApp) to CAPIF """ def __init__(self, @@ -757,15 +757,14 @@ def register_and_onboard_netapp(self)->None: """ public_key =self._create_private_and_public_keys() - - net_app_id,capif_onboarding_url,capif_discover_url = self._register_netapp_to_capif() - - capif_access_token = self._save_capif_ca_root_file_and_get_auth_token() - + role = "invoker" + registration_result = self._register_to_capif(role) + capif_onboarding_url = registration_result['ccf_onboarding_url'] + capif_discover_url = registration_result['ccf_discover_url'] + capif_access_token = self._save_capif_ca_root_file_and_get_auth_token(role) api_invoker_id= self._onboard_netapp_to_capif_and_create_the_signed_certificate(public_key, capif_onboarding_url, capif_access_token) - self._write_to_file(self.csr_common_name,api_invoker_id,capif_discover_url) def _create_private_and_public_keys(self)->str: @@ -800,13 +799,13 @@ def _create_private_and_public_keys(self)->str: return public_key - def _register_netapp_to_capif(self): + def _register_to_capif(self, role): url = self.capif_http_url + "register" payload = dict() payload['username'] = self.capif_netapp_username payload['password'] = self.capif_netapp_password - payload['role'] = "invoker" + payload['role'] = role payload['description'] = self.description payload['cn'] = self.csr_common_name @@ -817,16 +816,16 @@ def _register_netapp_to_capif(self): response.raise_for_status() response_payload = json.loads(response.text) - return response_payload['id'], response_payload['ccf_onboarding_url'], response_payload['ccf_discover_url'], + return response_payload - def _save_capif_ca_root_file_and_get_auth_token(self): + def _save_capif_ca_root_file_and_get_auth_token(self,role): url = self.capif_http_url + "getauth" payload = dict() payload['username'] = self.capif_netapp_username payload['password'] = self.capif_netapp_password - payload['role'] = "invoker" + payload['role'] = role response = requests.request("POST", url, @@ -879,6 +878,154 @@ def _write_to_file(self,csr_common_name, api_invoker_id, discover_services_url): }, outfile) +class CAPIFExposerConnector: + """ + Τhis class is responsible for onboarding an exposer (eg. NEF emulator) to CAPIF + """ + + def __init__(self, + certificates_folder: str, + description: str, + common_name: str, + capif_host: str, + capif_http_port: str, + capif_https_port: str, + capif_netapp_username, + capif_netapp_password: str, + ): + """ + :param certificates_folder: The folder where certificates will be stores. Your own certificate, + along with the certificate root that will be retrieved by the CAPIF server + :param capif_host: + :param capif_http_port: + :param capif_https_port: + :param capif_netapp_username: The CAPIF username of your netapp + :param capif_netapp_password: The CAPIF password of your netapp + """ + # add the trailing slash if it is not already there using os.path.join + self.certificates_folder = os.path.join(certificates_folder.strip(), '') + self.description= description + self.common_name= common_name + self.capif_http_url = "http://" + capif_host.strip() + ":" + capif_http_port.strip() + "/" + self.capif_https_url = "https://" + capif_host.strip() + ":" + capif_https_port.strip() + "/" + self.capif_netapp_username = capif_netapp_username + self.capif_netapp_password = capif_netapp_password + + def _store_certificate_authority_file(self): + url = self.capif_http_url + "ca-root" + response = requests.request("POST", url, + headers={'Content-Type': 'application/json'}) + response.raise_for_status() + response_payload = json.loads(response.text) + with open(self.certificates_folder + 'ca.crt', 'wb+') as ca_root: + ca_root.write(bytes(response_payload['certificate'], 'utf-8')) + + + + def _onboard_exposer_to_capif(self, + api_provider_domain_json_full_path, + capif_onboarding_url, cert): + url = self.capif_https_url + capif_onboarding_url + with open(api_provider_domain_json_full_path + 'api_provider_domain.json') as json_file: + payload = json.load(json_file) + payload["regSec"] = cert + + headers = { + 'Content-Type': 'application/json' + } + + response = requests.request("POST", + url, + headers=headers, + data=json.dumps(payload), + cert=(self.certificates_folder+'exposer.crt', + self.certificates_folder + 'private.key'), + verify= self.certificates_folder+'ca.crt') + + response.raise_for_status() + response_payload = json.loads(response.text) + + return response_payload['apiProvDomId'] + + def _register_to_capif(self, role): + + url = self.capif_http_url + "register" + payload = dict() + payload['username'] = self.capif_netapp_username + payload['password'] = self.capif_netapp_password + payload['role'] = role + payload['description'] = self.description + payload['cn'] = self.common_name + + response = requests.request("POST", + url, + headers={'Content-Type': 'application/json'}, + data=json.dumps(payload)) + response.raise_for_status() + + response_payload = json.loads(response.text) + return response_payload + + def _perform_authorization_and_store_ssl_keys(self,role): + + url = self.capif_http_url + "getauth" + + payload = dict() + payload['username'] = self.capif_netapp_username + payload['password'] = self.capif_netapp_password + payload['role'] = role + + response = requests.request("POST", + url, + headers={'Content-Type': 'application/json' }, + data=json.dumps(payload)) + response.raise_for_status() + response_payload = json.loads(response.text) + + with open(self.certificates_folder + 'exposer.crt', 'wb+') as certification_file: + certification_file.write(bytes(response_payload['cert'], 'utf-8')) + + with open(self.certificates_folder + "private.key", 'wb+') as private_key_file: + private_key_file.write(bytes(response_payload['private_key'], 'utf-8')) + + return response_payload['cert'] + + def _write_to_file(self,publish_url): + with open(self.certificates_folder + "capif_exposer_details.json", "w") as outfile: + json.dump({ + "publish_url": publish_url + }, outfile) + + def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None: + role = "exposer" + self._store_certificate_authority_file() + registration_result = self._register_to_capif(role) + ccf_publish_url = registration_result['ccf_publish_url'] + capif_onboarding_url = registration_result['ccf_api_onboarding_url'] + cert = self._perform_authorization_and_store_ssl_keys(role) + api_prov_dom_id = self._onboard_exposer_to_capif(api_provider_domain_json_full_path,capif_onboarding_url, cert) + self._write_to_file(ccf_publish_url) + + def publish_services(self,service_api_description_json_full_path)->None: + + with open(self.certificates_folder + "capif_exposer_details.json", 'r') as openfile: + publish_url = json.load(openfile)["publish_url"] + + url = self.capif_https_url + publish_url + + with open(service_api_description_json_full_path, 'rb') as payload: + response = requests.request("POST", + url, + headers={'Content-Type': 'application/json'}, + data=payload, + cert=(self.certificates_folder + 'exposer.crt', + self.certificates_folder + 'private.key'), + verify=self.certificates_folder+'ca.crt') + response.raise_for_status() + response_payload = json.loads(response.text) + return response_payload["apiId"] + + class ServiceDiscoverer: def __init__(self, folder_path_for_certificates_and_api_key: str, diff --git a/examples/capif_connector_examples.py b/examples/capif_connector_examples.py deleted file mode 100644 index 00a8e19..0000000 --- a/examples/capif_connector_examples.py +++ /dev/null @@ -1,39 +0,0 @@ -from evolved5g.sdk import CAPIFConnector, ServiceDiscoverer - - -def showcase_capif_connector(): - """ - This method showcases how one can use the CAPIFConnector class. - This class is intended for use within the evolved5G Command Line interface. - It is a low level class part of the SDK that is not required to use while creating NetApps - """ - capif_connector = CAPIFConnector(folder_to_store_certificates= "/home/alex/Projects/test_certificate_folder", - capif_host="capifcore", - capif_http_port="8080", - capif_https_port="443", - capif_netapp_username="test_netapp20", - capif_netapp_password="test_netapp_password", - capif_callback_url="http://localhost:5000", - description= "test_app_description", - csr_common_name="test_app_common_name", - csr_organizational_unit="test_app_ou", - csr_organization="test_app_o", - crs_locality="Madrid", - csr_state_or_province_name="Madrid", - csr_country_name="ES", - csr_email_address="test@example.com" - ) - - capif_connector.register_and_onboard_netapp() - -def showcase_service_discovery(): - service_discoverer = ServiceDiscoverer(folder_path_for_certificates_and_api_key="/home/alex/Projects/test_certificate_folder", - capif_host="capifcore", - capif_https_port=443 - ) - endpoints = service_discoverer.discover_service_apis() - print(endpoints) - -if __name__ == "__main__": - showcase_capif_connector() - showcase_service_discovery() diff --git a/examples/capif_exposer_sample_files/api_provider_domain.json b/examples/capif_exposer_sample_files/api_provider_domain.json new file mode 100644 index 0000000..5e441e9 --- /dev/null +++ b/examples/capif_exposer_sample_files/api_provider_domain.json @@ -0,0 +1,17 @@ +{ + "regSec": "LEAVE_THIS_AS_EMPTY_IT_WILL_BE_AUTOMATICALLY_SET_DURING_CAPIF_REGISTRATION", + "apiProvFuncs": [ + { + "apiProvFuncId": "string_2", + "regInfo": { + "apiProvPubKey": "string", + "apiProvCert": "string" + }, + "apiProvFuncRole": "AEF", + "apiProvFuncInfo": "string" + } + ], + "apiProvDomInfo": "string", + "suppFeat": "fff", + "failReason": "string" + } diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json new file mode 100644 index 0000000..dc9bb88 --- /dev/null +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -0,0 +1,63 @@ + +{ + "apiName": "dummy-aef", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "hello-endpoint", + "commType": "REQUEST_RESPONSE", + "uri": "/hello", + "custOpName": "string", + "operations": [ + "POST" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "POST" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["Oauth", "PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "python_aef", + "port": 8086, + "securityMethods": ["Oauth"] + } + ] + } + ], + "description": "API of dummy netapp to test", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" + } \ No newline at end of file diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py new file mode 100644 index 0000000..68a913e --- /dev/null +++ b/examples/nef_capif_connector_examples.py @@ -0,0 +1,31 @@ +from evolved5g.sdk import CAPIFInvokerConnector, ServiceDiscoverer + + +def showcase_capif_connector(): + """ + This method showcases how one can use the CAPIFConnector class. + This class is intended for use within the evolved5G Command Line interface. + It is a low level class part of the SDK that is not required to use while creating NetApps + """ + capif_connector = CAPIFInvokerConnector(folder_to_store_certificates="/home/alex/Projects/test_certificate_folder", + capif_host="capifcore", + capif_http_port="8080", + capif_https_port="443", + capif_netapp_username="test_netapp20", + capif_netapp_password="test_netapp_password", + capif_callback_url="http://localhost:5000", + description= "test_app_description", + csr_common_name="test_app_common_name", + csr_organizational_unit="test_app_ou", + csr_organization="test_app_o", + crs_locality="Madrid", + csr_state_or_province_name="Madrid", + csr_country_name="ES", + csr_email_address="test@example.com" + ) + + capif_connector.register_and_onboard_netapp() + + +if __name__ == "__main__": + showcase_capif_connector() diff --git a/examples/netapp_capif_connector_examples.py b/examples/netapp_capif_connector_examples.py new file mode 100644 index 0000000..3ef4a91 --- /dev/null +++ b/examples/netapp_capif_connector_examples.py @@ -0,0 +1,39 @@ +from evolved5g.sdk import CAPIFInvokerConnector, ServiceDiscoverer + + +def showcase_capif_connector(): + """ + This method showcases how one can use the CAPIFConnector class. + This class is intended for use within the evolved5G Command Line interface. + It is a low level class part of the SDK that is not required to use while creating NetApps + """ + capif_connector = CAPIFInvokerConnector(folder_to_store_certificates="/home/alex/Projects/test_certificate_folder", + capif_host="capifcore", + capif_http_port="8080", + capif_https_port="443", + capif_netapp_username="test_netapp20", + capif_netapp_password="test_netapp_password", + capif_callback_url="http://localhost:5000", + description= "test_app_description", + csr_common_name="test_app_common_name", + csr_organizational_unit="test_app_ou", + csr_organization="test_app_o", + crs_locality="Madrid", + csr_state_or_province_name="Madrid", + csr_country_name="ES", + csr_email_address="test@example.com" + ) + + capif_connector.register_and_onboard_netapp() + +def showcase_service_discovery(): + service_discoverer = ServiceDiscoverer(folder_path_for_certificates_and_api_key="/home/alex/Projects/test_certificate_folder", + capif_host="capifcore", + capif_https_port=443 + ) + endpoints = service_discoverer.discover_service_apis() + print(endpoints) + +if __name__ == "__main__": + showcase_capif_connector() + showcase_service_discovery() From baaa80f324150acd4080abfbac3227fe2c3e074b Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 19:00:35 +0300 Subject: [PATCH 02/20] bug fixes on CAPIFExposesConnector --- evolved5g/sdk.py | 54 ++++++++++++------------ examples/nef_capif_connector_examples.py | 31 ++++++-------- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index cdf22f5..61d8922 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -730,7 +730,7 @@ def __init__(self, self.folder_to_store_certificates = os.path.join(folder_to_store_certificates.strip(), '') self.capif_http_url = "http://" + capif_host.strip() + ":" + capif_http_port.strip() + "/" self.capif_https_url = "https://" + capif_host.strip() + ":" + capif_https_port.strip() + "/" - self.capif_callback_url = self._add_trailing_slash_to_url_if_missing(capif_callback_url.strip()) + self.capif_callback_url = self.__add_trailing_slash_to_url_if_missing(capif_callback_url.strip()) self.capif_netapp_username = capif_netapp_username self.capif_netapp_password = capif_netapp_password self.description =description @@ -742,7 +742,7 @@ def __init__(self, self.csr_country_name = csr_country_name self.csr_email_address = csr_email_address - def _add_trailing_slash_to_url_if_missing(self, url): + def __add_trailing_slash_to_url_if_missing(self, url): if url[len(url) - 1] != "/": url = url + "/" return url @@ -756,18 +756,18 @@ def register_and_onboard_netapp(self)->None: These will be used ServiceDiscoverer class in order to communicate with CAPIF and discover services """ - public_key =self._create_private_and_public_keys() + public_key =self.__create_private_and_public_keys() role = "invoker" - registration_result = self._register_to_capif(role) + registration_result = self.__register_to_capif(role) capif_onboarding_url = registration_result['ccf_onboarding_url'] capif_discover_url = registration_result['ccf_discover_url'] - capif_access_token = self._save_capif_ca_root_file_and_get_auth_token(role) - api_invoker_id= self._onboard_netapp_to_capif_and_create_the_signed_certificate(public_key, - capif_onboarding_url, - capif_access_token) - self._write_to_file(self.csr_common_name,api_invoker_id,capif_discover_url) + capif_access_token = self.__save_capif_ca_root_file_and_get_auth_token(role) + api_invoker_id= self.__onboard_netapp_to_capif_and_create_the_signed_certificate(public_key, + capif_onboarding_url, + capif_access_token) + self.__write_to_file(self.csr_common_name, api_invoker_id, capif_discover_url) - def _create_private_and_public_keys(self)->str: + def __create_private_and_public_keys(self)->str: """ Creates 2 keys in folder folder_to_store_certificates. A private.key and a cert_req.csr. :return: The contents of the public key @@ -799,7 +799,7 @@ def _create_private_and_public_keys(self)->str: return public_key - def _register_to_capif(self, role): + def __register_to_capif(self, role): url = self.capif_http_url + "register" payload = dict() @@ -818,7 +818,7 @@ def _register_to_capif(self, role): response_payload = json.loads(response.text) return response_payload - def _save_capif_ca_root_file_and_get_auth_token(self,role): + def __save_capif_ca_root_file_and_get_auth_token(self, role): url = self.capif_http_url + "getauth" @@ -837,7 +837,7 @@ def _save_capif_ca_root_file_and_get_auth_token(self,role): ca_root_file.write(bytes(response_payload['ca_root'], 'utf-8')) return response_payload['access_token'] - def _onboard_netapp_to_capif_and_create_the_signed_certificate(self, public_key, capif_onboarding_url,capif_access_token): + def __onboard_netapp_to_capif_and_create_the_signed_certificate(self, public_key, capif_onboarding_url, capif_access_token): url = self.capif_https_url + capif_onboarding_url payload_dict = { "notificationDestination": self.capif_callback_url, @@ -869,7 +869,7 @@ def _onboard_netapp_to_capif_and_create_the_signed_certificate(self, public_key, certification_file.close() return response_payload['apiInvokerId'] - def _write_to_file(self,csr_common_name, api_invoker_id, discover_services_url): + def __write_to_file(self, csr_common_name, api_invoker_id, discover_services_url): with open(self.folder_to_store_certificates + "capif_api_details.json", "w") as outfile: json.dump({ "csr_common_name": csr_common_name, @@ -911,9 +911,9 @@ def __init__(self, self.capif_netapp_username = capif_netapp_username self.capif_netapp_password = capif_netapp_password - def _store_certificate_authority_file(self): + def __store_certificate_authority_file(self): url = self.capif_http_url + "ca-root" - response = requests.request("POST", url, + response = requests.request("GET", url, headers={'Content-Type': 'application/json'}) response.raise_for_status() response_payload = json.loads(response.text) @@ -922,11 +922,11 @@ def _store_certificate_authority_file(self): - def _onboard_exposer_to_capif(self, - api_provider_domain_json_full_path, - capif_onboarding_url, cert): + def __onboard_exposer_to_capif(self, + api_provider_domain_json_full_path, + capif_onboarding_url, cert): url = self.capif_https_url + capif_onboarding_url - with open(api_provider_domain_json_full_path + 'api_provider_domain.json') as json_file: + with open(api_provider_domain_json_full_path) as json_file: payload = json.load(json_file) payload["regSec"] = cert @@ -947,7 +947,7 @@ def _onboard_exposer_to_capif(self, return response_payload['apiProvDomId'] - def _register_to_capif(self, role): + def __register_to_capif(self, role): url = self.capif_http_url + "register" payload = dict() @@ -966,7 +966,7 @@ def _register_to_capif(self, role): response_payload = json.loads(response.text) return response_payload - def _perform_authorization_and_store_ssl_keys(self,role): + def __perform_authorization_and_store_ssl_keys(self, role): url = self.capif_http_url + "getauth" @@ -998,17 +998,17 @@ def _write_to_file(self,publish_url): def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None: role = "exposer" - self._store_certificate_authority_file() - registration_result = self._register_to_capif(role) + self.__store_certificate_authority_file() + registration_result = self.__register_to_capif(role) ccf_publish_url = registration_result['ccf_publish_url'] capif_onboarding_url = registration_result['ccf_api_onboarding_url'] - cert = self._perform_authorization_and_store_ssl_keys(role) - api_prov_dom_id = self._onboard_exposer_to_capif(api_provider_domain_json_full_path,capif_onboarding_url, cert) + cert = self.__perform_authorization_and_store_ssl_keys(role) + api_prov_dom_id = self.__onboard_exposer_to_capif(api_provider_domain_json_full_path, capif_onboarding_url, cert) self._write_to_file(ccf_publish_url) def publish_services(self,service_api_description_json_full_path)->None: - with open(self.certificates_folder + "capif_exposer_details.json", 'r') as openfile: + with open(self.certificates_folder, 'r') as openfile: publish_url = json.load(openfile)["publish_url"] url = self.capif_https_url + publish_url diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 68a913e..aa872dd 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -1,31 +1,26 @@ -from evolved5g.sdk import CAPIFInvokerConnector, ServiceDiscoverer +from evolved5g.sdk import CAPIFExposerConnector - -def showcase_capif_connector(): +def showcase_capif_nef_connector(): """ - This method showcases how one can use the CAPIFConnector class. - This class is intended for use within the evolved5G Command Line interface. - It is a low level class part of the SDK that is not required to use while creating NetApps + """ - capif_connector = CAPIFInvokerConnector(folder_to_store_certificates="/home/alex/Projects/test_certificate_folder", + capif_connector = CAPIFExposerConnector(certificates_folder="/home/alex/Projects/test_nef_certificate_folder/", capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_netapp20", + capif_netapp_username="test_nef05", capif_netapp_password="test_netapp_password", - capif_callback_url="http://localhost:5000", description= "test_app_description", - csr_common_name="test_app_common_name", - csr_organizational_unit="test_app_ou", - csr_organization="test_app_o", - crs_locality="Madrid", - csr_state_or_province_name="Madrid", - csr_country_name="ES", - csr_email_address="test@example.com" + common_name="test_app_common_name" ) - capif_connector.register_and_onboard_netapp() + capif_connector.register_and_onboard_exposer( + api_provider_domain_json_full_path="/home/alex/Projects/test_nef_certificate_folder/api_provider_domain.json" + ) + + capif_connector.publish_services( + service_api_description_json_full_path="/home/alex/Projects/test_nef_certificate_folder/service_api_description.json") if __name__ == "__main__": - showcase_capif_connector() + showcase_capif_nef_connector() From d02af78fc68f83958a74dbe80991cf91305e929c Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 19:32:16 +0300 Subject: [PATCH 03/20] troubleshooting registration --- evolved5g/sdk.py | 12 ++++++------ examples/nef_capif_connector_examples.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 61d8922..9f7fb89 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -886,7 +886,7 @@ class CAPIFExposerConnector: def __init__(self, certificates_folder: str, description: str, - common_name: str, + csr_common_name: str, capif_host: str, capif_http_port: str, capif_https_port: str, @@ -905,7 +905,7 @@ def __init__(self, # add the trailing slash if it is not already there using os.path.join self.certificates_folder = os.path.join(certificates_folder.strip(), '') self.description= description - self.common_name= common_name + self.csr_common_name= csr_common_name self.capif_http_url = "http://" + capif_host.strip() + ":" + capif_http_port.strip() + "/" self.capif_https_url = "https://" + capif_host.strip() + ":" + capif_https_port.strip() + "/" self.capif_netapp_username = capif_netapp_username @@ -938,7 +938,7 @@ def __onboard_exposer_to_capif(self, url, headers=headers, data=json.dumps(payload), - cert=(self.certificates_folder+'exposer.crt', + cert=(self.certificates_folder+ self.csr_common_name+'.crt', self.certificates_folder + 'private.key'), verify= self.certificates_folder+'ca.crt') @@ -955,7 +955,7 @@ def __register_to_capif(self, role): payload['password'] = self.capif_netapp_password payload['role'] = role payload['description'] = self.description - payload['cn'] = self.common_name + payload['cn'] = self.csr_common_name response = requests.request("POST", url, @@ -982,7 +982,7 @@ def __perform_authorization_and_store_ssl_keys(self, role): response.raise_for_status() response_payload = json.loads(response.text) - with open(self.certificates_folder + 'exposer.crt', 'wb+') as certification_file: + with open(self.certificates_folder + self.csr_common_name +'.crt', 'wb+') as certification_file: certification_file.write(bytes(response_payload['cert'], 'utf-8')) with open(self.certificates_folder + "private.key", 'wb+') as private_key_file: @@ -1018,7 +1018,7 @@ def publish_services(self,service_api_description_json_full_path)->None: url, headers={'Content-Type': 'application/json'}, data=payload, - cert=(self.certificates_folder + 'exposer.crt', + cert=(self.certificates_folder + self.csr_common_name +'.crt', self.certificates_folder + 'private.key'), verify=self.certificates_folder+'ca.crt') response.raise_for_status() diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index aa872dd..ed45d56 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,10 +8,10 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef05", + capif_netapp_username="test_nef08", capif_netapp_password="test_netapp_password", description= "test_app_description", - common_name="test_app_common_name" + csr_common_name="test_app_common_name" ) capif_connector.register_and_onboard_exposer( From b19d27054eb4e99570e70425492f5924305b46e7 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 19:39:51 +0300 Subject: [PATCH 04/20] troubleshooting registration --- examples/nef_capif_connector_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index ed45d56..9148c0d 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef08", + capif_netapp_username="test_nef09", capif_netapp_password="test_netapp_password", description= "test_app_description", csr_common_name="test_app_common_name" From 3e467e9e77265aa6ba8fc73f9a0b6122c2db9bab Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 20:03:36 +0300 Subject: [PATCH 05/20] bug fix on registration --- evolved5g/sdk.py | 25 ++++++++++--------- .../service_api_description.json | 2 +- examples/nef_capif_connector_examples.py | 5 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 9f7fb89..30fbc21 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -886,7 +886,6 @@ class CAPIFExposerConnector: def __init__(self, certificates_folder: str, description: str, - csr_common_name: str, capif_host: str, capif_http_port: str, capif_https_port: str, @@ -905,7 +904,7 @@ def __init__(self, # add the trailing slash if it is not already there using os.path.join self.certificates_folder = os.path.join(certificates_folder.strip(), '') self.description= description - self.csr_common_name= csr_common_name + self.csr_common_name= capif_netapp_username self.capif_http_url = "http://" + capif_host.strip() + ":" + capif_http_port.strip() + "/" self.capif_https_url = "https://" + capif_host.strip() + ":" + capif_https_port.strip() + "/" self.capif_netapp_username = capif_netapp_username @@ -990,7 +989,7 @@ def __perform_authorization_and_store_ssl_keys(self, role): return response_payload['cert'] - def _write_to_file(self,publish_url): + def __write_to_file(self, publish_url): with open(self.certificates_folder + "capif_exposer_details.json", "w") as outfile: json.dump({ "publish_url": publish_url @@ -1004,26 +1003,28 @@ def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None capif_onboarding_url = registration_result['ccf_api_onboarding_url'] cert = self.__perform_authorization_and_store_ssl_keys(role) api_prov_dom_id = self.__onboard_exposer_to_capif(api_provider_domain_json_full_path, capif_onboarding_url, cert) - self._write_to_file(ccf_publish_url) + self.__write_to_file(ccf_publish_url) def publish_services(self,service_api_description_json_full_path)->None: - with open(self.certificates_folder, 'r') as openfile: - publish_url = json.load(openfile)["publish_url"] + with open(self.certificates_folder + "capif_exposer_details.json", 'r') as openfile: + file = json.load(openfile) + publish_url = file["publish_url"] url = self.capif_https_url + publish_url - with open(service_api_description_json_full_path, 'rb') as payload: - response = requests.request("POST", + with open(service_api_description_json_full_path, 'rb') as service_file: + data = json.load(service_file) + response = requests.request("POST", url, headers={'Content-Type': 'application/json'}, - data=payload, + data=data, cert=(self.certificates_folder + self.csr_common_name +'.crt', self.certificates_folder + 'private.key'), verify=self.certificates_folder+'ca.crt') - response.raise_for_status() - response_payload = json.loads(response.text) - return response_payload["apiId"] + response.raise_for_status() + response_payload = json.loads(response.text) + return response_payload["apiId"] class ServiceDiscoverer: diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index dc9bb88..aab4134 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -60,4 +60,4 @@ ] }, "ccfId": "string" - } \ No newline at end of file + } diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 9148c0d..06fe6d2 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,10 +8,9 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef09", + capif_netapp_username="test_nef23", capif_netapp_password="test_netapp_password", - description= "test_app_description", - csr_common_name="test_app_common_name" + description= "test_app_description" ) capif_connector.register_and_onboard_exposer( From e5f6d84991cc4cc6d16fe462e4cd7b87d6cdcad2 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 20:13:48 +0300 Subject: [PATCH 06/20] capif exposer troubleshooting --- .../capif_exposer_sample_files/service_api_description.json | 3 +-- examples/nef_capif_connector_examples.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index aab4134..4a0a93b 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -1,4 +1,3 @@ - { "apiName": "dummy-aef", "aefProfiles": [ @@ -60,4 +59,4 @@ ] }, "ccfId": "string" - } +} diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 06fe6d2..8894366 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef23", + capif_netapp_username="test_nef30", capif_netapp_password="test_netapp_password", description= "test_app_description" ) From f660fad2bd43f6415cdf0414ed02a043e99e0dea Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 20:17:18 +0300 Subject: [PATCH 07/20] change version and add comments --- HISTORY.rst | 6 +++++- evolved5g/__init__.py | 2 +- setup.cfg | 2 +- setup.py | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 034ebda..4486053 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,11 +2,15 @@ History ======= +0.8.3 (2022-10-17) +------------------- +* News SDK Library CAPIFExposerConnector, that allows exposers to register to CAPIF and publish services + + 0.8.2 (2022-10-14) ------------------- * Bug fix on import CAPIFConnector class from sdk - 0.8.1 (2022-10-12) ------------------- * New class at the Libraries: CAPIFConnector. Used in the CLI in order to onboard a netApp to CAPIF server diff --git a/evolved5g/__init__.py b/evolved5g/__init__.py index 3d3b947..aa68a47 100644 --- a/evolved5g/__init__.py +++ b/evolved5g/__init__.py @@ -1,7 +1,7 @@ """Top-level package for Evolved5G_CLI.""" __author__ = "EVOLVED5G project" -__version__ = '0.8.2' +__version__ = '0.8.3' # Uncomment next lines to give direct import access to modules #from . import cli diff --git a/setup.cfg b/setup.cfg index 9842ddc..1e6b2f1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.2 +current_version = 0.8.3 commit = True tag = True diff --git a/setup.py b/setup.py index 4c9f2e3..238308e 100644 --- a/setup.py +++ b/setup.py @@ -46,6 +46,6 @@ test_suite='tests', tests_require=test_requirements, url='https://github.com/EVOLVED-5G/SDK-CLI', - version='0.8.2', + version='0.8.3', zip_safe=False, ) From 7ed1e93ce9685934cbc998adbba11cd22d352452 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 20:48:01 +0300 Subject: [PATCH 08/20] add comments to method definitions' --- evolved5g/sdk.py | 14 ++++++++++---- .../service_api_description.json | 4 ++-- examples/nef_capif_connector_examples.py | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 30fbc21..f43711e 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -893,8 +893,8 @@ def __init__(self, capif_netapp_password: str, ): """ - :param certificates_folder: The folder where certificates will be stores. Your own certificate, - along with the certificate root that will be retrieved by the CAPIF server + :param certificates_folder: The folder where certificates will be created and stored. + :param description: A short description of the Exposer :param capif_host: :param capif_http_port: :param capif_https_port: @@ -996,6 +996,9 @@ def __write_to_file(self, publish_url): }, outfile) def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None: + """ + :param api_provider_domain_json_full_path: The full path of the api_provider_domain.json + """ role = "exposer" self.__store_certificate_authority_file() registration_result = self.__register_to_capif(role) @@ -1006,7 +1009,10 @@ def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None self.__write_to_file(ccf_publish_url) def publish_services(self,service_api_description_json_full_path)->None: - + """ + :param service_api_description_json_full_path: The full path fo the service_api_description.json that contains + the endpoints that will be published + """ with open(self.certificates_folder + "capif_exposer_details.json", 'r') as openfile: file = json.load(openfile) publish_url = file["publish_url"] @@ -1018,7 +1024,7 @@ def publish_services(self,service_api_description_json_full_path)->None: response = requests.request("POST", url, headers={'Content-Type': 'application/json'}, - data=data, + data=json.dumps(data), cert=(self.certificates_folder + self.csr_common_name +'.crt', self.certificates_folder + 'private.key'), verify=self.certificates_folder+'ca.crt') diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index 4a0a93b..3721ff7 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -1,8 +1,8 @@ { - "apiName": "dummy-aef", + "apiName": "THE_NAME_OF_API", "aefProfiles": [ { - "aefId": "string", + "aefId": "UNIQUE_STRING", "versions": [ { "apiVersion": "v1", diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 8894366..9cc8e58 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef30", + capif_netapp_username="test_nef34", capif_netapp_password="test_netapp_password", description= "test_app_description" ) From fabfec9c9a40c9834a5f9febdd63cc04e0266081 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 17 Oct 2022 20:55:23 +0300 Subject: [PATCH 09/20] change user name --- examples/nef_capif_connector_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 9cc8e58..77fb708 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef34", + capif_netapp_username="test_nef36", capif_netapp_password="test_netapp_password", description= "test_app_description" ) From 4d06131418a7e40399a6834c4f5886620f35ce19 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 20 Oct 2022 12:16:22 +0300 Subject: [PATCH 10/20] simplify CAPIFExposer connector --- evolved5g/sdk.py | 52 ++++++++++++------- .../api_provider_domain.json | 17 ------ .../service_api_description.json | 4 +- examples/nef_capif_connector_examples.py | 6 +-- examples/netapp_capif_connector_examples.py | 2 +- 5 files changed, 38 insertions(+), 43 deletions(-) delete mode 100644 examples/capif_exposer_sample_files/api_provider_domain.json diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index f43711e..413d7fc 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -921,18 +921,28 @@ def __store_certificate_authority_file(self): - def __onboard_exposer_to_capif(self, - api_provider_domain_json_full_path, - capif_onboarding_url, cert): + def __onboard_exposer_to_capif(self, capif_registration_id, public_key, capif_onboarding_url): url = self.capif_https_url + capif_onboarding_url - with open(api_provider_domain_json_full_path) as json_file: - payload = json.load(json_file) - payload["regSec"] = cert - - headers = { - 'Content-Type': 'application/json' + payload = { + "regSec": public_key, + "apiProvFuncs": [ + { + "apiProvFuncId": capif_registration_id, + "regInfo": { + "apiProvPubKey": public_key, + "apiProvCert": "", # what is this? + }, + "apiProvFuncRole": "AEF", + "apiProvFuncInfo": "" + } + ], + "apiProvDomInfo": "", + "suppFeat": "fff", + "failReason": "" } + headers = { 'Content-Type': 'application/json'} + response = requests.request("POST", url, headers=headers, @@ -963,7 +973,7 @@ def __register_to_capif(self, role): response.raise_for_status() response_payload = json.loads(response.text) - return response_payload + return response_payload def __perform_authorization_and_store_ssl_keys(self, role): @@ -987,26 +997,28 @@ def __perform_authorization_and_store_ssl_keys(self, role): with open(self.certificates_folder + "private.key", 'wb+') as private_key_file: private_key_file.write(bytes(response_payload['private_key'], 'utf-8')) - return response_payload['cert'] + return response_payload - def __write_to_file(self, publish_url): + def __write_to_file(self,capif_registration_id,api_prov_dom_id, publish_url): with open(self.certificates_folder + "capif_exposer_details.json", "w") as outfile: json.dump({ + "capif_registration_id": capif_registration_id, + "api_prov_dom_id": api_prov_dom_id, "publish_url": publish_url }, outfile) - def register_and_onboard_exposer(self, api_provider_domain_json_full_path)->None: - """ - :param api_provider_domain_json_full_path: The full path of the api_provider_domain.json - """ + def register_and_onboard_exposer(self)->None: role = "exposer" self.__store_certificate_authority_file() registration_result = self.__register_to_capif(role) + capif_registration_id = registration_result["id"] ccf_publish_url = registration_result['ccf_publish_url'] capif_onboarding_url = registration_result['ccf_api_onboarding_url'] - cert = self.__perform_authorization_and_store_ssl_keys(role) - api_prov_dom_id = self.__onboard_exposer_to_capif(api_provider_domain_json_full_path, capif_onboarding_url, cert) - self.__write_to_file(ccf_publish_url) + authorization_result = self.__perform_authorization_and_store_ssl_keys(role) + public_key = authorization_result['cert'] + + api_prov_dom_id = self.__onboard_exposer_to_capif(capif_registration_id, public_key, capif_onboarding_url) + self.__write_to_file(capif_registration_id,api_prov_dom_id,ccf_publish_url) def publish_services(self,service_api_description_json_full_path)->None: """ @@ -1016,6 +1028,8 @@ def publish_services(self,service_api_description_json_full_path)->None: with open(self.certificates_folder + "capif_exposer_details.json", 'r') as openfile: file = json.load(openfile) publish_url = file["publish_url"] + api_prov_dom_id = file["api_prov_dom_id"] + url = self.capif_https_url + publish_url diff --git a/examples/capif_exposer_sample_files/api_provider_domain.json b/examples/capif_exposer_sample_files/api_provider_domain.json deleted file mode 100644 index 5e441e9..0000000 --- a/examples/capif_exposer_sample_files/api_provider_domain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "regSec": "LEAVE_THIS_AS_EMPTY_IT_WILL_BE_AUTOMATICALLY_SET_DURING_CAPIF_REGISTRATION", - "apiProvFuncs": [ - { - "apiProvFuncId": "string_2", - "regInfo": { - "apiProvPubKey": "string", - "apiProvCert": "string" - }, - "apiProvFuncRole": "AEF", - "apiProvFuncInfo": "string" - } - ], - "apiProvDomInfo": "string", - "suppFeat": "fff", - "failReason": "string" - } diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index 3721ff7..bed6d40 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -2,7 +2,7 @@ "apiName": "THE_NAME_OF_API", "aefProfiles": [ { - "aefId": "UNIQUE_STRING", + "aefId": "UNIQUE_ID THAT IS SET AUTOMATICALLY BY THE SDK. Contains the API PROV DOM ID parameter", "versions": [ { "apiVersion": "v1", @@ -36,7 +36,7 @@ "securityMethods": ["Oauth", "PSK"], "interfaceDescriptions": [ { - "ipv4Addr": "python_aef", + "ipv4Addr": "the ip address where the exposer relies", "port": 8086, "securityMethods": ["Oauth"] } diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 77fb708..b832ff9 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,14 +8,12 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef36", + capif_netapp_username="test_nef47", capif_netapp_password="test_netapp_password", description= "test_app_description" ) - capif_connector.register_and_onboard_exposer( - api_provider_domain_json_full_path="/home/alex/Projects/test_nef_certificate_folder/api_provider_domain.json" - ) + capif_connector.register_and_onboard_exposer() capif_connector.publish_services( service_api_description_json_full_path="/home/alex/Projects/test_nef_certificate_folder/service_api_description.json") diff --git a/examples/netapp_capif_connector_examples.py b/examples/netapp_capif_connector_examples.py index 3ef4a91..9eb7949 100644 --- a/examples/netapp_capif_connector_examples.py +++ b/examples/netapp_capif_connector_examples.py @@ -11,7 +11,7 @@ def showcase_capif_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_netapp20", + capif_netapp_username="test_netapp_21", capif_netapp_password="test_netapp_password", capif_callback_url="http://localhost:5000", description= "test_app_description", From 735fe930fd458637690bd693243c2a429bb2de94 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 20 Oct 2022 12:31:10 +0300 Subject: [PATCH 11/20] pass the api prom dom id while publishing --- evolved5g/sdk.py | 4 ++++ .../capif_exposer_sample_files/service_api_description.json | 4 ++-- examples/nef_capif_connector_examples.py | 2 +- examples/netapp_capif_connector_examples.py | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 413d7fc..f96598f 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -1035,6 +1035,10 @@ def publish_services(self,service_api_description_json_full_path)->None: with open(service_api_description_json_full_path, 'rb') as service_file: data = json.load(service_file) + #todo: not sure if this is correct + for profile in data["aefProfiles"]: + profile["aefId"] = api_prov_dom_id + response = requests.request("POST", url, headers={'Content-Type': 'application/json'}, diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index bed6d40..a859e89 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -1,5 +1,5 @@ { - "apiName": "THE_NAME_OF_API", + "apiName": "api_name_2", "aefProfiles": [ { "aefId": "UNIQUE_ID THAT IS SET AUTOMATICALLY BY THE SDK. Contains the API PROV DOM ID parameter", @@ -58,5 +58,5 @@ "string" ] }, - "ccfId": "string" + "ccfId": "test" } diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index b832ff9..0218b4f 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef47", + capif_netapp_username="test_nef51", capif_netapp_password="test_netapp_password", description= "test_app_description" ) diff --git a/examples/netapp_capif_connector_examples.py b/examples/netapp_capif_connector_examples.py index 9eb7949..6c9cb6e 100644 --- a/examples/netapp_capif_connector_examples.py +++ b/examples/netapp_capif_connector_examples.py @@ -11,7 +11,7 @@ def showcase_capif_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_netapp_21", + capif_netapp_username="test_netapp_22", capif_netapp_password="test_netapp_password", capif_callback_url="http://localhost:5000", description= "test_app_description", From a529ed29198f6fd71d2d333003351accfab745e1 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 20 Oct 2022 14:21:38 +0300 Subject: [PATCH 12/20] update the CLI to retrieve a config file with the parameters for NetApp onboarding --- evolved5g/cli_helper.py | 91 +++++++++---------- examples/nef_capif_connector_examples.py | 2 +- .../netap_capif_connector_config_file.json | 17 ++++ 3 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 examples/netapp_capif_config_file/netap_capif_connector_config_file.json diff --git a/evolved5g/cli_helper.py b/evolved5g/cli_helper.py index 188722e..015e13f 100644 --- a/evolved5g/cli_helper.py +++ b/evolved5g/cli_helper.py @@ -7,7 +7,8 @@ from evolved5g.sdk import CAPIFInvokerConnector import traceback -class CLI_helper: + +class CLI_helper: def __init__(self): @@ -17,7 +18,7 @@ def __init__(self): self.password_token = "evolved5g" self.netapp_branch = "evolved5g" self.branch_cicd_repo = "develop" - self.header = { "Content-Type":"application/json", "accept": "application/json", "Authorization": None } + self.header = {"Content-Type": "application/json", "accept": "application/json", "Authorization": None} self.repository = "https://api.github.com/repos/EVOLVED-5G" self.jenkinsjob = "003-NETAPPS/999-ToReview/" @@ -29,10 +30,10 @@ def generate(self, config_file): def generate_token(self): - self.header = { "content-Type":"application/json", "accept": None, "Authorization": None } + self.header = {"content-Type": "application/json", "accept": None, "Authorization": None} data = '{ "username": "' + self.username_token + '", "password": "' + self.password_token + '" }' resp = requests.post(self.url_token, headers=self.header, data=data) - return(resp.json()["access_token"]) + return (resp.json()["access_token"]) def run_verification_tests(self, mode, repo): """Run the build pipeline for the EVOLVED-5G NetApp""" @@ -41,25 +42,29 @@ def run_verification_tests(self, mode, repo): if "message" not in repo_exist: try: if mode == "build": - self.header = { "content-Type":"application/json", "accept": "application/json", "Authorization": self.generate_token() } - data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "'+self.jenkinsjob + mode+'", "parameters": { "VERSION": "1.0", "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'", "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '", "GIT_CICD_BRANCH": "' + self.branch_cicd_repo + '"} }' + self.header = {"content-Type": "application/json", "accept": "application/json", + "Authorization": self.generate_token()} + data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "' + self.jenkinsjob + mode + '", "parameters": { "VERSION": "1.0", "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '", "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '", "GIT_CICD_BRANCH": "' + self.branch_cicd_repo + '"} }' resp = requests.post(self.url_curl, headers=self.header, data=data) echo('Your pipeline ID is: %s' % resp.json()["id"]) elif mode == "deploy" or mode == "destroy": - self.header = { "content-Type":"application/json", "accept": "application/json", "Authorization": self.generate_token() } - data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "'+self.jenkinsjob + mode+'", "parameters": { "VERSION": "1.0", "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'", "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '", "GIT_CICD_BRANCH": "' + self.branch_cicd_repo + '"} }' + self.header = {"content-Type": "application/json", "accept": "application/json", + "Authorization": self.generate_token()} + data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "' + self.jenkinsjob + mode + '", "parameters": { "VERSION": "1.0", "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '", "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '", "GIT_CICD_BRANCH": "' + self.branch_cicd_repo + '"} }' resp = requests.post(self.url_curl, headers=self.header, data=data) echo('Your pipeline ID is: %s' % resp.json()["id"]) elif mode == "code_analysis": - self.header = { "content-Type":"application/json", "accept": "application/json", "Authorization": self.generate_token() } - data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/001-Static Code Analysis", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' + self.header = {"content-Type": "application/json", "accept": "application/json", + "Authorization": self.generate_token()} + data = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/001-Static Code Analysis", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' resp = requests.post(self.url_curl, headers=self.header, data=data) echo('Your pipeline ID is: %s' % resp.json()["id"]) elif mode == "security_scan": - self.header = { "content-Type":"application/json", "accept": "application/json", "Authorization": self.generate_token() } - data1 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/002-Security Scan Code", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' - data2 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/003-Security Scan Secrets", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' - data3 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/004-Security Scan Docker Images", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo +'","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' + self.header = {"content-Type": "application/json", "accept": "application/json", + "Authorization": self.generate_token()} + data1 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/002-Security Scan Code", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' + data2 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/003-Security Scan Secrets", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' + data3 = '{ "instance": "pro-dcip-evol5-01.hi.inet", "job": "003-NETAPPS/003-Helpers/004-Security Scan Docker Images", "parameters": { "GIT_NETAPP_URL": "https://github.com/EVOLVED-5G/' + repo + '","GIT_CICD_BRANCH": "develop", "BUILD_ID": "0" , "REPORTING": "true" , "GIT_NETAPP_BRANCH": "' + self.netapp_branch + '"} }' resp1 = requests.post(self.url_curl, headers=self.header, data=data1) resp2 = requests.post(self.url_curl, headers=self.header, data=data2) resp3 = requests.post(self.url_curl, headers=self.header, data=data3) @@ -73,14 +78,16 @@ def run_verification_tests(self, mode, repo): except TypeError as e: echo("Please enter the correct command: evolved5g run_pipeline --mode build --repo REPOSITORY_NAME") else: - echo(f"The {repo} repository you have chosen does not exist, please check the name you typed and try again.") + echo( + f"The {repo} repository you have chosen does not exist, please check the name you typed and try again.") def check_job(self, id): """Check the status of the pipeline for the EVOLVED-5G NetApp""" try: - self.header = { "content-Type":"application/json", "accept": "application/json", "Authorization": self.generate_token() } + self.header = {"content-Type": "application/json", "accept": "application/json", + "Authorization": self.generate_token()} resp = requests.get(f"{self.url_curl}/{id}", headers=self.header) result = resp.json() @@ -99,37 +106,24 @@ def check_job(self, id): except ValueError as e: echo("Please add the ID: evolved5g check-pipeline --id ") - def register_and_onboard_to_capif(self, folder_to_store_certificates: str, - capif_host, - capif_http_port, - capif_https_port, - capif_netapp_username, - capif_netapp_password: str, - capif_callback_url: str, - description:str, - csr_common_name: str, - csr_organizational_unit: str, - csr_organization: str, - crs_locality: str, - csr_state_or_province_name, - csr_country_name, - csr_email_address)->None: - - capif_connector = CAPIFInvokerConnector(folder_to_store_certificates, - capif_host, - capif_http_port, - capif_https_port, - capif_netapp_username, - capif_netapp_password, - capif_callback_url, - description, - csr_common_name, - csr_organizational_unit, - csr_organization, - crs_locality, - csr_state_or_province_name, - csr_country_name, - csr_email_address) + def register_and_onboard_to_capif(self, config_file_full_path: str) -> None: + with open(config_file_full_path, 'r') as openfile: + config = json.load(openfile) + capif_connector = CAPIFInvokerConnector(folder_to_store_certificates=config["folder_to_store_certificates"], + capif_host=config["capif_host"], + capif_http_port=config["capif_http_port"], + capif_https_port=config["capif_https_port"], + capif_netapp_username=config["capif_netapp_username"], + capif_netapp_password=config["capif_netapp_password"], + capif_callback_url=config["capif_callback_url"], + description=config["description"], + csr_common_name=config["csr_common_name"], + csr_organizational_unit=config["csr_organizational_unit"], + csr_organization=config["csr_organization"], + crs_locality=config["crs_locality"], + csr_state_or_province_name= config["csr_state_or_province_name"], + csr_country_name=config["csr_country_name"], + csr_email_address=config["csr_email_address"]) try: capif_connector.register_and_onboard_netapp() echo("Your netApp has been successfully registered and onboarded to the CAPIF server." + @@ -137,6 +131,3 @@ def register_and_onboard_to_capif(self, folder_to_store_certificates: str, except Exception: echo("An error occurred. Registration failed:") traceback.print_exc() - - - diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 0218b4f..2af3709 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -8,7 +8,7 @@ def showcase_capif_nef_connector(): capif_host="capifcore", capif_http_port="8080", capif_https_port="443", - capif_netapp_username="test_nef51", + capif_netapp_username="test_nef01", capif_netapp_password="test_netapp_password", description= "test_app_description" ) diff --git a/examples/netapp_capif_config_file/netap_capif_connector_config_file.json b/examples/netapp_capif_config_file/netap_capif_connector_config_file.json new file mode 100644 index 0000000..e1a5e5c --- /dev/null +++ b/examples/netapp_capif_config_file/netap_capif_connector_config_file.json @@ -0,0 +1,17 @@ +{ + "folder_to_store_certificates": "/home/alex/Projects/test_certificate_folder", + "capif_host": "capifcore", + "capif_http_port": 8080, + "capif_https_port": 443, + "capif_netapp_username": "test_netapp_22", + "capif_netapp_password": "test_netapp_password", + "capif_callback_url": "http://localhost:5000", + "description": ",test_app_description", + "csr_common_name": "test_app_common_name", + "csr_organizational_unit": "test_app_ou", + "csr_organization": "test_app_o", + "crs_locality": "Madrid", + "csr_state_or_province_name": "Madrid", + "csr_country_name": "ES", + "csr_email_address": "test@example.com" +} From fd39431d823b4ff3fc217bbe71e5deaa22177cb0 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 20 Oct 2022 14:44:44 +0300 Subject: [PATCH 13/20] update documentation --- HISTORY.rst | 1 + docs/source/libraries.rst | 13 +++- evolved5g/cli.py | 67 ++++++------------- evolved5g/sdk.py | 4 +- .../netapp_capif_connector_config_file.json} | 2 +- 5 files changed, 38 insertions(+), 49 deletions(-) rename examples/{netapp_capif_config_file/netap_capif_connector_config_file.json => netapp_capif_config/netapp_capif_connector_config_file.json} (92%) diff --git a/HISTORY.rst b/HISTORY.rst index 4486053..c7aa4eb 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -5,6 +5,7 @@ History 0.8.3 (2022-10-17) ------------------- * News SDK Library CAPIFExposerConnector, that allows exposers to register to CAPIF and publish services +* New CLI command evolved5G register-and-onboard-to-capif that allows NetApps to register their NetAPP to CAPIF via the command line 0.8.2 (2022-10-14) diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 7fe154b..edb0ef0 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -2,11 +2,15 @@ SDK - Libraries =============== -At the current release the SDK contains two classes +At the current release the SDK contains six classes * **LocationSubscriber**: allows you to track devices and retrieve updates about their location.You can use LocationSubscriber to create subscriptions, where each one of them can be used to track a device. * **QosAwareness**: allows you to request QoS from a set of standardized values for better service experience (Ex. TCP_BASED / LIVE Streaming / CONVERSATIONAL_VOICE etc). You can create subscriptions where each one of them has specific QoS parameters. A notification is sent back to the net-app if the QoS targets can no longer be full-filled. * **ConnectionMonitor**: allows you to monitor devices in the 5G Network. You this class to p can retrieve notifications by the 5G Network for individual devices when connection is lost (for example the user device has not been connected to the 5G network for the past 10 seconds) or when connection is alive (for example the user device has been connected to the 5G network for the past 10 seconds). +* **CAPIFInvokerConnector** a low level class, that is used by the evolved-5G CLI in order to register NetApps to CAPIF +* **CAPIFExposerConnector** a low level class, that allows an Exposer (like the NEF emulator) to register to CAPIF +* **ServiceDiscoverer** allows NetApp developer to connect to CAPIF in order to discover services + @@ -20,6 +24,13 @@ Have a look at the examples folder for code samples on how to use the SDK Librar * `ConnectionMonitor example `_ +* `CAPIFInvokerConnector example `_ + +* `CAPIFExposerConnector example `_ + +* `ServiceDiscoverer example `_ + + Prerequisites / How to start ---------------------------- diff --git a/evolved5g/cli.py b/evolved5g/cli.py index 92a7ca1..efe8bd6 100644 --- a/evolved5g/cli.py +++ b/evolved5g/cli.py @@ -38,51 +38,28 @@ def check_job(ctx, id): @cli.command() -@click.option('--folder_to_store_certificates',type=str, help='The folder where certificates and authorization files will be stored') -@click.option('--capif_host',type=str, help='The host of the CAPIF Server (Ex. capifcore if you are running the docker container)') -@click.option('--capif_http_port',type=str, help='The http port of the CAPIF Server (Ex. 8080 if you are running the docker container)') -@click.option('--capif_https_port',type=str, help='The https port of theCAPIF Server (Ex. 443 if you are running the docker container)') -@click.option('--capif_netapp_username',type=str, help='The CAPIF username of your netapp') -@click.option('--capif_netapp_password',type=str, help='The CAPIF password of your netapp') -@click.option('--capif_callback_url',type=str, help='A url provided by you that will be used to receive HTTP POST notifications from CAPIF.') -@click.option('--description',type=str, help='A short description of your netapp') -@click.option('--csr_common_name',type=str, help='The CommonName that will be used in the generated X.509 certificate') -@click.option('--csr_organizational_unit',type=str, help='The OrganizationalUnit that will be used in the generated X.509 certificate') -@click.option('--csr_organization',type=str, help='The Organization that will be used in the generated X.509 certificate') -@click.option('--crs_locality',type=str, help=' The Locality that will be used in the generated X.509 certificate') -@click.option('--csr_state_or_province_name',type=str, help='The StateOrProvinceName that will be used in the generated X.509 certificate') -@click.option('--csr_country_name',type=str, help='The CountryName that will be used in the generated X.509 certificate') -@click.option('--csr_email_address',type=str, help='The email that will be used in the generated X.509 certificate') +@click.option('--config_file_full_path',type=str, + help="""The configuration file used to register and onboard the NetApp to CAPIF + --folder_to_store_certificates: The folder where certificates and authorization files will be stored + --capif_host: The host of the CAPIF Server (Ex. capifcore if you are running the docker container) + --capif_http_port: The http port of the CAPIF Server (Ex. 8080 if you are running the docker container) + --capif_https_port: The https port of theCAPIF Server (Ex. 443 if you are running the docker container) + --capif_netapp_username: The CAPIF username of your netapp + --capif_netapp_password: The CAPIF password of your netapp + --capif_callback_url: A url provided by you that will be used to receive HTTP POST notifications from CAPIF. + --description: A short description of your netapp + --csr_common_name: The CommonName that will be used in the generated X.509 certificate + --csr_organizational_unit: The OrganizationalUnit that will be used in the generated X.509 certificate + --csr_organization: The Organization that will be used in the generated X.509 certificate + --crs_locality: The Locality that will be used in the generated X.509 certificatE + --csr_state_or_province_name: The StateOrProvinceName that will be used in the generated X.509 certificate + --csr_country_name: The CountryName that will be used in the generated X.509 certificate + --csr_email_address: The email that will be used in the generated X.509 certificate + """ + ) + @click.pass_context def register_and_onboard_to_capif(ctx, - folder_to_store_certificates: str, - capif_host: str, - capif_http_port: str, - capif_https_port: str, - capif_netapp_username, - capif_netapp_password: str, - capif_callback_url: str, - description:str, - csr_common_name: str, - csr_organizational_unit: str, - csr_organization: str, - crs_locality: str, - csr_state_or_province_name, - csr_country_name:str, - csr_email_address:str): + config_file_full_path:str): - ctx.obj["helper"].register_and_onboard_to_capif(folder_to_store_certificates, - capif_host, - capif_http_port, - capif_https_port, - capif_netapp_username, - capif_netapp_password, - capif_callback_url, - description, - csr_common_name, - csr_organizational_unit, - csr_organization, - crs_locality, - csr_state_or_province_name, - csr_country_name, - csr_email_address) + ctx.obj["helper"].register_and_onboard_to_capif(config_file_full_path) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index f96598f..bdbf463 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -728,8 +728,8 @@ def __init__(self, """ # add the trailing slash if it is not already there using os.path.join self.folder_to_store_certificates = os.path.join(folder_to_store_certificates.strip(), '') - self.capif_http_url = "http://" + capif_host.strip() + ":" + capif_http_port.strip() + "/" - self.capif_https_url = "https://" + capif_host.strip() + ":" + capif_https_port.strip() + "/" + self.capif_http_url = "http://" + capif_host.strip() + ":" + str(capif_http_port) + "/" + self.capif_https_url = "https://" + capif_host.strip() + ":" + str(capif_https_port) + "/" self.capif_callback_url = self.__add_trailing_slash_to_url_if_missing(capif_callback_url.strip()) self.capif_netapp_username = capif_netapp_username self.capif_netapp_password = capif_netapp_password diff --git a/examples/netapp_capif_config_file/netap_capif_connector_config_file.json b/examples/netapp_capif_config/netapp_capif_connector_config_file.json similarity index 92% rename from examples/netapp_capif_config_file/netap_capif_connector_config_file.json rename to examples/netapp_capif_config/netapp_capif_connector_config_file.json index e1a5e5c..7a34d48 100644 --- a/examples/netapp_capif_config_file/netap_capif_connector_config_file.json +++ b/examples/netapp_capif_config/netapp_capif_connector_config_file.json @@ -3,7 +3,7 @@ "capif_host": "capifcore", "capif_http_port": 8080, "capif_https_port": 443, - "capif_netapp_username": "test_netapp_22", + "capif_netapp_username": "test_netapp_23", "capif_netapp_password": "test_netapp_password", "capif_callback_url": "http://localhost:5000", "description": ",test_app_description", From f2004f74a70a7bb3988c42871b72f5741e514950 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 20 Oct 2022 18:10:04 +0300 Subject: [PATCH 14/20] update example --- examples/nef_capif_connector_examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nef_capif_connector_examples.py b/examples/nef_capif_connector_examples.py index 2af3709..12e6854 100644 --- a/examples/nef_capif_connector_examples.py +++ b/examples/nef_capif_connector_examples.py @@ -4,7 +4,7 @@ def showcase_capif_nef_connector(): """ """ - capif_connector = CAPIFExposerConnector(certificates_folder="/home/alex/Projects/test_nef_certificate_folder/", + capif_connector = CAPIFExposerConnector(certificates_folder="/the_path_to_the_certificates_folder/", capif_host="capifcore", capif_http_port="8080", capif_https_port="443", @@ -16,7 +16,7 @@ def showcase_capif_nef_connector(): capif_connector.register_and_onboard_exposer() capif_connector.publish_services( - service_api_description_json_full_path="/home/alex/Projects/test_nef_certificate_folder/service_api_description.json") + service_api_description_json_full_path="/the_path_to_service_api_description_json") if __name__ == "__main__": From 2dd9f793bbd4f0d88bb2faf81731f4f00dc12b7f Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Wed, 26 Oct 2022 16:33:15 +0300 Subject: [PATCH 15/20] The SDK Library classes should read the endpoints from ServiceDiscoverer. Change the all the API endpoints for the SDK-NEF communication in order to read the endpoints dynamically --- evolved5g/sdk.py | 77 +++++++++--- .../api/monitoring_event_api_api.py | 10 +- .../api/session_with_qo_s_api_api.py | 112 ++++++++++++------ examples/location_subscriber_examples.py | 8 +- 4 files changed, 148 insertions(+), 59 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index bdbf463..d8b9d82 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -19,10 +19,19 @@ class MonitoringSubscriber(ABC): - def __init__(self, host: str, bearer_access_token: str): + def __init__(self, host: str, + nef_bearer_access_token: str, + folder_path_for_certificates_and_capif_api_key: str, + capif_host:str, + capif_https_port:int): configuration = swagger_client.Configuration() configuration.host = host - configuration.access_token = bearer_access_token + configuration.access_token = nef_bearer_access_token + #todo: these endpoints should be found dynamically by the capif + configuration.available_endpoints = { + "MONITORING_SUBSCRIPTIONS": '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions', + "MONITORING_SUBSCRIPTION_SINGLE": '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}' + } api_client = swagger_client.ApiClient(configuration=configuration) self.monitoring_event_api = MonitoringEventAPIApi(api_client) self.cell_api = CellsApi(api_client) @@ -82,7 +91,11 @@ def delete_subscription(self, netapp_id: str, subscription_id: str): class LocationSubscriber(MonitoringSubscriber): - def __init__(self, host: str, bearer_access_token: str): + def __init__(self, host: str, + bearer_access_token: str, + folder_path_for_certificates_and_capif_api_key: str, + capif_host:str, + capif_https_port:int): """ Initializes class LocationSubscriber. This SKD class allows you to track devices and retrieve updates about their location. @@ -92,7 +105,10 @@ def __init__(self, host: str, bearer_access_token: str): :param str host: The url of the 5G-API :param str bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API """ - super().__init__(host, bearer_access_token) + super().__init__(host, bearer_access_token, + folder_path_for_certificates_and_capif_api_key, + capif_host, + capif_https_port) def __get_monitoring_type(self): return "LOCATION_REPORTING" @@ -198,7 +214,12 @@ class MonitoringType(Enum): INFORM_WHEN_CONNECTED = 1 INFORM_WHEN_NOT_CONNECTED = 2 - def __init__(self, host: str, bearer_access_token: str): + def __init__(self, + host: str, + bearer_access_token: str, + folder_path_for_certificates_and_capif_api_key: str, + capif_host:str, + capif_https_port:int): """ Initializes class ConnectionMonitor. Consider a scenario where a NetApp wants to monitor 100 devices in the 5G Network. @@ -210,8 +231,15 @@ def __init__(self, host: str, bearer_access_token: str): :param str host: The url of the 5G-API :param str bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API + :param folder_path_for_certificates_and_capif_api_key: The folder that contains the NetApp certificates and + CAPIF API Key. These are created while registering and onboarding the NetApp to the CAPIF Server + :param capif_host: The host of the CAPIF Server (ex. "capifcore") + :param capif_https_port: The https_port of the CAPIF Server """ - super().__init__(host, bearer_access_token) + super().__init__(host, bearer_access_token, + folder_path_for_certificates_and_capif_api_key, + capif_host, + capif_https_port) def __get_monitoring_type(self, monitoring_type: MonitoringType): if monitoring_type == self.MonitoringType.INFORM_WHEN_CONNECTED: @@ -397,21 +425,36 @@ def get_reporting_mode(self): def get_reporting_configuration(self): return self.repetition_period_in_seconds - def __init__(self, host: str, bearer_access_token: str): + def __init__(self, host: str, + nef_bearer_access_token: str, + folder_path_for_certificates_and_capif_api_key: str, + capif_host:str, + capif_https_port:int): """ - Initializes class QosAwareness. - This SKD class allows you to requests QoS from a set of standardized values for better service experience. - - You can create subscriptions where each one of them has specific QoS parameters. - A notification is sent to a callback url you will provide, informing you in case the QoS targets can no - longer be full-filled. - - :param str host: The url of the 5G-API - :param str bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API + Initializes class QosAwareness. + This SKD class allows you to request QoS from a set of standardized values for better service experience. + + You can create subscriptions where each one of them has specific QoS parameters. + A notification is sent to a callback url you will provide, informing you in case the QoS targets can no + longer be full-filled. + + :param host: The url of the 5G-API (ex. NEF emulator) + :param nef_bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API + :param folder_path_for_certificates_and_capif_api_key: The folder that contains the NetApp certificates and + CAPIF API Key. These are created while registering and onboarding the NetApp to the CAPIF Server + :param capif_host: The host of the CAPIF Server (ex. "capifcore") + :param capif_https_port: The https_port of the CAPIF Server """ + configuration = swagger_client.Configuration() configuration.host = host - configuration.access_token = bearer_access_token + configuration.access_token = nef_bearer_access_token + service_discoverer = ServiceDiscoverer(folder_path_for_certificates_and_capif_api_key,capif_host,capif_https_port) + #todo: these endpoints should be found dynamically by the capif + configuration.available_endpoints = { + "QOS_SUBSCRIPTIONS": '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions', + "QOS_SUBSCRIPTION_SINGLE": '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}' + } api_client = swagger_client.ApiClient(configuration=configuration) self.qos_api = SessionWithQoSAPIApi(api_client) diff --git a/evolved5g/swagger_client/api/monitoring_event_api_api.py b/evolved5g/swagger_client/api/monitoring_event_api_api.py index 9893374..2b523a0 100644 --- a/evolved5g/swagger_client/api/monitoring_event_api_api.py +++ b/evolved5g/swagger_client/api/monitoring_event_api_api.py @@ -124,7 +124,7 @@ def create_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_p auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions', 'POST', + self.api_client.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'POST', path_params, query_params, header_params, @@ -233,7 +233,7 @@ def delete_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_s auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}', 'DELETE', + self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'DELETE', path_params, query_params, header_params, @@ -336,7 +336,7 @@ def read_active_subscriptions_api_v13gpp_monitoring_event_v1_scs_as_id_subscript auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions', 'GET', + self.api_client.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'GET', path_params, query_params, header_params, @@ -439,7 +439,7 @@ def read_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_sub auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}', 'GET', + self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'GET', path_params, query_params, header_params, @@ -554,7 +554,7 @@ def update_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_s auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}', 'PUT', + self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'PUT', path_params, query_params, header_params, diff --git a/evolved5g/swagger_client/api/session_with_qo_s_api_api.py b/evolved5g/swagger_client/api/session_with_qo_s_api_api.py index 4b9154c..92c1343 100644 --- a/evolved5g/swagger_client/api/session_with_qo_s_api_api.py +++ b/evolved5g/swagger_client/api/session_with_qo_s_api_api.py @@ -32,7 +32,8 @@ def __init__(self, api_client=None): api_client = ApiClient() self.api_client = api_client - def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post(self, body, scs_as_id, **kwargs): # noqa: E501 + def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post(self, body, scs_as_id, + **kwargs): # noqa: E501 """Create Subscription # noqa: E501 This method makes a synchronous HTTP request by default. To make an @@ -49,12 +50,17 @@ def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): - return self.create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info(body, scs_as_id, **kwargs) # noqa: E501 + return self.create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info( + body, scs_as_id, **kwargs) # noqa: E501 else: - (data) = self.create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info(body, scs_as_id, **kwargs) # noqa: E501 + ( + data) = self.create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info( + body, scs_as_id, **kwargs) # noqa: E501 return data - def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info(self, body, scs_as_id, **kwargs): # noqa: E501 + def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post_with_http_info(self, body, + scs_as_id, + **kwargs): # noqa: E501 """Create Subscription # noqa: E501 This method makes a synchronous HTTP request by default. To make an @@ -88,11 +94,13 @@ def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription # verify the required parameter 'body' is set if ('body' not in params or params['body'] is None): - raise ValueError("Missing the required parameter `body` when calling `create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post`") # noqa: E501 + raise ValueError( + "Missing the required parameter `body` when calling `create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post`") # noqa: E501 # verify the required parameter 'scs_as_id' is set if ('scs_as_id' not in params or params['scs_as_id'] is None): - raise ValueError("Missing the required parameter `scs_as_id` when calling `create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post`") # noqa: E501 + raise ValueError( + "Missing the required parameter `scs_as_id` when calling `create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_post`") # noqa: E501 collection_formats = {} @@ -122,7 +130,7 @@ def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions', 'POST', + self.api_client.configuration["QOS_SUBSCRIPTIONS"], 'POST', path_params, query_params, header_params, @@ -137,7 +145,10 @@ def create_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) - def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete(self, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete(self, + scs_as_id, + subscription_id, + **kwargs): # noqa: E501 """Delete Subscription # noqa: E501 Delete a subscription # noqa: E501 @@ -155,12 +166,16 @@ def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): - return self.delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info(scs_as_id, subscription_id, **kwargs) # noqa: E501 + return self.delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info( + scs_as_id, subscription_id, **kwargs) # noqa: E501 else: - (data) = self.delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info(scs_as_id, subscription_id, **kwargs) # noqa: E501 + ( + data) = self.delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info( + scs_as_id, subscription_id, **kwargs) # noqa: E501 return data - def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info(self, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete_with_http_info( + self, scs_as_id, subscription_id, **kwargs): # noqa: E501 """Delete Subscription # noqa: E501 Delete a subscription # noqa: E501 @@ -195,11 +210,13 @@ def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription # verify the required parameter 'scs_as_id' is set if ('scs_as_id' not in params or params['scs_as_id'] is None): - raise ValueError("Missing the required parameter `scs_as_id` when calling `delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete`") # noqa: E501 + raise ValueError( + "Missing the required parameter `scs_as_id` when calling `delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete`") # noqa: E501 # verify the required parameter 'subscription_id' is set if ('subscription_id' not in params or params['subscription_id'] is None): - raise ValueError("Missing the required parameter `subscription_id` when calling `delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete`") # noqa: E501 + raise ValueError( + "Missing the required parameter `subscription_id` when calling `delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_delete`") # noqa: E501 collection_formats = {} @@ -225,7 +242,7 @@ def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}', 'DELETE', + self.api_client.configuration["QOS_SUBSCRIPTION_SINGLE"], 'DELETE', path_params, query_params, header_params, @@ -240,7 +257,8 @@ def delete_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) - def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get(self, scs_as_id, **kwargs): # noqa: E501 + def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get(self, scs_as_id, + **kwargs): # noqa: E501 """Read Active Subscriptions # noqa: E501 Get subscription by id # noqa: E501 @@ -257,12 +275,17 @@ def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscr """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): - return self.read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info(scs_as_id, **kwargs) # noqa: E501 + return self.read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info( + scs_as_id, **kwargs) # noqa: E501 else: - (data) = self.read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info(scs_as_id, **kwargs) # noqa: E501 + ( + data) = self.read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info( + scs_as_id, **kwargs) # noqa: E501 return data - def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info(self, scs_as_id, **kwargs): # noqa: E501 + def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get_with_http_info(self, + scs_as_id, + **kwargs): # noqa: E501 """Read Active Subscriptions # noqa: E501 Get subscription by id # noqa: E501 @@ -296,7 +319,8 @@ def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscr # verify the required parameter 'scs_as_id' is set if ('scs_as_id' not in params or params['scs_as_id'] is None): - raise ValueError("Missing the required parameter `scs_as_id` when calling `read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get`") # noqa: E501 + raise ValueError( + "Missing the required parameter `scs_as_id` when calling `read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_get`") # noqa: E501 collection_formats = {} @@ -320,7 +344,7 @@ def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscr auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions', 'GET', + self.api_client.configuration["QOS_SUBSCRIPTIONS"], 'GET', path_params, query_params, header_params, @@ -335,7 +359,9 @@ def read_active_subscriptions_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscr _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) - def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get(self, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get(self, scs_as_id, + subscription_id, + **kwargs): # noqa: E501 """Read Subscription # noqa: E501 Get subscription by id # noqa: E501 @@ -353,12 +379,16 @@ def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_ """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): - return self.read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info(scs_as_id, subscription_id, **kwargs) # noqa: E501 + return self.read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info( + scs_as_id, subscription_id, **kwargs) # noqa: E501 else: - (data) = self.read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info(scs_as_id, subscription_id, **kwargs) # noqa: E501 + ( + data) = self.read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info( + scs_as_id, subscription_id, **kwargs) # noqa: E501 return data - def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info(self, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get_with_http_info( + self, scs_as_id, subscription_id, **kwargs): # noqa: E501 """Read Subscription # noqa: E501 Get subscription by id # noqa: E501 @@ -393,11 +423,13 @@ def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_ # verify the required parameter 'scs_as_id' is set if ('scs_as_id' not in params or params['scs_as_id'] is None): - raise ValueError("Missing the required parameter `scs_as_id` when calling `read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get`") # noqa: E501 + raise ValueError( + "Missing the required parameter `scs_as_id` when calling `read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get`") # noqa: E501 # verify the required parameter 'subscription_id' is set if ('subscription_id' not in params or params['subscription_id'] is None): - raise ValueError("Missing the required parameter `subscription_id` when calling `read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get`") # noqa: E501 + raise ValueError( + "Missing the required parameter `subscription_id` when calling `read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_get`") # noqa: E501 collection_formats = {} @@ -423,7 +455,7 @@ def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_ auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}', 'GET', + self.api_client.configuration["QOS_SUBSCRIPTION_SINGLE"], 'GET', path_params, query_params, header_params, @@ -438,7 +470,10 @@ def read_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_ _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) - def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put(self, body, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put(self, body, + scs_as_id, + subscription_id, + **kwargs): # noqa: E501 """Update Subscription # noqa: E501 Update subscription by id # noqa: E501 @@ -457,12 +492,16 @@ def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): - return self.update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info(body, scs_as_id, subscription_id, **kwargs) # noqa: E501 + return self.update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info( + body, scs_as_id, subscription_id, **kwargs) # noqa: E501 else: - (data) = self.update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info(body, scs_as_id, subscription_id, **kwargs) # noqa: E501 + ( + data) = self.update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info( + body, scs_as_id, subscription_id, **kwargs) # noqa: E501 return data - def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info(self, body, scs_as_id, subscription_id, **kwargs): # noqa: E501 + def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put_with_http_info( + self, body, scs_as_id, subscription_id, **kwargs): # noqa: E501 """Update Subscription # noqa: E501 Update subscription by id # noqa: E501 @@ -498,15 +537,18 @@ def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription # verify the required parameter 'body' is set if ('body' not in params or params['body'] is None): - raise ValueError("Missing the required parameter `body` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 + raise ValueError( + "Missing the required parameter `body` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 # verify the required parameter 'scs_as_id' is set if ('scs_as_id' not in params or params['scs_as_id'] is None): - raise ValueError("Missing the required parameter `scs_as_id` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 + raise ValueError( + "Missing the required parameter `scs_as_id` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 # verify the required parameter 'subscription_id' is set if ('subscription_id' not in params or params['subscription_id'] is None): - raise ValueError("Missing the required parameter `subscription_id` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 + raise ValueError( + "Missing the required parameter `subscription_id` when calling `update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscriptions_subscription_id_put`") # noqa: E501 collection_formats = {} @@ -538,7 +580,7 @@ def update_subscription_api_v13gpp_as_session_with_qos_v1_scs_as_id_subscription auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}', 'PUT', + self.api_client.configuration["QOS_SUBSCRIPTION_SINGLE"], 'PUT', path_params, query_params, header_params, diff --git a/examples/location_subscriber_examples.py b/examples/location_subscriber_examples.py index 930693e..9561656 100644 --- a/examples/location_subscriber_examples.py +++ b/examples/location_subscriber_examples.py @@ -20,7 +20,11 @@ def showcase_create_subscription_and_retrieve_call_backs(): netapp_id = "myNetapp" host = emulator_utils.get_host_of_the_nef_emulator() token = emulator_utils.get_token() - location_subscriber = LocationSubscriber(host, token.access_token) + location_subscriber = LocationSubscriber(host=host, + bearer_access_token=token.access_token, + folder_path_for_certificates_and_capif_api_key="", + capif_host="capifcore", + capif_https_port=443) # The following external identifier was copy pasted by the NEF emulator. Go to the Map and click on a User icon. There you can retrieve the id external_id = "10003@domain.com" @@ -103,7 +107,7 @@ def read_and_delete_all_existing_subscriptions(): if __name__ == "__main__": - read_and_delete_all_existing_subscriptions() + #read_and_delete_all_existing_subscriptions() showcase_create_subscription_and_retrieve_call_backs() read_and_delete_all_existing_subscriptions() showcase_create_single_request_for_location_info() From 140c3a89ec922fb1d843a7f05170b1d1005baad8 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 27 Oct 2022 19:59:28 +0300 Subject: [PATCH 16/20] Improve the examples, pass the extra parameters needed for CAPIF communication --- evolved5g/sdk.py | 65 +++++--- .../service_api_description.json | 142 ++++++++++-------- examples/connection_monitor_examples.py | 16 +- examples/emulator_examples.py | 2 +- examples/emulator_utils.py | 31 +++- examples/location_subscriber_examples.py | 32 ++-- examples/qos_awereness_examples.py | 17 ++- 7 files changed, 195 insertions(+), 110 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index d8b9d82..caf128e 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -27,10 +27,12 @@ def __init__(self, host: str, configuration = swagger_client.Configuration() configuration.host = host configuration.access_token = nef_bearer_access_token - #todo: these endpoints should be found dynamically by the capif + service_discoverer = ServiceDiscoverer(folder_path_for_certificates_and_capif_api_key,capif_host,capif_https_port) configuration.available_endpoints = { - "MONITORING_SUBSCRIPTIONS": '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions', - "MONITORING_SUBSCRIPTION_SINGLE": '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}' + "MONITORING_SUBSCRIPTIONS": service_discoverer.retrieve_specific_resource_name("nef_emulator_endpoints", + "MONITORING_SUBSCRIPTIONS"), + "MONITORING_SUBSCRIPTION_SINGLE": service_discoverer.retrieve_specific_resource_name("nef_emulator_endpoints", + "MONITORING_SUBSCRIPTION_SINGLE"), } api_client = swagger_client.ApiClient(configuration=configuration) self.monitoring_event_api = MonitoringEventAPIApi(api_client) @@ -91,8 +93,8 @@ def delete_subscription(self, netapp_id: str, subscription_id: str): class LocationSubscriber(MonitoringSubscriber): - def __init__(self, host: str, - bearer_access_token: str, + def __init__(self, nef_url: str, + nef_bearer_access_token: str, folder_path_for_certificates_and_capif_api_key: str, capif_host:str, capif_https_port:int): @@ -102,10 +104,10 @@ def __init__(self, host: str, You can create subscriptions where each one of them can be used to track a device. A notification is sent to a callback url you will provide, everytime the user device changes Cell - :param str host: The url of the 5G-API - :param str bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API + :param str nef_url: The url of the 5G-API + :param str nef_bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API """ - super().__init__(host, bearer_access_token, + super().__init__(nef_url, nef_bearer_access_token, folder_path_for_certificates_and_capif_api_key, capif_host, capif_https_port) @@ -215,8 +217,8 @@ class MonitoringType(Enum): INFORM_WHEN_NOT_CONNECTED = 2 def __init__(self, - host: str, - bearer_access_token: str, + nef_url: str, + nef_bearer_access_token: str, folder_path_for_certificates_and_capif_api_key: str, capif_host:str, capif_https_port:int): @@ -229,14 +231,14 @@ def __init__(self, Connection is lost (for example the user device has not been connected to the 5G network for the past 10 seconds) Connection is alive (for example the user device has been connected to the 5G network for the past 10 seconds) - :param str host: The url of the 5G-API - :param str bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API + :param str nef_url: The url of the 5G-API + :param str nef_bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API :param folder_path_for_certificates_and_capif_api_key: The folder that contains the NetApp certificates and CAPIF API Key. These are created while registering and onboarding the NetApp to the CAPIF Server :param capif_host: The host of the CAPIF Server (ex. "capifcore") :param capif_https_port: The https_port of the CAPIF Server """ - super().__init__(host, bearer_access_token, + super().__init__(nef_url, nef_bearer_access_token, folder_path_for_certificates_and_capif_api_key, capif_host, capif_https_port) @@ -425,7 +427,7 @@ def get_reporting_mode(self): def get_reporting_configuration(self): return self.repetition_period_in_seconds - def __init__(self, host: str, + def __init__(self, nef_url: str, nef_bearer_access_token: str, folder_path_for_certificates_and_capif_api_key: str, capif_host:str, @@ -438,7 +440,7 @@ def __init__(self, host: str, A notification is sent to a callback url you will provide, informing you in case the QoS targets can no longer be full-filled. - :param host: The url of the 5G-API (ex. NEF emulator) + :param nef_url: The url of the 5G-API (ex. NEF emulator) :param nef_bearer_access_token: The bearer access token that will be used to authenticate with the 5G-API :param folder_path_for_certificates_and_capif_api_key: The folder that contains the NetApp certificates and CAPIF API Key. These are created while registering and onboarding the NetApp to the CAPIF Server @@ -447,13 +449,12 @@ def __init__(self, host: str, """ configuration = swagger_client.Configuration() - configuration.host = host + configuration.host = nef_url configuration.access_token = nef_bearer_access_token service_discoverer = ServiceDiscoverer(folder_path_for_certificates_and_capif_api_key,capif_host,capif_https_port) - #todo: these endpoints should be found dynamically by the capif configuration.available_endpoints = { - "QOS_SUBSCRIPTIONS": '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions', - "QOS_SUBSCRIPTION_SINGLE": '/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}' + "QOS_SUBSCRIPTIONS": service_discoverer.retrieve_specific_resource_name("nef_emulator_endpoints", "QOS_SUBSCRIPTIONS"), + "QOS_SUBSCRIPTION_SINGLE": service_discoverer.retrieve_specific_resource_name("nef_emulator_endpoints", "QOS_SUBSCRIPTION_SINGLE") } api_client = swagger_client.ApiClient(configuration=configuration) self.qos_api = SessionWithQoSAPIApi(api_client) @@ -1095,6 +1096,9 @@ def publish_services(self,service_api_description_json_full_path)->None: class ServiceDiscoverer: + class ServiceDiscovererException(Exception): + pass + def __init__(self, folder_path_for_certificates_and_api_key: str, capif_host:str, @@ -1132,6 +1136,29 @@ def discover_service_apis(self): response_payload = json.loads(response.text) return response_payload + def retrieve_specific_resource_name(self, api_name,resource_name): + """ + Can be used to locate specific resources inside APIS. + For example the NEF emulator exposes an api with name "nef_emulator_endpoints" that contains two resources (two endpoints) + 1. '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions' with resource name:MONITORING_SUBSCRIPTIONS + 2. '/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}' with resource name : MONITORING_SUBSCRIPTION_SINGLE + """ + capif_apifs = self.discover_service_apis() + nef_endpoints = (list(filter(lambda api: api["api_name"] == api_name , capif_apifs))) + if len(nef_endpoints)== 0: + raise ServiceDiscoverer.ServiceDiscovererException("Could not find available endpoints for api_name: " + + api_name + ".Make sure that a) your NetApp is registered and onboarded to CAPIF and b) the NEF emulator has been registered and onboarded to CAPIF") + else: + resources = nef_endpoints[0]["aef_profiles"][0]["versions"][0]["resources"] + uris = (list(filter(lambda resource: resource["resource_name"] == resource_name , resources))) + if len(uris)==0: + raise ServiceDiscoverer.ServiceDiscovererException("Could not find resource_name: "+ resource_name + "at api_name" + api_name) + else: + return uris[0]["uri"] + + + + diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index a859e89..898ee2c 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -1,62 +1,86 @@ { - "apiName": "api_name_2", - "aefProfiles": [ - { - "aefId": "UNIQUE_ID THAT IS SET AUTOMATICALLY BY THE SDK. Contains the API PROV DOM ID parameter", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "hello-endpoint", - "commType": "REQUEST_RESPONSE", - "uri": "/hello", - "custOpName": "string", - "operations": [ - "POST" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "POST" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["Oauth", "PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "the ip address where the exposer relies", - "port": 8086, - "securityMethods": ["Oauth"] - } - ] - } - ], - "description": "API of dummy netapp to test", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" + "apiName": "nef_emulator_endpoints", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2100-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "MONITORING_SUBSCRIPTIONS", + "commType": " SUBSCRIBE_NOTIFY", + "uri": "nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions", + "custOpName": "http_post", + "operations": ["GET","POST","PUT","DELETE"], + "description": "Endpoint to manage monitoring subscriptions" + }, + { + "resourceName": "MONITORING_SUBSCRIPTION_SINGLE", + "commType": " SUBSCRIBE_NOTIFY", + "uri": "/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions/{subscriptionId}", + "custOpName": "http_get", + "operations": [ "GET","POST" ], + "description": "Endpoint to manage single subscription" + }, + { + "resourceName": "QOS_SUBSCRIPTIONS", + "commType": " SUBSCRIBE_NOTIFY", + "uri": "/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions", + "custOpName": "http_post", + "operations": ["GET","POST","PUT","DELETE"], + "description": "Endpoint to manage monitoring subscriptions" + }, + { + "resourceName": "QOS_SUBSCRIPTION_SINGLE", + "commType": " SUBSCRIBE_NOTIFY", + "uri": "/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions/{subscriptionId}", + "custOpName": "http_get", + "operations": [ "GET","POST" ], + "description": "Endpoint to manage single subscription" + } + + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "POST" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["Oauth", "PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "127.0.0.1", + "port": 8888, + "securityMethods": ["Oauth"] + } ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "test" + } + ], + "description": "API of dummy netapp to test", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" } + diff --git a/examples/connection_monitor_examples.py b/examples/connection_monitor_examples.py index 9c32531..e43ca83 100644 --- a/examples/connection_monitor_examples.py +++ b/examples/connection_monitor_examples.py @@ -18,9 +18,11 @@ def showcase_create_subscription_and_retrieve_call_backs(): # Create a subscription, that will notify us 1000 times, for the next 1 day starting from now expire_time = (datetime.datetime.utcnow() + datetime.timedelta(days=1)).isoformat() + "Z" netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - connection_monitor = ConnectionMonitor(host, token.access_token) + connection_monitor = ConnectionMonitor(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port() ) # The following external identifier was copy pasted by the NEF emulator. Go to the Map and click on a User icon. There you can retrieve the id external_id = "10003@domain.com" @@ -82,9 +84,11 @@ def showcase_create_subscription_and_retrieve_call_backs(): def read_and_delete_all_existing_subscriptions(): # How to get all subscriptions netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - connection_monitor = ConnectionMonitor(host, token.access_token) + connection_monitor = ConnectionMonitor(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port()) try: all_subscriptions = connection_monitor.get_all_subscriptions(netapp_id, 0, 100) diff --git a/examples/emulator_examples.py b/examples/emulator_examples.py index 3f380bd..3e719e7 100644 --- a/examples/emulator_examples.py +++ b/examples/emulator_examples.py @@ -7,7 +7,7 @@ def showcase_login_to_the_emulator_and_test_token(): Demonstrate how to interact with the Emulator, to a token and the current logged in User """ - token = emulator_utils.get_token() + token = emulator_utils.get_token_for_nef_emulator() print("-----") print("Got token") print(token) diff --git a/examples/emulator_utils.py b/examples/emulator_utils.py index ed54f1f..69f3e68 100644 --- a/examples/emulator_utils.py +++ b/examples/emulator_utils.py @@ -3,7 +3,7 @@ from evolved5g.swagger_client.models import Token -def get_token() -> Token: +def get_token_for_nef_emulator() -> Token: username = "admin@my-email.com" password = "pass" @@ -11,7 +11,7 @@ def get_token() -> Token: # https://github.com/EVOLVED-5G/NEF_emulator configuration = swagger_client.Configuration() # The host of the 5G API (emulator) - configuration.host = get_host_of_the_nef_emulator() + configuration.host = get_url_of_the_nef_emulator() api_client = swagger_client.ApiClient(configuration=configuration) api_client.select_header_content_type(["application/x-www-form-urlencoded"]) api = LoginApi(api_client) @@ -21,11 +21,34 @@ def get_token() -> Token: def get_api_client(token) -> swagger_client.ApiClient: configuration = swagger_client.Configuration() - configuration.host = get_host_of_the_nef_emulator() + configuration.host = get_url_of_the_nef_emulator() configuration.access_token = token.access_token api_client = swagger_client.ApiClient(configuration=configuration) return api_client -def get_host_of_the_nef_emulator() -> str: +def get_url_of_the_nef_emulator() -> str: return "http://localhost:8888" + +def get_folder_path_for_certificated_and_capif_api_key()->str: + """ + This is the folder that was provided when you registered the NetApp to CAPIF. + It contains the certificates and the api.key needed to communicate with the CAPIF server + :return: + """ + return "/home/alex/Projects/test_certificate_folder" + +def get_capif_host()->str: + """ + When running CAPIF via docker (by running ./run.sh) you should have at your /etc/hosts the following record + 127.0.0.1 capifcore + :return: + """ + return "capifcore" + +def get_capif_https_port()->int: + """ + This is the default https port when running CAPIF via docker + :return: + """ + return 443 diff --git a/examples/location_subscriber_examples.py b/examples/location_subscriber_examples.py index 9561656..fefdd83 100644 --- a/examples/location_subscriber_examples.py +++ b/examples/location_subscriber_examples.py @@ -18,13 +18,12 @@ def showcase_create_subscription_and_retrieve_call_backs(): # Create a subscription, that will notify us 1000 times, for the next 1 day starting from now expire_time = (datetime.datetime.utcnow() + datetime.timedelta(days=1)).isoformat() + "Z" netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - location_subscriber = LocationSubscriber(host=host, - bearer_access_token=token.access_token, - folder_path_for_certificates_and_capif_api_key="", - capif_host="capifcore", - capif_https_port=443) + + location_subscriber = LocationSubscriber(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port()) # The following external identifier was copy pasted by the NEF emulator. Go to the Map and click on a User icon. There you can retrieve the id external_id = "10003@domain.com" @@ -63,9 +62,12 @@ def showcase_create_single_request_for_location_info(): """ netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - location_subscriber = LocationSubscriber(host, token.access_token) + + location_subscriber = LocationSubscriber(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port()) # The following external identifier was copy pasted by the NEF emulator. Go to the Map and click on a User icon. There you can retrieve the id external_id = "10003@domain.com" @@ -86,9 +88,11 @@ def showcase_create_single_request_for_location_info(): def read_and_delete_all_existing_subscriptions(): # How to get all subscriptions netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - location_subscriber = LocationSubscriber(host, token.access_token) + location_subscriber = LocationSubscriber(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port()) try: all_subscriptions = location_subscriber.get_all_subscriptions(netapp_id, 0, 100) @@ -107,7 +111,7 @@ def read_and_delete_all_existing_subscriptions(): if __name__ == "__main__": - #read_and_delete_all_existing_subscriptions() + read_and_delete_all_existing_subscriptions() showcase_create_subscription_and_retrieve_call_backs() read_and_delete_all_existing_subscriptions() showcase_create_single_request_for_location_info() diff --git a/examples/qos_awereness_examples.py b/examples/qos_awereness_examples.py index ee0eb6c..19501a1 100644 --- a/examples/qos_awereness_examples.py +++ b/examples/qos_awereness_examples.py @@ -17,9 +17,12 @@ def showcase_create_quaranteed_bit_rate_subscription_for_conversational_voice(): A testing local webserver (Flask webserver) can be initiated by running the examples/api.py """ netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() - qos_awereness = QosAwareness(host, token.access_token) + + qos_awereness = QosAwareness(nef_url=emulator_utils.get_url_of_the_nef_emulator(), + nef_bearer_access_token= emulator_utils.get_token_for_nef_emulator().access_token, + folder_path_for_certificates_and_capif_api_key=emulator_utils.get_folder_path_for_certificated_and_capif_api_key(), + capif_host=emulator_utils.get_capif_host(), + capif_https_port=emulator_utils.get_capif_https_port()) # The following external identifier was copy pasted by the NEF emulator. # Go to the Map and hover over a User icon.There you can retrieve the id address. # Notice that the NEF emulator is able to establish a guaranteed bit rate only if one and only one user is connected to a shell @@ -95,8 +98,8 @@ def showcase_create_non_quaranteed_bit_rate_subscription_for_live_streaming(): # Create a subscription, that will notify us 1000 times, for the next 1 day starting from now netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() + host = emulator_utils.get_url_of_the_nef_emulator() + token = emulator_utils.get_token_for_nef_emulator() qos_awereness = QosAwareness(host, token.access_token) # The following external identifier was copy pasted by the NEF emulator. Go to the Map and hover over a User icon. # There you can retrieve the id address @@ -142,8 +145,8 @@ def showcase_create_non_quaranteed_bit_rate_subscription_for_live_streaming(): def read_and_delete_all_existing_subscriptions(): # How to get all subscriptions netapp_id = "myNetapp" - host = emulator_utils.get_host_of_the_nef_emulator() - token = emulator_utils.get_token() + host = emulator_utils.get_url_of_the_nef_emulator() + token = emulator_utils.get_token_for_nef_emulator() qos_awareness = QosAwareness(host, token.access_token) try: From 7fe050c5e6fafa52113094a75049035660fdae68 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 27 Oct 2022 20:12:12 +0300 Subject: [PATCH 17/20] improve the examples, update the history and the documentation --- HISTORY.rst | 2 ++ docs/source/libraries.rst | 7 +++++++ evolved5g/__init__.py | 2 +- examples/connection_monitor_examples.py | 8 +++++--- examples/location_subscriber_examples.py | 8 +++++--- examples/qos_awereness_examples.py | 11 +++++------ setup.cfg | 2 +- setup.py | 2 +- 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index c7aa4eb..54ef8b4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,8 @@ ======= History ======= +0.8.4 (2022-10-27) +* The SDK Library now communicates first with CAPIF server in order to discover the NEF endpoints 0.8.3 (2022-10-17) ------------------- diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index edb0ef0..b0ba15f 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -43,6 +43,13 @@ Install the requirements_dev.txt Make sure you have initiated the NEF_EMULATOR at url :py:func:`http://localhost:8888` (See `here `_ for instructions), you have logged in to the interface, clicked on the map and have started the simulation. +Make sure that your NetApp has been registered and onboarded to CAPIF. If this process is completed, then in the specified folder the following files should be present + + - ca.crt + - capif_api_details.json + - private.key + - your_common_name_you_specified.crt + Then run a webserver in order to capture the callback post requests from NEF EMULATOR: On the terminal run the following commands to initialize the webserver. diff --git a/evolved5g/__init__.py b/evolved5g/__init__.py index aa68a47..fc9881a 100644 --- a/evolved5g/__init__.py +++ b/evolved5g/__init__.py @@ -1,7 +1,7 @@ """Top-level package for Evolved5G_CLI.""" __author__ = "EVOLVED5G project" -__version__ = '0.8.3' +__version__ = '0.8.4' # Uncomment next lines to give direct import access to modules #from . import cli diff --git a/examples/connection_monitor_examples.py b/examples/connection_monitor_examples.py index e43ca83..6a6ed60 100644 --- a/examples/connection_monitor_examples.py +++ b/examples/connection_monitor_examples.py @@ -10,9 +10,11 @@ def showcase_create_subscription_and_retrieve_call_backs(): """ This example showcases how you can create a subscription to the 5G-API in order to monitor devices that are connected or disconnected to the network. - In order to run this example you need to follow the instructions in readme.md in order to a) run the NEF emulator - and b) run a local webserver that will print the notifications it retrieves from the emulator. - A testing local webserver (Flask webserver) can be initiated by running the examples/api.py + In order to run this example, to follow the instructions in readme.md (https://evolved5g-cli.readthedocs.io/en/latest/libraries.html) in order to + a) run the NEF emulator + b) run the CAPIF server + c) connect your NetAPP to the CAPIF server (you have to do this only once) + d) run a local webserver that will print the notifications it retrieves from the emulator. A testing local webserver (Flask webserver) can be initiated by running the examples/api.py """ # Create a subscription, that will notify us 1000 times, for the next 1 day starting from now diff --git a/examples/location_subscriber_examples.py b/examples/location_subscriber_examples.py index fefdd83..c326194 100644 --- a/examples/location_subscriber_examples.py +++ b/examples/location_subscriber_examples.py @@ -10,9 +10,11 @@ def showcase_create_subscription_and_retrieve_call_backs(): """ This example showcases how you can create a subscription to the 5G-API in order to monitor device location. - In order to run this example you need to follow the instructions in readme.md in order to a) run the NEF emulator - and b) run a local webserver that will print the location notifications it retrieves from the emulator. - A testing local webserver (Flask webserver) can be initiated by running the examples/api.py + In order to run this example, to follow the instructions in readme.md (https://evolved5g-cli.readthedocs.io/en/latest/libraries.html) in order to + a) run the NEF emulator + b) run the CAPIF server + c) connect your NetAPP to the CAPIF server (you have to do this only once) + d) run a local webserver that will print the location notifications it retrieves from the emulator. A testing local webserver (Flask webserver) can be initiated by running the examples/api.py """ # Create a subscription, that will notify us 1000 times, for the next 1 day starting from now diff --git a/examples/qos_awereness_examples.py b/examples/qos_awereness_examples.py index 19501a1..7fc2d9d 100644 --- a/examples/qos_awereness_examples.py +++ b/examples/qos_awereness_examples.py @@ -4,17 +4,16 @@ import emulator_utils from evolved5g.swagger_client import UsageThreshold - - def showcase_create_quaranteed_bit_rate_subscription_for_conversational_voice(): """ This example showcases how you can create a subscription to the 5G-API in order to establish a Guaranteed Bit Rate (NON-GBR) QoS. - In order to run this example you need to follow the instructions in readme.md in order to - a) run the NEF emulator and - b) run a local webserver that will print the location notifications it retrieves from the emulator. - A testing local webserver (Flask webserver) can be initiated by running the examples/api.py + In order to run this example, to follow the instructions in readme.md (https://evolved5g-cli.readthedocs.io/en/latest/libraries.html) in order to + a) run the NEF emulator + b) run the CAPIF server + c) connect your NetAPP to the CAPIF server (you have to do this only once) + d) run a local webserver that will print the notifications it retrieves from the emulator. A testing local webserver (Flask webserver) can be initiated by running the examples/api.py """ netapp_id = "myNetapp" diff --git a/setup.cfg b/setup.cfg index 1e6b2f1..7d57281 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.3 +current_version = 0.8.4 commit = True tag = True diff --git a/setup.py b/setup.py index 238308e..fedb978 100644 --- a/setup.py +++ b/setup.py @@ -46,6 +46,6 @@ test_suite='tests', tests_require=test_requirements, url='https://github.com/EVOLVED-5G/SDK-CLI', - version='0.8.3', + version='0.8.4', zip_safe=False, ) From c9a2ef2fa061cb80eb0f732a5cac27cd381899f7 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 27 Oct 2022 20:53:56 +0300 Subject: [PATCH 18/20] bug fixes --- evolved5g/sdk.py | 3 +++ .../swagger_client/api/monitoring_event_api_api.py | 10 +++++----- .../service_api_description.json | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index caf128e..48d1544 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -1154,6 +1154,9 @@ def retrieve_specific_resource_name(self, api_name,resource_name): if len(uris)==0: raise ServiceDiscoverer.ServiceDiscovererException("Could not find resource_name: "+ resource_name + "at api_name" + api_name) else: + #url = "http://" + nef_endpoints[0]["aef_profiles"][0]["interface_descriptions"][0]["ipv4_addr"] + #url = url + ":" + str(nef_endpoints[0]["aef_profiles"][0]["interface_descriptions"][0]["port"])+"/" + #url = url +uris[0]["uri"] return uris[0]["uri"] diff --git a/evolved5g/swagger_client/api/monitoring_event_api_api.py b/evolved5g/swagger_client/api/monitoring_event_api_api.py index 2b523a0..06eef75 100644 --- a/evolved5g/swagger_client/api/monitoring_event_api_api.py +++ b/evolved5g/swagger_client/api/monitoring_event_api_api.py @@ -124,7 +124,7 @@ def create_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_p auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - self.api_client.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'POST', + self.api_client.configuration.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'POST', path_params, query_params, header_params, @@ -233,7 +233,7 @@ def delete_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_s auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'DELETE', + self.api_client.configuration.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'DELETE', path_params, query_params, header_params, @@ -336,7 +336,7 @@ def read_active_subscriptions_api_v13gpp_monitoring_event_v1_scs_as_id_subscript auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - self.api_client.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'GET', + self.api_client.configuration.available_endpoints["MONITORING_SUBSCRIPTIONS"], 'GET', path_params, query_params, header_params, @@ -439,7 +439,7 @@ def read_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_sub auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'GET', + self.api_client.configuration.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'GET', path_params, query_params, header_params, @@ -554,7 +554,7 @@ def update_subscription_api_v13gpp_monitoring_event_v1_scs_as_id_subscriptions_s auth_settings = ['OAuth2PasswordBearer'] # noqa: E501 return self.api_client.call_api( - self.api_client.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'PUT', + self.api_client.configuration.available_endpoints["MONITORING_SUBSCRIPTION_SINGLE"], 'PUT', path_params, query_params, header_params, diff --git a/examples/capif_exposer_sample_files/service_api_description.json b/examples/capif_exposer_sample_files/service_api_description.json index 898ee2c..27f1ea4 100644 --- a/examples/capif_exposer_sample_files/service_api_description.json +++ b/examples/capif_exposer_sample_files/service_api_description.json @@ -11,7 +11,7 @@ { "resourceName": "MONITORING_SUBSCRIPTIONS", "commType": " SUBSCRIBE_NOTIFY", - "uri": "nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions", + "uri": "/nef/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions", "custOpName": "http_post", "operations": ["GET","POST","PUT","DELETE"], "description": "Endpoint to manage monitoring subscriptions" From 505b9731f6f13639c67b693cfca101d4de1a5ab0 Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Thu, 27 Oct 2022 20:54:22 +0300 Subject: [PATCH 19/20] bug fixes --- evolved5g/sdk.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/evolved5g/sdk.py b/evolved5g/sdk.py index 48d1544..caf128e 100644 --- a/evolved5g/sdk.py +++ b/evolved5g/sdk.py @@ -1154,9 +1154,6 @@ def retrieve_specific_resource_name(self, api_name,resource_name): if len(uris)==0: raise ServiceDiscoverer.ServiceDiscovererException("Could not find resource_name: "+ resource_name + "at api_name" + api_name) else: - #url = "http://" + nef_endpoints[0]["aef_profiles"][0]["interface_descriptions"][0]["ipv4_addr"] - #url = url + ":" + str(nef_endpoints[0]["aef_profiles"][0]["interface_descriptions"][0]["port"])+"/" - #url = url +uris[0]["uri"] return uris[0]["uri"] From 8f956684658cb9cf72c00c0fba934f4d094f9d8e Mon Sep 17 00:00:00 2001 From: AlexJoom Date: Mon, 31 Oct 2022 12:13:31 +0200 Subject: [PATCH 20/20] fix title at History.rst --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index 54ef8b4..067434a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,7 @@ History ======= 0.8.4 (2022-10-27) +------------------- * The SDK Library now communicates first with CAPIF server in order to discover the NEF endpoints 0.8.3 (2022-10-17)