Skip to content

Commit

Permalink
Main 2.6.1 (#51)
Browse files Browse the repository at this point in the history
* Bumped version to 2.6.1

Updated vulnerable packages

* SIMPLE-5729 uploading image files now keeps the extension, removed old deprecated parameter from upload_image_file (#50)

SIMPLE-5729 improved image upload unit test, now checks the API call

* Updated vulnerable gitpython and aiohttp, regenerated test requirements

---------

Co-authored-by: Daniel Valent <dvalent@cisco.com>
  • Loading branch information
tmikuska and daniel-valent authored Sep 4, 2023
1 parent 831f841 commit 28bcaf9
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 46 deletions.
22 changes: 11 additions & 11 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "virl2_client"
version = "2.6.0"
version = "2.6.1"
description = "VIRL2 Client Library"
authors = ["Simon Knight <simknigh@cisco.com>", "Ralph Schmieder <rschmied@cisco.com>"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
anyio==3.6.2; python_full_version >= "3.6.2" and python_version >= "3.7"
certifi==2022.12.7; python_version >= "3.7"
certifi==2023.7.22; python_version >= "3.7"
cfgv==3.3.1; python_full_version >= "3.6.1" and python_version >= "3.8"
colorama==0.4.6; python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.7" and python_full_version >= "3.7.0"
distlib==0.3.6; python_version >= "3.8"
Expand Down
1 change: 1 addition & 0 deletions tests/test_data/.file.qcow
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
1 change: 1 addition & 0 deletions tests/test_data/file.qcow
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
1 change: 1 addition & 0 deletions tests/test_data/file.qcow.qcow
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
1 change: 1 addition & 0 deletions tests/test_data/file.tar.gz.qcow
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
1 change: 1 addition & 0 deletions tests/test_data/qcow2.qcow2.qcow2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
72 changes: 54 additions & 18 deletions tests/test_image_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@

import contextlib
import pathlib
from unittest.mock import MagicMock
from io import BufferedReader
from unittest.mock import ANY, MagicMock

import pytest

from virl2_client.exceptions import InvalidImageFile
from virl2_client.models.node_image_definitions import NodeImageDefinitions

wrong_format_list = [
WRONG_FORMAT_LIST = [
"",
".",
"file",
Expand All @@ -41,7 +42,7 @@
".file.",
"file.qcow.",
]
not_supported_list = [
NOT_SUPPORTED_LIST = [
" . ",
"file.txt",
"file.qcw",
Expand All @@ -52,7 +53,7 @@
"file.qcow ",
"file.qcow.tar.gz",
]
expected_pass_list = [
EXPECTED_PASS_LIST = [
"file.qcow",
"file.tar.gz.qcow",
"file.qcow.qcow",
Expand All @@ -61,6 +62,17 @@
]


# This fixture is not meant to be used in tests - rather, it's here to easily manually
# update files when the expected_pass_list is changed. Just change autouse to True,
# then locally run test_image_upload_file, and this will generate all the files
# in the expected_pass_list into test_data.
@pytest.fixture
def create_test_files(change_test_dir):
for file_path in EXPECTED_PASS_LIST:
path = pathlib.Path("test_data") / file_path
path.write_text("test")


@contextlib.contextmanager
def windows_path(path: str):
if "\\" in path:
Expand All @@ -86,30 +98,54 @@ def windows_path(path: str):
pytest.param("\\"),
pytest.param("..\\..\\"),
pytest.param("\\test\\"),
pytest.param("test_data/"),
],
)
@pytest.mark.parametrize(
"rename",
[
pytest.param(None),
pytest.param("renamed.qcow"),
pytest.param("renamed.qcow2"),
pytest.param("renamed"),
],
)
@pytest.mark.parametrize("usage", [pytest.param("name"), pytest.param("rename")])
@pytest.mark.parametrize(
"test_string, message",
[pytest.param(test_str, "wrong format") for test_str in wrong_format_list]
+ [pytest.param(test_str, "not supported") for test_str in not_supported_list]
+ [pytest.param(test_str, "") for test_str in expected_pass_list],
[pytest.param(test_str, "wrong format") for test_str in WRONG_FORMAT_LIST]
+ [pytest.param(test_str, "not supported") for test_str in NOT_SUPPORTED_LIST]
+ [pytest.param(test_str, "") for test_str in EXPECTED_PASS_LIST],
)
def test_image_upload_file(usage: str, test_string: str, message: str, test_path: str):
def test_image_upload_file(
change_test_dir,
test_path: str,
rename: str,
test_string: str,
message: str,
):
session = MagicMock()
session.post = MagicMock()
nid = NodeImageDefinitions(session)
rename = None
filename = test_path + test_string

if usage == "rename":
rename = test_string
if message in ("wrong format", "not supported"):
with pytest.raises(InvalidImageFile, match=message):
with windows_path(filename):
nid.upload_image_file(filename, rename)

try:
elif test_path == "test_data/":
with windows_path(filename):
nid.upload_image_file(filename, rename)
except FileNotFoundError:
assert message == ""
except InvalidImageFile as exc:
assert message in exc.args[0]
name = rename or test_string
files = {"field0": (name, ANY)}
headers = {"X-Original-File-Name": name}
session.post.assert_called_with("images/upload", files=files, headers=headers)
file = session.post.call_args.kwargs["files"]["field0"][1]
assert isinstance(file, BufferedReader)
assert pathlib.Path(file.name).resolve() == pathlib.Path(filename).resolve()
file.close()

else:
assert message == ""
with pytest.raises(FileNotFoundError):
with windows_path(filename):
nid.upload_image_file(filename, rename)
16 changes: 2 additions & 14 deletions virl2_client/models/node_image_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,31 +183,19 @@ def download_image_definition(self, definition_id: str) -> str:
url = "image_definitions/" + definition_id
return self._session.get(url).json()

def upload_image_file(
self,
filename: str,
rename: Optional[str] = None,
chunk_size_mb: Optional[int] = None,
) -> None:
def upload_image_file(self, filename: str, rename: Optional[str] = None) -> None:
"""
:param filename: the path of the image to upload
:param rename: Optional filename to rename to
:param chunk_size_mb: Optional size of upload chunk (mb)
(deprecated since 2.2.0)
"""
if chunk_size_mb is not None:
warnings.warn(
'The argument "chunk_size_mb" is deprecated as it never worked',
DeprecationWarning,
)

extension_list = [".qcow", ".qcow2"]
url = "images/upload"

path = pathlib.Path(filename)
extension = "".join(path.suffixes)
last_ext = path.suffix
name = rename or path.stem
name = rename or path.name

if extension == "" or name == "":
message = (
Expand Down
2 changes: 1 addition & 1 deletion virl2_client/virl2_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class ClientLibrary:
"""Python bindings for the REST API of a CML controller."""

# current client version
VERSION = Version("2.6.0")
VERSION = Version("2.6.1")
# list of Version objects
INCOMPATIBLE_CONTROLLER_VERSIONS = [
Version("2.0.0"),
Expand Down

0 comments on commit 28bcaf9

Please sign in to comment.