aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Jagiello <michal.jagiello@t-mobile.pl>2023-12-19 09:34:03 +0100
committerMichal Jagiello <michal.jagiello@t-mobile.pl>2023-12-19 09:44:36 +0100
commit4474aafa07d378be7c896821e2af86c3deb1e2d3 (patch)
tree40ae6afe627cd2447a0ece5c6894c2b15fe8eb7e
parentec7d9491a6f4cfa90e1140cc51975c98b6a555e8 (diff)
Refactor CPS module url creation
Switch from string formatting into urllib urljoin. Fix issue with invalid CPS requests urls Issue-ID: INT-2277 Signed-off-by: Michal Jagiello <michal.jagiello@t-mobile.pl> Change-Id: I37583aa3517be6cc27ed547ca6b11b19d6ccaca7
-rw-r--r--src/onapsdk/cps/anchor.py30
-rw-r--r--src/onapsdk/cps/cps_element.py2
-rw-r--r--src/onapsdk/cps/dataspace.py30
-rw-r--r--src/onapsdk/cps/schemaset.py3
-rw-r--r--src/onapsdk/version.py2
-rw-r--r--tests/test_cps.py48
-rw-r--r--tests/test_version.py2
7 files changed, 67 insertions, 50 deletions
diff --git a/src/onapsdk/cps/anchor.py b/src/onapsdk/cps/anchor.py
index 2a5c49f..f1917b7 100644
--- a/src/onapsdk/cps/anchor.py
+++ b/src/onapsdk/cps/anchor.py
@@ -14,6 +14,7 @@
# limitations under the License.
from typing import Any, Dict, TYPE_CHECKING
+from urllib.parse import urljoin
from .cps_element import CpsElement
@@ -57,12 +58,14 @@ class Anchor(CpsElement):
str: Anchor url
"""
- return f"{self._url}/dataspaces/{self.schema_set.dataspace.name}/anchors/{self.name}"
+ return urljoin(self._url,
+ f"dataspaces/{self.schema_set.dataspace.name}/anchors/{self.name}/")
def delete(self) -> None:
"""Delete anchor."""
+ # For some reason CPS API does not strip ending '/' character so it has to be removed here.
self.send_message(
- "DELETE", f"Delete {self.name} anchor", self.url, auth=self.auth
+ "DELETE", f"Delete {self.name} anchor", self.url.rstrip("/"), auth=self.auth
)
def create_node(self, node_data: str) -> None:
@@ -77,7 +80,7 @@ class Anchor(CpsElement):
self.send_message(
"POST",
f"Create {self.name} anchor node",
- f"{self.url}/nodes",
+ urljoin(self.url, "nodes"),
data=node_data,
auth=self.auth,
)
@@ -100,8 +103,9 @@ class Anchor(CpsElement):
return self.send_message_json(
"GET",
f"Get {self.name} anchor node with {xpath} xpath",
- f"{self.url}/node?xpath={xpath}"
- f"&descendants={descendants}",
+ urljoin(self.url, "node"),
+ params={"xpath": xpath,
+ "descendants": descendants},
auth=self.auth
)
@@ -120,7 +124,8 @@ class Anchor(CpsElement):
self.send_message(
"PATCH",
f"Update {self.name} anchor node with {xpath} xpath",
- f"{self.url}/nodes?xpath={xpath}",
+ urljoin(self.url, "nodes"),
+ params={"xpath": xpath},
data=node_data,
auth=self.auth,
)
@@ -138,7 +143,8 @@ class Anchor(CpsElement):
self.send_message(
"PUT",
f"Replace {self.name} anchor node with {xpath} xpath",
- f"{self.url}/nodes?xpath={xpath}",
+ urljoin(self.url, "nodes"),
+ params={"xpath": xpath},
data=node_data,
auth=self.auth,
)
@@ -154,7 +160,8 @@ class Anchor(CpsElement):
self.send_message(
"POST",
f"Add element to {self.name} anchor node with {xpath} xpath",
- f"{self.url}/list-nodes?xpath={xpath}",
+ urljoin(self.url, "list-nodes"),
+ params={"xpath": xpath},
data=node_data,
auth=self.auth,
)
@@ -176,7 +183,9 @@ class Anchor(CpsElement):
return self.send_message_json(
"GET",
f"Get {self.name} anchor node with {query} query",
- f"{self.url}/nodes/query?cps-path={query}&include-descendants={include_descendants}",
+ urljoin(self.url, "nodes/query"),
+ params={"cps-path": query,
+ "include-descendants": include_descendants},
auth=self.auth,
)
@@ -192,6 +201,7 @@ class Anchor(CpsElement):
self.send_message(
"DELETE",
f"Delete {self.name} anchor nodes with {xpath} xpath",
- f"{self.url}/nodes?xpath={xpath}",
+ urljoin(self.url, "nodes"),
+ params={"xpath": xpath},
auth=self.auth,
)
diff --git a/src/onapsdk/cps/cps_element.py b/src/onapsdk/cps/cps_element.py
index edcabc7..1aaa25d 100644
--- a/src/onapsdk/cps/cps_element.py
+++ b/src/onapsdk/cps/cps_element.py
@@ -22,5 +22,5 @@ from onapsdk.onap_service import OnapService
class CpsElement(OnapService):
"""Mother Class of all CPS elements."""
- _url: str = urljoin(settings.CPS_URL, f"cps/api/{settings.CPS_VERSION}")
+ _url: str = urljoin(settings.CPS_URL, f"cps/api/{settings.CPS_VERSION}/")
auth: tuple = settings.CPS_AUTH
diff --git a/src/onapsdk/cps/dataspace.py b/src/onapsdk/cps/dataspace.py
index e595598..112dbca 100644
--- a/src/onapsdk/cps/dataspace.py
+++ b/src/onapsdk/cps/dataspace.py
@@ -15,8 +15,9 @@
from functools import wraps
from typing import Any, BinaryIO, Dict, Iterable, Union
-from ..exceptions import (APIError, ResourceNotFound)
+from urllib.parse import urljoin
+from ..exceptions import (APIError, ResourceNotFound)
from .anchor import Anchor
from .cps_element import CpsElement
from .schemaset import SchemaSet, SchemaSetModuleReference
@@ -52,7 +53,7 @@ class Dataspace(CpsElement):
str: Dataspace url
"""
- return f"{self._url}/dataspaces/{self.name}"
+ return urljoin(self._url, f"dataspaces/{self.name}/")
def exception_handler(function): # pylint: disable= no-self-argument
"""Exception handler.
@@ -84,7 +85,8 @@ class Dataspace(CpsElement):
cls.send_message(
"POST",
f"Create {dataspace_name} dataspace",
- f"{cls._url}/dataspaces?dataspace-name={dataspace_name}",
+ urljoin(cls._url, "dataspaces"),
+ params={"dataspace-name": dataspace_name},
auth=cls.auth
)
return Dataspace(dataspace_name)
@@ -104,7 +106,7 @@ class Dataspace(CpsElement):
dataspace_data = cls.send_message_json(
"GET",
f"Get {dataspace_name} dataspace",
- f"{cls._url}/admin/dataspaces/{dataspace_name}",
+ urljoin(cls._url, f"admin/dataspaces/{dataspace_name}/"),
auth=cls.auth
)
return Dataspace(name=dataspace_data["name"])
@@ -123,8 +125,10 @@ class Dataspace(CpsElement):
"""
self.send_message(
"POST",
- "Get all CPS dataspace schemasets",
- f"{self.url}/anchors/?schema-set-name={schema_set.name}&anchor-name={anchor_name}",
+ f"Create {anchor_name} anchor",
+ urljoin(self.url, "anchors"),
+ params={"schema-set-name": schema_set.name,
+ "anchor-name": anchor_name},
auth=self.auth
)
return Anchor(name=anchor_name, schema_set=schema_set)
@@ -143,7 +147,7 @@ class Dataspace(CpsElement):
for anchor_data in self.send_message_json(\
"GET",\
"Get all CPS dataspace anchors",\
- f"{self.url}/anchors",\
+ urljoin(self.url, "anchors"),\
auth=self.auth\
):
yield Anchor(name=anchor_data["name"],
@@ -171,7 +175,7 @@ class Dataspace(CpsElement):
anchor_data: Dict[str, Any] = self.send_message_json(
"GET",
f"Get {anchor_name} anchor",
- f"{self.url}/anchors/{anchor_name}",
+ urljoin(self.url, f"anchors/{anchor_name}"),
auth=self.auth
)
return Anchor(name=anchor_data["name"],
@@ -188,7 +192,7 @@ class Dataspace(CpsElement):
self.send_message(
"DELETE",
f"Delete {anchor_name} anchor",
- f"{self.url}/anchors/{anchor_name}",
+ urljoin(self.url, f"anchors/{anchor_name}"),
auth=self.auth
)
@@ -206,7 +210,7 @@ class Dataspace(CpsElement):
schema_set_data: Dict[str, Any] = self.send_message_json(
"GET",
f"Get CPS dataspace {schema_set_name} schemaset",
- f"{self._url}/dataspaces/{self.name}/schema-sets/{schema_set_name}",
+ urljoin(self._url, f"dataspaces/{self.name}/schema-sets/{schema_set_name}"),
auth=self.auth
)
return SchemaSet(
@@ -242,7 +246,8 @@ class Dataspace(CpsElement):
self.send_message(
"POST",
"Create schema set",
- f"{self._url}/dataspaces/{self.name}/schema-sets?schema-set-name={schema_set_name}",
+ urljoin(self._url, f"dataspaces/{self.name}/schema-sets"),
+ params={"schema-set-name": schema_set_name},
files={"file": schema_set},
headers={}, # Leave headers empty to fill it correctly by `requests` library
auth=self.auth
@@ -254,6 +259,7 @@ class Dataspace(CpsElement):
self.send_message(
"DELETE",
f"Delete {self.name} dataspace",
- f"{self._url}/dataspaces?dataspace-name={self.name}",
+ urljoin(self._url, "dataspaces"),
+ params={"dataspace-name": self.name},
auth=self.auth
)
diff --git a/src/onapsdk/cps/schemaset.py b/src/onapsdk/cps/schemaset.py
index b94cd60..171fbe3 100644
--- a/src/onapsdk/cps/schemaset.py
+++ b/src/onapsdk/cps/schemaset.py
@@ -15,6 +15,7 @@
from dataclasses import dataclass
from typing import List, Optional, TYPE_CHECKING
+from urllib.parse import urljoin
from .cps_element import CpsElement
@@ -69,6 +70,6 @@ class SchemaSet(CpsElement):
self.send_message(
"DELETE",
f"Delete {self.name} schema set",
- f"{self._url}/dataspaces/{self.dataspace.name}/schema-sets/{self.name}",
+ urljoin(self._url, f"dataspaces/{self.dataspace.name}/schema-sets/{self.name}"),
auth=self.auth
)
diff --git a/src/onapsdk/version.py b/src/onapsdk/version.py
index 6fd109a..b82b975 100644
--- a/src/onapsdk/version.py
+++ b/src/onapsdk/version.py
@@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-__version__ = "12.7.2"
+__version__ = "12.7.3"
diff --git a/tests/test_cps.py b/tests/test_cps.py
index be9ed12..9be0940 100644
--- a/tests/test_cps.py
+++ b/tests/test_cps.py
@@ -177,7 +177,7 @@ def test_anchor_delete(mock_send_message):
anchor.delete()
mock_send_message.assert_called_once()
url = mock_send_message.call_args[0][2]
- assert anchor.url in url
+ assert anchor.url.rstrip("/") in url
@mock.patch("onapsdk.cps.Anchor.send_message")
def test_anchor_create_node(mock_send_message):
@@ -192,71 +192,71 @@ def test_anchor_get_node(mock_send_message_json):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.get_node("test-xpath")
mock_send_message_json.assert_called_once()
- url = mock_send_message_json.call_args[0][2]
- assert "xpath=test-xpath" in url
- assert "descendants=0" in url
+ params = mock_send_message_json.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath"
+ assert "descendants" in params and params["descendants"] == 0
mock_send_message_json.reset_mock()
anchor.get_node("test-xpath-2", descendants=-1)
mock_send_message_json.assert_called_once()
- url = mock_send_message_json.call_args[0][2]
- assert "xpath=test-xpath-2" in url
- assert "descendants=-1" in url
+ params = mock_send_message_json.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath-2"
+ assert "descendants" in params and params["descendants"] == -1
mock_send_message_json.reset_mock()
anchor.get_node("test-xpath-3", descendants=2)
mock_send_message_json.assert_called_once()
- url = mock_send_message_json.call_args[0][2]
- assert "xpath=test-xpath-3" in url
- assert "descendants=2" in url
+ params = mock_send_message_json.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath-3"
+ assert "descendants" in params and params["descendants"] == 2
@mock.patch("onapsdk.cps.Anchor.send_message")
def test_anchor_update_node(mock_send_message):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.update_node("test-xpath", '{"test": "data"}')
mock_send_message.assert_called_once()
- url = mock_send_message.call_args[0][2]
- assert "xpath=test-xpath" in url
+ params = mock_send_message.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath"
@mock.patch("onapsdk.cps.Anchor.send_message")
def test_anchor_replace_node(mock_send_message):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.replace_node("test-xpath", '{"test": "data"}')
mock_send_message.assert_called_once()
- url = mock_send_message.call_args[0][2]
- assert "xpath=test-xpath" in url
+ params = mock_send_message.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath"
@mock.patch("onapsdk.cps.Anchor.send_message")
def test_anchor_add_list_node(mock_send_message):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.add_list_node("test-xpath", '{"test": "data"}')
mock_send_message.assert_called_once()
- url = mock_send_message.call_args[0][2]
- assert "xpath=test-xpath" in url
+ params = mock_send_message.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath"
@mock.patch("onapsdk.cps.Anchor.send_message_json")
def test_anchor_query_node(mock_send_message_json):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.query_node("/test-query")
mock_send_message_json.assert_called_once()
- url = mock_send_message_json.call_args[0][2]
- assert "cps-path=/test-query" in url
- assert "include-descendants=False" in url
+ params = mock_send_message_json.call_args.kwargs["params"]
+ assert "cps-path" in params and params["cps-path"] == "/test-query"
+ assert "include-descendants" in params and params["include-descendants"] is False
mock_send_message_json.reset_mock()
anchor.query_node("/test-query1", include_descendants=True)
mock_send_message_json.assert_called_once()
- url = mock_send_message_json.call_args[0][2]
- assert "cps-path=/test-query1" in url
- assert "include-descendants=True" in url
+ params = mock_send_message_json.call_args.kwargs["params"]
+ assert "cps-path" in params and params["cps-path"] == "/test-query1"
+ assert "include-descendants" in params and params["include-descendants"] is True
@mock.patch("onapsdk.cps.Anchor.send_message")
def test_anchor_delete_nodes(mock_send_message):
anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock())
anchor.delete_nodes("test-xpath")
mock_send_message.assert_called_once()
- url = mock_send_message.call_args[0][2]
- assert "xpath=test-xpath" in url
+ params = mock_send_message.call_args.kwargs["params"]
+ assert "xpath" in params and params["xpath"] == "test-xpath"
@mock.patch("onapsdk.cps.Dataspace.send_message")
def test_dataspace_create_anchor_except(mock_send_message_json):
diff --git a/tests/test_version.py b/tests/test_version.py
index 600e562..bf3b69b 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -17,4 +17,4 @@ import onapsdk.version as version
def test_version():
"""Check version is the right one."""
- assert version.__version__ == '12.7.2'
+ assert version.__version__ == '12.7.3'