diff --git a/docs/clmc-service.md b/docs/clmc-service.md index 7b1cc1d0d54d7b1731d2131b15885c5bbf26a9c8..2ffd82e68fa8d038bcb531b901770d455275d8aa 100644 --- a/docs/clmc-service.md +++ b/docs/clmc-service.md @@ -336,50 +336,50 @@ configuration files of the service can be found in the **src/service** folder. [ { "location": "location_1", + "server": "location_1", "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - }, + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + }, { "location": "location_2", + "server": "location_2", "sfc": "sfc_2", - "sfc_i": "sfc_i_2", - "sf": "sf_2", - "sf_i": "sf_i_2", - "sf_endpoint": "sf_endpoint_2", - "sr": "sr_2" - } + "sfc_instance": "sfc_i_2", + "sf_package": "sf_2", + "sf": "sf_i_2", + "sf_endpoint": "sf_endpoint_2" + } ] ``` -* **GET** ***/whoami/endpoints/instance?sr={sr_id}&sf_i={sf_instance_id}&sf_endpoint={sf_endpoint_id}*** +* **GET** ***/whoami/endpoints/instance?sf_endpoint={sf_endpoint_id}*** - This API method retrieves the uniquely defined service function endpoint configuration associated with the given URL parameters - sr, sf_i and sf_endpoint. + This API method retrieves the uniquely defined service function endpoint configuration associated with the given URL parameter - sf_endpoint. * Response: Returns a JSON-formatted response - a JSON object representing the service function endpoint configuration if it exists. - Returns a 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameters. + Returns a 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameter. - Returns a 400 Bad Request error if the url parameters are invalid. + Returns a 400 Bad Request error if the url parameter is invalid or missing. * Response Body Example: - - Request made to /whoami/endpoints/instance?sr=sr_1&sf_i=sf_i_1&sf_endpoint=sf_endpoint_1 + - Request made to /whoami/endpoints/instance?sf_endpoint=sf_endpoint_1 ```json - { - "location": "location_1", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } + { + "location": "location_1", + "server": "location_1", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } ``` * **POST** ***/whoami/endpoints*** @@ -392,17 +392,17 @@ configuration files of the service can be found in the **src/service** folder. * Request Body Example: - ```json - { - "location": "location_1", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } - ``` + ```json + { + "location": "location_1", + "server": "location_1", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } + ``` * Response @@ -410,25 +410,25 @@ configuration files of the service can be found in the **src/service** folder. Returns a 400 Bad Request error if the request body is invalid. - Returns a 409 Conflict error if there exists another service function endpoint configuration with the same 'sr', 'sf_i' and 'sf_endpoint' values. + Returns a 409 Conflict error if there exists another service function endpoint configuration with the same 'sf_endpoint' ID. * Response Body Example: - ```json - { - "location": "location_1", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } - ``` + ```json + { + "location": "location_1", + "server": "location_1", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } + ``` -* **PUT** ***/whoami/endpoints/instance?sr={sr_id}&sf_i={sf_instance_id}&sf_endpoint={sf_endpoint_id}*** +* **PUT** ***/whoami/endpoints/instance?sf_endpoint={sf_endpoint_id}*** - This API method replaces the uniquely defined service function endpoint configuration associated with the given URL parameters - sr, sf_i and sf_endpoint with a new service + This API method replaces the uniquely defined service function endpoint configuration associated with the given URL parameter - sf_endpoint, with a new service function endpoint configuration given in the request body (JSON format). It can also be used for updating. * Request: @@ -437,17 +437,17 @@ configuration files of the service can be found in the **src/service** folder. * Request Body Example: - ```json - { - "location": "location_2", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } - ``` + ```json + { + "location": "location_2", + "server": "location_2", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } + ``` * Response @@ -455,50 +455,52 @@ configuration files of the service can be found in the **src/service** folder. Returns a 400 Bad Request error if the request body is invalid. - Returns a 400 Bad Request error if the url parameters are invalid. + Returns a 400 Bad Request error if the url parameter is invalid. - Returns an 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameters. + Returns an 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameter. - Returns a 409 Conflict error if there exists another service function endpoint configuration with the same 'sr', 'sf_i' and 'sf_endpoint' values as the ones in the request body. + Returns a 409 Conflict error if there exists another service function endpoint configuration with the same 'sf_endpoint' ID as the ones in the request body. * Response Body Example: - - Request made to /whoami/endpoints/instance?sr=sr_1&sf_i=sf_i_1&sf_endpoint=sf_endpoint_1 + - Request made to /whoami/endpoints/instance?sf_endpoint=sf_endpoint_1 + ```json - { - "location": "location_2", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } - ``` + { + "location": "location_2", + "server": "location_2", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } + ``` -* **DELETE** ***/whoami/endpoints/instance?sr={sr_id}&sf_i={sf_instance_id}&sf_endpoint={sf_endpoint_id}*** +* **DELETE** ***/whoami/endpoints/instance?sf_endpoint={sf_endpoint_id}*** - This API method deletes the uniquely defined service function endpoint configuration associated with the given URL parameters - sr, sf_i and sf_endpoint. + This API method deletes the uniquely defined service function endpoint configuration associated with the given URL parameter - sf_endpoint. * Response: Returns the JSON representation of the deleted object. - Returns an 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameters. + Returns an 404 Not Found error if there is no service function endpoint configuration associated with the given URL parameter. - Returns a 400 Bad Request error if the url parameters are invalid. + Returns a 400 Bad Request error if the url parameter is invalid. * Response Body Example: - - Request made to /whoami/endpoints/instance?sr=sr_1&sf_i=sf_i_1&sf_endpoint=sf_endpoint_1 + - Request made to /whoami/endpoints/instance?sf_endpoint=sf_endpoint_1 + ```json - { - "location": "location_1", - "sfc": "sfc_1", - "sfc_i": "sfc_i_1", - "sf": "sf_1", - "sf_i": "sf_i_1", - "sf_endpoint": "sf_endpoint_1", - "sr": "sr_1" - } + { + "location": "location_1", + "server": "location_1", + "sfc": "sfc_1", + "sfc_instance": "sfc_i_1", + "sf_package": "sf_1", + "sf": "sf_i_1", + "sf_endpoint": "sf_endpoint_1" + } ``` diff --git a/src/service/clmcservice/models/whoami_models.py b/src/service/clmcservice/models/whoami_models.py index 30466ccfeb4ad77ad7c13a020e1664f1f67f33fe..3fdc01ea7030c777e57aca94facc765eca0a2ab9 100644 --- a/src/service/clmcservice/models/whoami_models.py +++ b/src/service/clmcservice/models/whoami_models.py @@ -33,17 +33,15 @@ class ServiceFunctionEndpoint(Base): __tablename__ = 'sfendpoint' # table name in the PostgreSQL database - __table_args__ = (UniqueConstraint('sf_i', 'sf_endpoint', 'sr'),) # defines a unique constraint across 3 columns - sf_i, sf_endpoint, sr + __table_args__ = (UniqueConstraint('sf', 'sf_endpoint'),) # defines a unique constraint across 2 columns - sf, sf_endpoint - uid = Column(Integer, primary_key=True, autoincrement=True, nullable=False) # a primary key integer field (auto incremented) - - location = Column(String, nullable=False) # cluster label + server = Column(String, nullable=False) # cluster label + location = Column(String, nullable=False) # location label sfc = Column(String, nullable=False) # service function chain label - sfc_i = Column(String, nullable=False) # service function chain instance identifier - sf = Column(String, nullable=False) # service function label - sf_i = Column(String, nullable=False) # service function identifier (potentially FQDN) - sf_endpoint = Column(String, nullable=False) # service function endpoint (potentially IP address) - sr = Column(String, nullable=False) # service router ID - service router that connects the VM to FLAME + sfc_instance = Column(String, nullable=False) # service function chain instance identifier + sf_package = Column(String, nullable=False) # service function package label + sf = Column(String, nullable=False) # service function node defined in the TOSCA resource specification + sf_endpoint = Column(String, nullable=False, primary_key=True) # service function endpoint (FQDN(s) + IP address) @property def json(self): @@ -54,52 +52,29 @@ class ServiceFunctionEndpoint(Base): """ fields = {c.name: getattr(self, c.name) for c in self.__table__.columns} - fields.pop("uid") return fields @staticmethod - def required_columns(): - """ - Returns the required columns for constructing a valid instance. - - :return: a generator object + def get(sf_endpoint): """ + Gets the service function endpoint object or None if not existing. - return tuple(column.name for column in ServiceFunctionEndpoint.__table__.columns if column.name != "uid") - - @staticmethod - def constrained_columns(): - """ - :return: the columns that are uniquely identifying an instance of this model. - """ - - return tuple(column.name for column in ServiceFunctionEndpoint.__table_args__[0].columns) - - @staticmethod - def get(sf_i, sf_endpoint, sr): - """ - Gets the instance matching the unique constraint or None if not existing. - - :param sf_i: service function instance :param sf_endpoint: service function endpoint - :param sr: service router - :return: the first object from the result set that matches the unique constraint or None + :return: the first object from the result set that matches the unique constraint (should be only one) or None """ - return ServiceFunctionEndpoint.query().filter(and_(ServiceFunctionEndpoint.sf_i == sf_i, ServiceFunctionEndpoint.sf_endpoint == sf_endpoint, ServiceFunctionEndpoint.sr == sr)).first() + return ServiceFunctionEndpoint.query().filter(ServiceFunctionEndpoint.sf_endpoint == sf_endpoint).first() @staticmethod - def exists(sf_i, sf_endpoint, sr): + def exists(sf_endpoint): """ - Checks if an instance matching the unique constraint exists. + Checks if an instance matching the sf_endpoint ID exists. - :param sf_i: service function instance - :param sf_endpoint: service function endpoint - :param sr: service router + :param sf_endpoint: service function endpoint ID to check :return: True if exists, False otherwise """ - return ServiceFunctionEndpoint.get(sf_i, sf_endpoint, sr) is not None + return ServiceFunctionEndpoint.get(sf_endpoint) is not None diff --git a/src/service/clmcservice/whoamiapi/tests.py b/src/service/clmcservice/whoamiapi/tests.py index f50886616960d4c6fb8c24425895757057e69525..9c6238c45b6fc8efb32c815d2b62961c06ccc953 100644 --- a/src/service/clmcservice/whoamiapi/tests.py +++ b/src/service/clmcservice/whoamiapi/tests.py @@ -57,7 +57,7 @@ class TestWhoamiAPI(object): response = WhoamiAPI(request).get_all() assert response == [], "Initially there mustn't be any service function endpoint configurations in the database." - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(server="DC1", location="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") expected_response_data = [sf_e.json] ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database @@ -65,10 +65,10 @@ class TestWhoamiAPI(object): response = WhoamiAPI(request).get_all() assert response == expected_response_data, "Incorrect response data with 1 service function endpoint configuration." - sf_e = ServiceFunctionEndpoint(location="DC2", sfc="sfc2", sfc_i="sfc_i2", sf="sf2", sf_i="sf_i2", sf_endpoint="sf_endpoint2", sr="sr2") + sf_e = ServiceFunctionEndpoint(server="DC2", location="DC2", sfc="sfc2", sfc_instance="sfc_i2", sf_package="sf2", sf="sf_i2", sf_endpoint="sf_endpoint2") expected_response_data.append(sf_e.json) ServiceFunctionEndpoint.add(sf_e) - sf_e = ServiceFunctionEndpoint(location="DC3", sfc="sfc3", sfc_i="sfc_i3", sf="sf3", sf_i="sf_i3", sf_endpoint="sf_endpoint3", sr="sr3") + sf_e = ServiceFunctionEndpoint(server="DC3", location="DC3", sfc="sfc3", sfc_instance="sfc_i3", sf_package="sf3", sf="sf_i3", sf_endpoint="sf_endpoint3") expected_response_data.append(sf_e.json) ServiceFunctionEndpoint.add(sf_e) @@ -87,21 +87,17 @@ class TestWhoamiAPI(object): self._validation_of_url_parameters_test("get_one") - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") expected_response_data = sf_e.json ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" response = WhoamiAPI(request).get_one() assert response == expected_response_data, "Invalid data returned in the response of GET instance" request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint2" - request.params["sf_i"] = "sf_i2" - request.params["sr"] = "sr2" error_raised = False try: WhoamiAPI(request).get_one() @@ -118,13 +114,13 @@ class TestWhoamiAPI(object): response = WhoamiAPI(request).get_all() assert response == [], "Initially there mustn't be any service function endpoint configurations in the database." - resource = dict(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + resource = dict(server="DC1", location="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") json_data = dumps(resource) request = testing.DummyRequest() request.body = json_data.encode(request.charset) response = WhoamiAPI(request).post() assert response == resource, "POST request must return the created resource" - assert ServiceFunctionEndpoint.exists("sf_i1", "sf_endpoint1", "sr1"), "POST request must have created the resource" + assert ServiceFunctionEndpoint.exists("sf_endpoint1"), "POST request must have created the resource" resource["location"] = "DC2" json_data = dumps(resource) @@ -138,11 +134,11 @@ class TestWhoamiAPI(object): assert error_raised, "An error must be raised when trying to create a resource which breaks the unique constraint" @pytest.mark.parametrize("body, valid", [ - ('{"location": "DC1", "sfc": "sfc1", "sfc_i": "sfc_i1", "sf": "sf1", "sf_i": "sf_i1", "sf_endpoint": "sf_endpoint1", "sr": "sr1"}', True), - ('{"location": "DC2", "sfc": "sfc2", "sfc_i": "sfc_i2", "sf": "sf2", "sf_i": "sf_i2", "sf_endpoint": "sf_endpoint2", "sr": "sr2"}', True), + ('{"location": "DC1", "server": "DC1", "sfc": "sfc1", "sfc_instance": "sfc_i1", "sf_package": "sf1", "sf": "sf_i1", "sf_endpoint": "sf_endpoint1"}', True), + ('{"location": "DC2", "server": "DC2", "sfc": "sfc2", "sfc_instance": "sfc_i2", "sf_package": "sf2", "sf": "sf_i2", "sf_endpoint": "sf_endpoint2"}', True), ('{}', False), - ('{"location": "DC1", "sfc": "sfc1", "sfc_i": "sfc_i1", "sf": "sf1", "sf_i": "sf_i1"}', False), - ('{"place": "DC2", "sfc": "sfc2", "sfc_i": "sfc_i2", "sf": "sf2", "sf_i": "sf_i2", "sf_endpoint": "sf_endpoint2", "sr": "sr2"}', False), + ('{"location": "DC1", "server": "DC1", "sfc": "sfc1", "sfc_instance": "sfc_i1", "sf_package": "sf1", "sf": "sf_i1"}', False), + ('{"place": "DC2", "server": "DC2", "sfc": "sfc2", "sfc_instance": "sfc_i2", "sf_package": "sf2", "sf": "sf_i2", "sf_endpoint": "sf_endpoint2"}', False), ('{invalid json}', False), ]) def test_post_body_validation(self, body, valid): @@ -173,12 +169,10 @@ class TestWhoamiAPI(object): self._validation_of_url_parameters_test("put") - resource = dict(location="location1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + resource = dict(location="location1", server="location1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") body = dumps(resource) request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" request.body = body.encode(request.charset) error_raised = False try: @@ -187,41 +181,35 @@ class TestWhoamiAPI(object): error_raised = True assert error_raised, "Not found error must be raised in case of a non existing service function endpoint" - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database - resource = dict(location="location1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + resource = dict(location="location1", server="location1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") body = dumps(resource) request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" request.body = body.encode(request.charset) response = WhoamiAPI(request).put() assert response == resource, "PUT request must return the updated resource" - assert ServiceFunctionEndpoint.get("sf_i1", "sf_endpoint1", "sr1").json["location"] == "location1" + assert ServiceFunctionEndpoint.get("sf_endpoint1").json["location"] == "location1" - resource = dict(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i2", sf_endpoint="sf_endpoint2", sr="sr2") + resource = dict(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i2", sf_endpoint="sf_endpoint2") body = dumps(resource) request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" request.body = body.encode(request.charset) response = WhoamiAPI(request).put() assert response == resource, "PUT request must return the updated resource" - assert not ServiceFunctionEndpoint.exists("sf_i1", "sf_endpoint1", "sr1"), "Resource has not been updated" - assert ServiceFunctionEndpoint.exists("sf_i2", "sf_endpoint2", "sr2"), "Resource has not been updated" + assert not ServiceFunctionEndpoint.exists("sf_endpoint1"), "Resource has not been updated" + assert ServiceFunctionEndpoint.exists("sf_endpoint2"), "Resource has not been updated" - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database - resource = dict(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i2", sf_endpoint="sf_endpoint2", sr="sr2") + resource = dict(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i2", sf_endpoint="sf_endpoint2") body = dumps(resource) request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" request.body = body.encode(request.charset) error_raised = False try: @@ -231,11 +219,11 @@ class TestWhoamiAPI(object): assert error_raised, "PUT request breaks unique constraint" @pytest.mark.parametrize("body, valid", [ - ('{"location": "DC1", "sfc": "sfc1", "sfc_i": "sfc_i1", "sf": "sf1", "sf_i": "sf_i1", "sf_endpoint": "sf_endpoint1", "sr": "sr1"}', True), - ('{"location": "DC2", "sfc": "sfc2", "sfc_i": "sfc_i2", "sf": "sf2", "sf_i": "sf_i2", "sf_endpoint": "sf_endpoint2", "sr": "sr2"}', True), + ('{"location": "DC1", "server": "DC1", "sfc": "sfc1", "sfc_instance": "sfc_i1", "sf_package": "sf1", "sf": "sf_i1", "sf_endpoint": "sf_endpoint1"}', True), + ('{"location": "DC2", "server": "DC2", "sfc": "sfc2", "sfc_instance": "sfc_i2", "sf_package": "sf2", "sf": "sf_i2", "sf_endpoint": "sf_endpoint2"}', True), ('{}', False), - ('{"location": "DC1", "sfc": "sfc1", "sfc_i": "sfc_i1", "sf": "sf1", "sf_i": "sf_i1"}', False), - ('{"place": "DC2", "sfc": "sfc2", "sfc_i": "sfc_i2", "sf": "sf2", "sf_i": "sf_i2", "sf_endpoint": "sf_endpoint2", "sr": "sr2"}', False), + ('{"location": "DC1", "server": "DC1", "sfc": "sfc1", "sfc_instance": "sfc_i1", "sf_package": "sf1", "sf": "sf_i1"}', False), + ('{"place": "DC2", "server": "DC2", "sfc": "sfc2", "sfc_instance": "sfc_i2", "sf_package": "sf2", "sf": "sf_i2", "sf_endpoint": "sf_endpoint2"}', False), ('{invalid json}', False), ]) def test_put_body_validation(self, body, valid): @@ -246,20 +234,19 @@ class TestWhoamiAPI(object): :param valid: True if body is valid, False otherwise """ - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" request.body = body.encode(request.charset) error_raised = False try: WhoamiAPI(request).put() except HTTPBadRequest: error_raised = True - assert error_raised == (not valid), "An error must be raised in case of an invalid request body" + + assert error_raised == (not valid) def test_delete(self): """ @@ -272,25 +259,21 @@ class TestWhoamiAPI(object): self._validation_of_url_parameters_test("delete") - sf_e = ServiceFunctionEndpoint(location="DC1", sfc="sfc1", sfc_i="sfc_i1", sf="sf1", sf_i="sf_i1", sf_endpoint="sf_endpoint1", sr="sr1") + sf_e = ServiceFunctionEndpoint(location="DC1", server="DC1", sfc="sfc1", sfc_instance="sfc_i1", sf_package="sf1", sf="sf_i1", sf_endpoint="sf_endpoint1") to_delete = sf_e.json ServiceFunctionEndpoint.add(sf_e) # adds the new instance of the model to the database - assert ServiceFunctionEndpoint.exists("sf_i1", "sf_endpoint1", "sr1") + assert ServiceFunctionEndpoint.exists("sf_endpoint1") request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" response = WhoamiAPI(request).delete() assert response == to_delete, "DELETE must return the deleted object if successful" - assert not ServiceFunctionEndpoint.exists("sf_i1", "sf_endpoint1", "sr1"), "Resource must be deleted after the delete API method has been called." + assert not ServiceFunctionEndpoint.exists("sf_endpoint1"), "Resource must be deleted after the delete API method has been called." request = testing.DummyRequest() request.params["sf_endpoint"] = "sf_endpoint1" - request.params["sf_i"] = "sf_i1" - request.params["sr"] = "sr1" error_raised = False try: WhoamiAPI(request).delete() @@ -321,12 +304,10 @@ class TestWhoamiAPI(object): getattr(WhoamiAPI(request), method).__call__() except HTTPBadRequest: error_raised = True - assert error_raised, "Error must be raised in case of insufficient number of arguments" + assert error_raised, "Error must be raised in case of wrong arguments" request = testing.DummyRequest() request.params["sf_endp"] = "sf_endpoint" # argument should be sf_endpoint - request.params["sf_i"] = "sf_i" - request.params["sr"] = "sr" try: getattr(WhoamiAPI(request), method).__call__() except HTTPBadRequest: diff --git a/src/service/clmcservice/whoamiapi/utilities.py b/src/service/clmcservice/whoamiapi/utilities.py index fd141d6025c333eb4e32485d9004a43444a7844c..0ee493671cc0ad6f1a989821ce98df5d70bacaa6 100644 --- a/src/service/clmcservice/whoamiapi/utilities.py +++ b/src/service/clmcservice/whoamiapi/utilities.py @@ -31,37 +31,21 @@ def validate_sfendpoint_body(body): Validates the request body used to create an endpoint configuration resource in the database. :param body: the request body to validate + :return the validated configuration dictionary object + :raise AssertionError: if the body is not a valid configuration """ try: body = loads(body) - except: + except Exception: raise AssertionError("Configuration must be a JSON object.") - # the database table has one more column which is a UID integer - assert len(body) == len(ServiceFunctionEndpoint.__table__.columns) - 1, "Endpoint configuration mustn't contain a different number of attributes than the number of required ones." + assert len(body) == len(ServiceFunctionEndpoint.__table__.columns), "Endpoint configuration mustn't contain a different number of attributes than the number of required ones." # validate that all required attributes are given in the body - for attribute in ServiceFunctionEndpoint.required_columns(): - assert attribute in body, "Required attribute not found in the request content." + for attribute in ServiceFunctionEndpoint.__table__.columns: + assert attribute.name in body, "Required attribute not found in the request content." return body - - -def validate_sfendpoint_params(params): - """ - Validates the request parameters to retrieve an endpoint configuration resource from the database. - - :param params: the parameters dictionary to validate - :return: the validated parameters - :raise AssertionError: for invalid parameters - """ - - constrained_cols = ServiceFunctionEndpoint.constrained_columns() - - assert len(params) == len(constrained_cols), "Incorrect url query parameters." - - return params - diff --git a/src/service/clmcservice/whoamiapi/views.py b/src/service/clmcservice/whoamiapi/views.py index 3e3a4e650467adb18fbb3b003d051a54dc89dc54..b89bfb5febc963521b43d8aa12ac379520e02ec4 100644 --- a/src/service/clmcservice/whoamiapi/views.py +++ b/src/service/clmcservice/whoamiapi/views.py @@ -25,7 +25,7 @@ from pyramid.httpexceptions import HTTPBadRequest, HTTPConflict, HTTPNotFound from pyramid.view import view_defaults, view_config from clmcservice.models import ServiceFunctionEndpoint -from clmcservice.whoamiapi.utilities import validate_sfendpoint_body, validate_sfendpoint_params +from clmcservice.whoamiapi.utilities import validate_sfendpoint_body @view_defaults(renderer='json') @@ -59,13 +59,14 @@ class WhoamiAPI(object): GET API call for a single resources. :return: One service function endpoint configuration instance retrieved from the database by querying the uniquely constrained columns. + :raises HTTPBadRequest: if the request parameters are invalid(invalid url query string) :raises HTTPNotFound: if a resource with the given parameters doesn't exist in the database """ sf_endpoint = self._get_sf_endpoint_from_url_string() if sf_endpoint is None: - raise HTTPNotFound("A service function endpoint with the given parameters doesn't exist.") + raise HTTPNotFound("A service function endpoint with the given URL query parameters doesn't exist.") else: return sf_endpoint.json @@ -75,6 +76,7 @@ class WhoamiAPI(object): A POST API call to create a new service function endpoint. :return: A JSON response to the POST call - essentially with the data of the new resource + :raises HTTPBadRequest: if request body is not a valid JSON for the configuration :raises HTTPConflict: if the unique constraints are not preserved after the creation of a new instance """ @@ -94,13 +96,14 @@ class WhoamiAPI(object): A PUT API call to update a service function endpoint. :return: A JSON response representing the updated object + :raises HTTPBadRequest: if the request parameters are invalid(invalid url query string) :raises HTTPNotFound: if a resource with the given parameters doesn't exist in the database """ sf_endpoint = self._get_sf_endpoint_from_url_string() if sf_endpoint is None: - raise HTTPNotFound("A service function endpoint with the given parameters doesn't exist.") + raise HTTPNotFound("A service function endpoint with the given identifier doesn't exist.") else: try: body = self.request.body.decode(self.request.charset) @@ -110,14 +113,14 @@ class WhoamiAPI(object): new_resource = validated_body old_resource = sf_endpoint.json - updating = new_resource["sf_i"] == old_resource["sf_i"] and new_resource["sf_endpoint"] == old_resource["sf_endpoint"] and new_resource["sr"] == old_resource["sr"] + updating = new_resource["sf_endpoint"] == old_resource["sf_endpoint"] if updating: ServiceFunctionEndpoint.delete(sf_endpoint) new_sf_endpoint = ServiceFunctionEndpoint(**validated_body) ServiceFunctionEndpoint.add(new_sf_endpoint) else: - resource_exists = ServiceFunctionEndpoint.exists(new_resource["sf_i"], new_resource["sf_endpoint"], new_resource["sr"]) + resource_exists = ServiceFunctionEndpoint.exists(new_resource["sf_endpoint"]) if resource_exists: raise HTTPConflict("Service function endpoint with this configuration already exists.") # error 409 in case of resource conflict @@ -132,6 +135,7 @@ class WhoamiAPI(object): Deletes an instance of a service function endpoint configuration in the database. :return: A content of the object that has been deleted + :raises HTTPBadRequest: if the request parameters are invalid(invalid url query string) :raises HTTPNotFound: if a resource with the given parameters doesn't exist in the database """ @@ -151,17 +155,12 @@ class WhoamiAPI(object): :return: An instance of a service function endpoint configuration or None if not existing """ - params = {} - for attribute in ServiceFunctionEndpoint.constrained_columns(): - if attribute in self.request.params: - params[attribute] = self.request.params.get(attribute) + sf_endpoint_id = self.request.params.get("sf_endpoint") + if sf_endpoint_id is None: + raise HTTPBadRequest("Request format is incorrect: sf_endpoint ID is not found in the URL query string.") - try: - params = validate_sfendpoint_params(params) - except AssertionError as e: - raise HTTPBadRequest("Request format is incorrect: {0}".format(e.args)) + sf_endpoint = ServiceFunctionEndpoint.get(sf_endpoint_id) - sf_endpoint = ServiceFunctionEndpoint.get(**params) return sf_endpoint def _validate_and_create(self): @@ -181,9 +180,9 @@ class WhoamiAPI(object): resource = validated_body - resource_exists = ServiceFunctionEndpoint.exists(resource["sf_i"], resource["sf_endpoint"], resource["sr"]) + resource_exists = ServiceFunctionEndpoint.exists(resource["sf_endpoint"]) if resource_exists: - raise HTTPConflict("Service function endpoint with this configuration already exists.") # error 409 in case of resource conflict + raise HTTPConflict("Service function endpoint with the given identifier already exists.") # error 409 in case of resource conflict # create an instance of the model sf_endpoint = ServiceFunctionEndpoint(**resource)