From 2d74e3c9de67ed51e9a2b2c70552a46879992cee Mon Sep 17 00:00:00 2001 From: Dev Gupta <72784479+guptadev21@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:32:18 +0530 Subject: [PATCH] feat: implements async client (#5) This commit implements the async client for the v2 APIs. --- .github/workflows/quality-checks.yml | 2 +- pyproject.toml | 84 +- rapyuta_io_sdk_v2/__init__.py | 1 + rapyuta_io_sdk_v2/async_client.py | 1438 +++++++++++++++++ rapyuta_io_sdk_v2/client.py | 234 +-- rapyuta_io_sdk_v2/config.py | 3 +- rapyuta_io_sdk_v2/utils.py | 35 + tests/async_tests/test_configtree_async.py | 362 +++++ tests/async_tests/test_deployment_async.py | 153 ++ tests/async_tests/test_disk_async.py | 142 ++ .../async_tests/test_managedservice_async.py | 208 +++ tests/async_tests/test_network_async.py | 124 ++ tests/async_tests/test_package_async.py | 106 ++ tests/async_tests/test_project_async.py | 97 ++ tests/async_tests/test_secret_async.py | 146 ++ tests/async_tests/test_staticroute_async.py | 148 ++ .../{utils/test_util.py => data/mock_data.py} | 17 +- tests/{ => sync_tests}/test_config.py | 2 +- tests/{ => sync_tests}/test_configtree.py | 216 +-- tests/sync_tests/test_deployment.py | 142 ++ tests/sync_tests/test_disk.py | 134 ++ tests/{ => sync_tests}/test_main.py | 10 +- tests/{ => sync_tests}/test_managedservice.py | 129 +- tests/{ => sync_tests}/test_network.py | 75 +- tests/{ => sync_tests}/test_package.py | 62 +- tests/{ => sync_tests}/test_project.py | 127 +- tests/{ => sync_tests}/test_secret.py | 72 +- tests/{ => sync_tests}/test_staticroute.py | 88 +- tests/test_deployment.py | 223 --- tests/test_disk.py | 205 --- tests/utils/fixtures.py | 25 + uv.lock | 31 +- 32 files changed, 3587 insertions(+), 1254 deletions(-) create mode 100644 rapyuta_io_sdk_v2/async_client.py create mode 100644 tests/async_tests/test_configtree_async.py create mode 100644 tests/async_tests/test_deployment_async.py create mode 100644 tests/async_tests/test_disk_async.py create mode 100644 tests/async_tests/test_managedservice_async.py create mode 100644 tests/async_tests/test_network_async.py create mode 100644 tests/async_tests/test_package_async.py create mode 100644 tests/async_tests/test_project_async.py create mode 100644 tests/async_tests/test_secret_async.py create mode 100644 tests/async_tests/test_staticroute_async.py rename tests/{utils/test_util.py => data/mock_data.py} (86%) rename tests/{ => sync_tests}/test_config.py (97%) rename tests/{ => sync_tests}/test_configtree.py (51%) create mode 100644 tests/sync_tests/test_deployment.py create mode 100644 tests/sync_tests/test_disk.py rename tests/{ => sync_tests}/test_main.py (82%) rename tests/{ => sync_tests}/test_managedservice.py (52%) rename tests/{ => sync_tests}/test_network.py (50%) rename tests/{ => sync_tests}/test_package.py (54%) rename tests/{ => sync_tests}/test_project.py (50%) rename tests/{ => sync_tests}/test_secret.py (53%) rename tests/{ => sync_tests}/test_staticroute.py (51%) delete mode 100644 tests/test_deployment.py delete mode 100644 tests/test_disk.py create mode 100644 tests/utils/fixtures.py diff --git a/.github/workflows/quality-checks.yml b/.github/workflows/quality-checks.yml index 2eac29b..b225d91 100644 --- a/.github/workflows/quality-checks.yml +++ b/.github/workflows/quality-checks.yml @@ -28,4 +28,4 @@ jobs: run: | uv sync --all-extras --dev source .venv/bin/activate - uv run pytest tests/ \ No newline at end of file + uv run pytest tests/ --cov \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index abc7c84..61ca75f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,87 @@ dev = [ "pytest-cov>=5.0.0", "pytest-mock>=3.14.0", "pytest>=8.3.3", - "anyio>=4.5.2", - "asyncer>=0.0.8", "typing-extensions>=4.12.2", + "pytest-asyncio>=0.24.0", + "asyncmock>=0.4.2", ] + + +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] + +# Same as Black. +line-length = 90 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py38" + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or +# McCabe complexity (`C901`) by default. +select = ["E4", "E7", "E9", "F", "B", "Q", "W", "N816"] +ignore = ["E741", "B904"] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" + +# Enable auto-formatting of code examples in docstrings. Markdown, +# reStructuredText code/literal blocks and doctests are all supported. +# +# This is currently disabled by default, but it is planned for this +# to be opt-out in the future. +docstring-code-format = false + +# Set the line length limit used when formatting code snippets in +# docstrings. +# +# This only has an effect when the `docstring-code-format` setting is +# enabled. +docstring-code-line-length = "dynamic" diff --git a/rapyuta_io_sdk_v2/__init__.py b/rapyuta_io_sdk_v2/__init__.py index c53ba64..3f0d943 100644 --- a/rapyuta_io_sdk_v2/__init__.py +++ b/rapyuta_io_sdk_v2/__init__.py @@ -1,4 +1,5 @@ # ruff: noqa +from rapyuta_io_sdk_v2.async_client import AsyncClient from rapyuta_io_sdk_v2.client import Client from rapyuta_io_sdk_v2.config import Configuration from rapyuta_io_sdk_v2.utils import walk_pages diff --git a/rapyuta_io_sdk_v2/async_client.py b/rapyuta_io_sdk_v2/async_client.py new file mode 100644 index 0000000..5f72e36 --- /dev/null +++ b/rapyuta_io_sdk_v2/async_client.py @@ -0,0 +1,1438 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Rapyuta Robotics +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import platform + +import httpx +from munch import Munch + +from rapyuta_io_sdk_v2.config import Configuration +from rapyuta_io_sdk_v2.utils import handle_and_munchify_response, handle_server_errors + + +class AsyncClient(object): + """AsyncClient class for the SDK.""" + + def __init__(self, config=None, **kwargs): + self.config = config or Configuration() + timeout = kwargs.get("timeout", 10) + self.c = httpx.AsyncClient( + timeout=timeout, + limits=httpx.Limits( + max_keepalive_connections=5, + max_connections=5, + keepalive_expiry=30, + ), + headers={ + "User-Agent": ( + "rio-sdk-v2;N/A;{};{};{} {}".format( + platform.processor() or platform.machine(), + platform.system(), + platform.release(), + platform.version(), + ) + ) + }, + ) + self.sync_client = httpx.Client( + timeout=timeout, + limits=httpx.Limits( + max_keepalive_connections=5, + max_connections=5, + keepalive_expiry=30, + ), + headers={ + "User-Agent": ( + "rio-sdk-v2;N/A;{};{};{} {}".format( + platform.processor() or platform.machine(), + platform.system(), + platform.release(), + platform.version(), + ) + ) + }, + ) + self.rip_host = self.config.hosts.get("rip_host") + self.v2api_host = self.config.hosts.get("v2api_host") + + def get_auth_token(self, email: str, password: str) -> str: + """Get the authentication token for the user. + + Args: + email (str) + password (str) + + Returns: + str: authentication token + """ + response = self.sync_client.post( + url=f"{self.rip_host}/user/login", + headers={"Content-Type": "application/json"}, + json={ + "email": email, + "password": password, + }, + ) + handle_server_errors(response) + return response.json()["data"].get("token") + + def login( + self, + email: str, + password: str, + ) -> None: + """Get the authentication token for the user. + + Args: + email (str) + password (str) + + Returns: + str: authentication token + """ + + token = self.get_auth_token(email, password) + self.config.auth_token = token + + @handle_and_munchify_response + def logout(self, token: str = None) -> Munch: + """Expire the authentication token. + + Args: + token (str): The token to expire. + """ + + if token is None: + token = self.config.auth_token + + return self.sync_client.post( + url=f"{self.rip_host}/user/logout", + headers={ + "Content-Type": "application/json", + "Authorization": f"Bearer {token}", + }, + ) + + def refresh_token(self, token: str = None, set_token: bool = True) -> str: + """Refresh the authentication token. + + Args: + token (str): The token to refresh. + set_token (bool): Set the refreshed token in the configuration. + + Returns: + str: The refreshed token. + """ + + if token is None: + token = self.config.auth_token + + response = self.sync_client.post( + url=f"{self.rip_host}/refreshtoken", + headers={"Content-Type": "application/json"}, + json={"token": token}, + ) + handle_server_errors(response) + if set_token: + self.config.auth_token = response.json()["data"].get("token") + return response.json()["data"].get("token") + + def set_organization(self, organization_guid: str) -> None: + """Set the organization GUID. + + Args: + organization_guid (str): Organization GUID + """ + self.config.set_organization(organization_guid) + + def set_project(self, project_guid: str) -> None: + """Set the project GUID. + + Args: + project_guid (str): Project GUID + """ + self.config.set_project(project_guid) + + # ----------------- Projects ----------------- + @handle_and_munchify_response + async def list_projects( + self, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + status: list[str] = None, + organizations: list[str] = None, + **kwargs, + ) -> Munch: + """List all projects in an organization. + + Args: + cont (int, optional): Start index of projects. Defaults to 0. + limit (int, optional): Number of projects to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get projects from. Defaults to None. + status (list[str], optional): Define status to get projects from. Defaults to None. + organizations (list[str], optional): Define organizations to get projects from. Defaults to None. + + Returns: + Munch: List of projects as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/projects/", + headers=self.config.get_headers(with_project=False, **kwargs), + params={ + "continue": cont, + "limit": limit, + "status": status, + "organizations": organizations, + "labelSelector": label_selector, + }, + ) + + @handle_and_munchify_response + async def get_project(self, project_guid: str = None, **kwargs) -> Munch: + """Get a project by its GUID. + + If no project or organization GUID is provided, + the async default project and organization GUIDs will + be picked from the current configuration. + + Args: + project_guid (str): user provided project GUID or config project GUID + + Raises: + ValueError: If organization_guid or project_guid is None + + Returns: + Munch: Project details as a Munch object. + """ + if project_guid is None: + project_guid = self.config.project_guid + + if not project_guid: + raise ValueError("project_guid is required") + + return await self.c.get( + url=f"{self.v2api_host}/v2/projects/{project_guid}/", + headers=self.config.get_headers(with_project=False, **kwargs), + ) + + @handle_and_munchify_response + async def create_project(self, body: dict, **kwargs) -> Munch: + """Create a new project. + + Args: + body (object): Project details + + Returns: + Munch: Project details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/projects/", + headers=self.config.get_headers(with_project=False, **kwargs), + json=body, + ) + + @handle_and_munchify_response + async def update_project( + self, body: dict, project_guid: str = None, **kwargs + ) -> Munch: + """Update a project by its GUID. + + Returns: + Munch: Project details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/projects/{project_guid}/", + headers=self.config.get_headers(with_project=False, **kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_project(self, project_guid: str, **kwargs) -> Munch: + """Delete a project by its GUID. + + Args: + project_guid (str): Project GUID + + Returns: + Munch: Project details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/projects/{project_guid}/", + headers=self.config.get_headers(with_project=False, **kwargs), + ) + + @handle_and_munchify_response + async def update_project_owner( + self, body: dict, project_guid: str = None, **kwargs + ) -> Munch: + """Update the owner of a project by its GUID. + + Returns: + Munch: Project details as a Munch object. + """ + project_guid = project_guid or self.config.project_guid + + return await self.c.put( + url=f"{self.v2api_host}/v2/projects/{project_guid}/owner/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + # -------------------Package------------------- + @handle_and_munchify_response + async def list_packages( + self, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + name: str = None, + **kwargs, + ) -> Munch: + """List all packages in a project. + + Args: + cont (int, optional): Start index of packages. Defaults to 0. + limit (int, optional): Number of packages to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get packages from. Defaults to None. + name (str, optional): Define name to get packages from. Defaults to None. + + Returns: + Munch: List of packages as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/packages/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + "name": name, + }, + ) + + @handle_and_munchify_response + async def create_package(self, body: dict, **kwargs) -> Munch: + """Create a new package. + + The Payload is the JSON format of the Package Manifest. + For a documented example, run the rio explain package command. + + Returns: + Munch: Package details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/packages/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_package(self, name: str, version: str = None, **kwargs) -> Munch: + """Get a package by its name. + + Args: + name (str): Package name + version (str, optional): Package version. Defaults to None. + + Returns: + Munch: Package details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/packages/{name}/", + headers=self.config.get_headers(**kwargs), + params={"version": version}, + ) + + @handle_and_munchify_response + async def delete_package(self, name: str, **kwargs) -> Munch: + """Delete a package by its name. + + Args: + name (str): Package name + + Returns: + Munch: Package details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/packages/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def list_deployments( + self, + cont: int = 0, + limit: int = 50, + dependencies: bool = False, + device_name: str = None, + guids: list[str] = None, + label_selector: list[str] = None, + name: str = None, + names: list[str] = None, + package_name: str = None, + package_version: str = None, + phases: list[str] = None, + regions: list[str] = None, + **kwargs, + ) -> Munch: + """List all deployments in a project. + + Args: + cont (int, optional): Start index of deployments. Defaults to 0. + limit (int, optional): Number of deployments to list. Defaults to 50. + dependencies (bool, optional): Filter by dependencies. Defaults to False. + device_name (str, optional): Filter deployments by device name. Defaults to None. + guids (list[str], optional): Filter by GUIDs. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get deployments from. Defaults to None. + name (str, optional): Define name to get deployments from. Defaults to None. + names (list[str], optional): Define names to get deployments from. Defaults to None. + package_name (str, optional): Filter by package name. Defaults to None. + package_version (str, optional): Filter by package version. Defaults to None. + phases (list[str], optional): Filter by phases. Available values : InProgress, Provisioning, Succeeded, FailedToUpdate, FailedToStart, Stopped. Defaults to None. + regions (list[str], optional): Filter by regions. Defaults to None. + + Returns: + Munch: List of deployments as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/deployments/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "dependencies": dependencies, + "deviceName": device_name, + "guids": guids, + "labelSelector": label_selector, + "name": name, + "names": names, + "packageName": package_name, + "packageVersion": package_version, + "phases": phases, + "regions": regions, + }, + ) + + # -------------------Deployment------------------- + + @handle_and_munchify_response + async def create_deployment(self, body: dict, **kwargs) -> Munch: + """Create a new deployment. + + Args: + body (object): Deployment details + + Returns: + Munch: Deployment details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/deployments/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_deployment(self, name: str, guid: str = None, **kwargs) -> Munch: + """Get a deployment by its name. + + Returns: + Munch: Deployment details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/deployments/{name}/", + headers=self.config.get_headers(**kwargs), + params={"guid": guid}, + ) + + @handle_and_munchify_response + async def update_deployment(self, name: str, body: dict, **kwargs) -> Munch: + """Update a deployment by its name. + + Returns: + Munch: Deployment details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/deployments/{name}/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_deployment(self, name: str, **kwargs) -> Munch: + """Delete a deployment by its name. + + Returns: + Munch: Deployment details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/deployments/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def get_deployment_graph(self, name: str, **kwargs) -> Munch: + """Get a deployment graph by its name. [Experimental] + + Returns: + Munch: Deployment graph as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/deployments/{name}/graph/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def get_deployment_history( + self, name: str, guid: str = None, **kwargs + ) -> Munch: + """Get a deployment history by its name. + + Returns: + Munch: Deployment history as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/deployments/{name}/history/", + headers=self.config.get_headers(**kwargs), + params={"guid": guid}, + ) + + # -------------------Disks------------------- + @handle_and_munchify_response + async def list_disks( + self, + cont: int = 0, + label_selector: list[str] = None, + limit: int = 50, + names: list[str] = None, + regions: list[str] = None, + status: list[str] = None, + **kwargs, + ) -> Munch: + """List all disks in a project. + + Args: + cont (int, optional): Start index of disks. Defaults to 0. + label_selector (list[str], optional): Define labelSelector to get disks from. Defaults to None. + limit (int, optional): Number of disks to list. Defaults to 50. + names (list[str], optional): Define names to get disks from. Defaults to None. + regions (list[str], optional): Define regions to get disks from. Defaults to None. + status (list[str], optional): Define status to get disks from. Available values : Available, Bound, Released, Failed, Pending.Defaults to None. + + + Returns: + Munch: List of disks as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/disks/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + "names": names, + "regions": regions, + "status": status, + }, + ) + + @handle_and_munchify_response + async def get_disk(self, name: str, **kwargs) -> Munch: + """Get a disk by its name. + + Args: + name (str): Disk name + + Returns: + Munch: Disk details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/disks/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def create_disk(self, body: str, **kwargs) -> Munch: + """Create a new disk. + + Returns: + Munch: Disk details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/disks/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_disk(self, name: str, **kwargs) -> Munch: + """Delete a disk by its name. + + Args: + name (str): Disk name + + Returns: + Munch: Disk details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/disks/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + # -------------------Static Routes------------------- + @handle_and_munchify_response + async def list_staticroutes( + self, + cont: int = 0, + limit: int = 50, + guids: list[str] = None, + label_selector: list[str] = None, + names: list[str] = None, + regions: list[str] = None, + **kwargs, + ) -> Munch: + """List all static routes in a project. + + Args: + cont (int, optional): Start index of static routes. Defaults to 0. + limit (int, optional): Number of static routes to list. Defaults to 50. + guids (list[str], optional): Define guids to get static routes from. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get static routes from. Defaults to None. + names (list[str], optional): Define names to get static routes from. Defaults to None. + regions (list[str], optional): Define regions to get static routes from. Defaults to None. + + Returns: + Munch: List of static routes as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/staticroutes/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "guids": guids, + "labelSelector": label_selector, + "names": names, + "regions": regions, + }, + ) + + @handle_and_munchify_response + async def create_staticroute(self, body: dict, **kwargs) -> Munch: + """Create a new static route. + + Returns: + Munch: Static route details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/staticroutes/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_staticroute(self, name: str, **kwargs) -> Munch: + """Get a static route by its name. + + Args: + name (str): Static route name + + Returns: + Munch: Static route details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/staticroutes/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def update_staticroute(self, name: str, body: dict, **kwargs) -> Munch: + """Update a static route by its name. + + Args: + name (str): Static route name + body (dict): Update details + + Returns: + Munch: Static route details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/staticroutes/{name}/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_staticroute(self, name: str, **kwargs) -> Munch: + """Delete a static route by its name. + + Args: + name (str): Static route name + + Returns: + Munch: Static route details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/staticroutes/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + # -------------------Networks------------------- + @handle_and_munchify_response + async def list_networks( + self, + cont: int = 0, + limit: int = 50, + device_name: str = None, + label_selector: list[str] = None, + names: list[str] = None, + network_type: str = None, + phases: list[str] = None, + regions: list[str] = None, + status: list[str] = None, + **kwargs, + ) -> Munch: + """List all networks in a project. + + Args: + cont (int, optional): Start index of networks. Defaults to 0. + limit (int, optional): Number of networks to list. Defaults to 50. + device_name (str, optional): Filter networks by device name. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get networks from. Defaults to None. + names (list[str], optional): Define names to get networks from. Defaults to None. + network_type (str, optional): Define network type to get networks from. Defaults to None. + phases (list[str], optional): Define phases to get networks from. Available values : InProgress, Provisioning, Succeeded, FailedToUpdate, FailedToStart, Stopped. Defaults to None. + regions (list[str], optional): Define regions to get networks from. Defaults to None. + status (list[str], optional): Define status to get networks from. Available values : Running, Pending, Error, Unknown, Stopped. Defaults to None. + + Returns: + Munch: List of networks as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/networks/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "deviceName": device_name, + "labelSelector": label_selector, + "names": names, + "networkType": network_type, + "phases": phases, + "regions": regions, + "status": status, + }, + ) + + @handle_and_munchify_response + async def create_network(self, body: dict, **kwargs) -> Munch: + """Create a new network. + + Returns: + Munch: Network details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/networks/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_network(self, name: str, **kwargs) -> Munch: + """Get a network by its name. + + Args: + name (str): Network name + + Returns: + Munch: Network details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/networks/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def delete_network(self, name: str, **kwargs) -> Munch: + """Delete a network by its name. + + Args: + name (str): Network name + + Returns: + Munch: Network details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/networks/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + # -------------------Secrets------------------- + @handle_and_munchify_response + async def list_secrets( + self, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + names: list[str] = None, + regions: list[str] = None, + **kwargs, + ) -> Munch: + """List all secrets in a project. + + Args: + cont (int, optional): Start index of secrets. Defaults to 0. + limit (int, optional): Number of secrets to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get secrets from. Defaults to None. + names (list[str], optional): Define names to get secrets from. Defaults to None. + regions (list[str], optional): Define regions to get secrets from. Defaults to None. + + Returns: + Munch: List of secrets as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/secrets/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + "names": names, + "regions": regions, + }, + ) + + @handle_and_munchify_response + async def create_secret(self, body: dict, **kwargs) -> Munch: + """Create a new secret. + + Returns: + Munch: Secret details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/secrets/", + headers=self.config.get_headers(*kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_secret(self, name: str, **kwargs) -> Munch: + """Get a secret by its name. + + Args: + name (str): Secret name + + Returns: + Munch: Secret details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/secrets/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def update_secret(self, name: str, body: dict, **kwargs) -> Munch: + """Update a secret by its name. + + Args: + name (str): Secret name + body (dict): Update details + + Returns: + Munch: Secret details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/secrets/{name}/", + headers=self.config.get_headers(**kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_secret(self, name: str, **kwargs) -> Munch: + """Delete a secret by its name. + + Args: + name (str): Secret name + + Returns: + Munch: Secret details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/secrets/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + # -------------------Config Trees------------------- + @handle_and_munchify_response + async def list_configtrees( + self, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + with_project: bool = True, + **kwargs, + ) -> Munch: + """List all config trees in a project. + + Args: + cont (int, optional): Start index of config trees. Defaults to 0. + limit (int, optional): Number of config trees to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get config trees from. Defaults to None. + with_project (bool, optional): Include project details. Defaults to True. + + Returns: + Munch: List of config trees as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/configtrees/", + headers=self.config.get_headers(with_project=with_project, **kwargs), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + }, + ) + + @handle_and_munchify_response + async def create_configtree( + self, body: dict, with_project: bool = True, **kwargs + ) -> Munch: + """Create a new config tree. + + Args: + body (object): Config tree details + with_project (bool, optional): Work in the project scope. Defaults to True. + + Returns: + Munch: Config tree details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/configtrees/", + headers=self.config.get_headers(with_project=with_project, **kwargs), + json=body, + ) + + @handle_and_munchify_response + async def get_configtree( + self, + name: str, + content_types: list[str] = None, + include_data: bool = False, + key_prefixes: list[str] = None, + revision: str = None, + with_project: bool = True, + **kwargs, + ) -> Munch: + """Get a config tree by its name. + + Args: + name (str): Config tree name + content_types (list[str], optional): Define contentTypes to get config tree from. Defaults to None. + include_data (bool, optional): Include data. Defaults to False. + key_prefixes (list[str], optional): Define keyPrefixes to get config tree from. Defaults to None. + revision (str, optional): Define revision to get config tree from. Defaults to None. + with_project (bool, optional): Work in the project scope. Defaults to True. + + Returns: + Munch: Config tree details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/configtrees/{name}/", + headers=self.config.get_headers(with_project=with_project, **kwargs), + params={ + "contentTypes": content_types, + "includeData": include_data, + "keyPrefixes": key_prefixes, + "revision": revision, + }, + ) + + @handle_and_munchify_response + async def set_configtree_revision( + self, name: str, configtree: object, project_guid: str = None, **kwargs + ) -> Munch: + """Set a config tree revision. + + Args: + name (str): Config tree name + configtree (object): Config tree details + project_guid (str, optional): Project GUID. async defaults to None. + + Returns: + Munch: Config tree details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/configtrees/{name}/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + json=configtree, + ) + + @handle_and_munchify_response + async def update_configtree( + self, name: str, body: dict, with_project: bool = True, **kwargs + ) -> Munch: + """Update a config tree by its name. + + Args: + name (str): Config tree name + body (dict): Update details + with_project (bool, optional): Work in the project scope. Defaults to True. + + Returns: + Munch: Config tree details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/configtrees/{name}/", + headers=self.config.get_headers(with_project=with_project, **kwargs), + json=body, + ) + + @handle_and_munchify_response + async def delete_configtree(self, name: str, **kwargs) -> Munch: + """Delete a config tree by its name. + + Args: + name (str): Config tree name + + Returns: + Munch: Config tree details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/configtrees/{name}/", + headers=self.config.get_headers(**kwargs), + ) + + @handle_and_munchify_response + async def list_revisions( + self, + tree_name: str, + cont: int = 0, + limit: int = 50, + committed: bool = False, + label_selector: list[str] = None, + **kwargs, + ) -> Munch: + """List all revisions of a config tree. + + Args: + tree_name (str): Config tree name + cont (int, optional): Continue param . Defaults to 0. + limit (int, optional): Limit param . Defaults to 50. + committed (bool, optional): Committed. Defaults to False. + label_selector (list[str], optional): Define labelSelector to get revisions from. Defaults to None. + + Returns: + Munch: List of revisions as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/", + headers=self.config.get_headers(**kwargs), + params={ + "continue": cont, + "limit": limit, + "committed": committed, + "labelSelector": label_selector, + }, + ) + + @handle_and_munchify_response + async def create_revision( + self, name: str, body: dict, project_guid: str = None, **kwargs + ) -> Munch: + """Create a new revision. + + Args: + name (str): Config tree name + body (object): Revision details + project_guid (str): Project GUID (optional) + + Returns: + Munch: Revision details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + json=body, + ) + + @handle_and_munchify_response + async def put_keys_in_revision( + self, name: str, revision_id: str, config_values: dict, **kwargs + ) -> Munch: + """Put keys in a revision. + + Args: + name (str): Config tree name + revision_id (str): Config tree revision ID + config_values (dict): Config values + + Returns: + Munch: Revision details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/keys/", + headers=self.config.get_headers(**kwargs), + json=config_values, + ) + + @handle_and_munchify_response + async def commit_revision( + self, + tree_name: str, + revision_id: str, + author: str = None, + message: str = None, + project_guid: str = None, + **kwargs, + ) -> Munch: + """Commit a revision. + + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + author (str, optional): Revision Author. Defaults to None. + message (str, optional): Revision Message. Defaults to None. + project_guid (str, optional): Project GUID. Defaults to None. + + Returns: + Munch: Revision details as a Munch object. + """ + config_tree_revision = { + "author": author, + "message": message, + } + + return await self.c.patch( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/commit/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + json=config_tree_revision, + ) + + @handle_and_munchify_response + async def get_key_in_revision( + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, + ) -> Munch: + """Get a key in a revision. + + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + key (str): Key + project_guid (str, optional): Project GUID. async defaults to None. + + Returns: + Munch: Key details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + ) + + @handle_and_munchify_response + async def put_key_in_revision( + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, + ) -> Munch: + """Put a key in a revision. + + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + key (str): Key + project_guid (str, optional): Project GUID. async defaults to None. + + Returns: + Munch: Key details as a Munch object. + """ + + return await self.c.put( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + ) + + @handle_and_munchify_response + async def delete_key_in_revision( + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, + ) -> Munch: + """Delete a key in a revision. + + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + key (str): Key + project_guid (str, optional): Project GUID. async defaults to None. + + Returns: + Munch: Key details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + ) + + @handle_and_munchify_response + async def rename_key_in_revision( + self, + tree_name: str, + revision_id: str, + key: str, + config_key_rename: dict, + project_guid: str = None, + **kwargs, + ) -> Munch: + """Rename a key in a revision. + + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + key (str): Key + config_key_rename (dict): Key rename details + project_guid (str, optional): Project GUID. async defaults to None. + + Returns: + Munch: Key details as a Munch object. + """ + + return await self.c.patch( + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", + headers=self.config.get_headers(project_guid=project_guid, **kwargs), + json=config_key_rename, + ) + + # Managed Service API + @handle_and_munchify_response + async def list_providers(self) -> Munch: + """List all providers. + + Returns: + Munch: List of providers as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/managedservices/providers/", + headers=self.config.get_headers(with_project=False), + ) + + @handle_and_munchify_response + async def list_instances( + self, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + providers: list[str] = None, + ): + """List all instances in a project. + + Args: + cont (int, optional): Start index of instances. Defaults to 0. + limit (int, optional): Number of instances to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get instances from. Defaults to None. + providers (list[str], optional): Define providers to get instances from. Defaults to None. + + Returns: + Munch: List of instances as a Munch object. + """ + return await self.c.get( + url=f"{self.v2api_host}/v2/managedservices/", + headers=self.config.get_headers(), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + "providers": providers, + }, + ) + + @handle_and_munchify_response + async def get_instance(self, name: str) -> Munch: + """Get an instance by its name. + + Args: + name (str): Instance name + + Returns: + Munch: Instance details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/managedservices/{name}/", + headers=self.config.get_headers(), + ) + + @handle_and_munchify_response + async def create_instance(self, body: dict) -> Munch: + """Create a new instance. + + Returns: + Munch: Instance details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/managedservices/", + headers=self.config.get_headers(), + json=body, + ) + + @handle_and_munchify_response + async def delete_instance(self, name: str) -> Munch: + """Delete an instance. + + Returns: + Munch: Instance details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/managedservices/{name}/", + headers=self.config.get_headers(), + ) + + @handle_and_munchify_response + async def list_instance_bindings( + self, + instance_name: str, + cont: int = 0, + limit: int = 50, + label_selector: list[str] = None, + ): + """List all instance bindings in a project. + + Args: + instance_name (str): Instance name. + cont (int, optional): Start index of instance bindings. Defaults to 0. + limit (int, optional): Number of instance bindings to list. Defaults to 50. + label_selector (list[str], optional): Define labelSelector to get instance bindings from. Defaults to None. + + Returns: + Munch: List of instance bindings as a Munch object. + """ + return await self.c.get( + url=f"{self.v2api_host}/v2/managedservices/{instance_name}/bindings/", + headers=self.config.get_headers(), + params={ + "continue": cont, + "limit": limit, + "labelSelector": label_selector, + }, + ) + + @handle_and_munchify_response + async def create_instance_binding(self, instance_name: str, body: dict) -> Munch: + """Create a new instance binding. + + Args: + instance_name (str): Instance name. + body (object): Instance binding details. + + Returns: + Munch: Instance binding details as a Munch object. + """ + + return await self.c.post( + url=f"{self.v2api_host}/v2/managedservices/{instance_name}/bindings/", + headers=self.config.get_headers(), + json=body, + ) + + @handle_and_munchify_response + async def get_instance_binding(self, instance_name: str, name: str) -> Munch: + """Get an instance binding by its name. + + Args: + instance_name (str): Instance name. + name (str): Instance binding name. + + Returns: + Munch: Instance binding details as a Munch object. + """ + + return await self.c.get( + url=f"{self.v2api_host}/v2/managedservices/{instance_name}/bindings/{name}/", + headers=self.config.get_headers(), + ) + + @handle_and_munchify_response + async def delete_instance_binding(self, instance_name: str, name: str) -> Munch: + """Delete an instance binding. + + Args: + instance_name (str): Instance name. + name (str): Instance binding name. + + Returns: + Munch: Instance binding details as a Munch object. + """ + + return await self.c.delete( + url=f"{self.v2api_host}/v2/managedservices/{instance_name}/bindings/{name}/", + headers=self.config.get_headers(), + ) diff --git a/rapyuta_io_sdk_v2/client.py b/rapyuta_io_sdk_v2/client.py index bf9b5dd..0660586 100644 --- a/rapyuta_io_sdk_v2/client.py +++ b/rapyuta_io_sdk_v2/client.py @@ -112,11 +112,12 @@ def logout(self, token: str = None) -> Munch: }, ) - def refresh_token(self, token: str = None) -> str: + def refresh_token(self, token: str = None, set_token: bool = True) -> str: """Refresh the authentication token. Args: token (str): The token to refresh. + set_token (bool): Set the refreshed token in the configuration. Returns: str: The refreshed token. @@ -131,6 +132,8 @@ def refresh_token(self, token: str = None) -> str: json={"token": token}, ) handle_server_errors(response) + if set_token: + self.config.auth_token = response.json()["data"].get("token") return response.json()["data"].get("token") def set_organization(self, organization_guid: str) -> None: @@ -178,7 +181,6 @@ def get_project(self, project_guid: str = None, **kwargs) -> Munch: headers=self.config.get_headers(with_project=False, **kwargs), ) - # @handle_and_munchify_response @handle_and_munchify_response def list_projects( self, @@ -290,7 +292,6 @@ def list_packages( limit: int = 50, label_selector: list[str] = None, name: str = None, - regions: list[str] = None, **kwargs, ) -> Munch: """List all packages in a project. @@ -300,7 +301,6 @@ def list_packages( limit (int, optional): Number of packages to list. Defaults to 50. label_selector (list[str], optional): Define labelSelector to get packages from. Defaults to None. name (str, optional): Define name to get packages from. Defaults to None. - regions (list[str], optional): Define regions to get packages from. Defaults to None. Returns: Munch: List of packages as a Munch object. @@ -314,7 +314,6 @@ def list_packages( "limit": limit, "labelSelector": label_selector, "name": name, - "regions": regions, }, ) @@ -336,18 +335,20 @@ def create_package(self, body: dict, **kwargs) -> Munch: ) @handle_and_munchify_response - def get_package( - self, name: str, project_guid: str = None, version: str = None, **kwargs - ) -> Munch: + def get_package(self, name: str, version: str = None, **kwargs) -> Munch: """Get a package by its name. + Args: + name (str): Package name + version (str, optional): Package version. Defaults to None. + Returns: Munch: Package details as a Munch object. """ return self.c.get( url=f"{self.v2api_host}/v2/packages/{name}/", - headers=self.config.get_headers(project_guid=project_guid, **kwargs), + headers=self.config.get_headers(**kwargs), params={"version": version}, ) @@ -355,6 +356,9 @@ def get_package( def delete_package(self, name: str, **kwargs) -> Munch: """Delete a package by its name. + Args: + name (str): Package name + Returns: Munch: Package details as a Munch object. """ @@ -369,15 +373,15 @@ def delete_package(self, name: str, **kwargs) -> Munch: def list_deployments( self, cont: int = 0, + limit: int = 50, dependencies: bool = False, - deviceName: str = None, + device_name: str = None, guids: list[str] = None, label_selector: list[str] = None, - limit: int = 50, name: str = None, names: list[str] = None, - packageName: str = None, - packageVersion: str = None, + package_name: str = None, + package_version: str = None, phases: list[str] = None, regions: list[str] = None, **kwargs, @@ -386,15 +390,15 @@ def list_deployments( Args: cont (int, optional): Start index of deployments. Defaults to 0. + limit (int, optional): Number of deployments to list. Defaults to 50. dependencies (bool, optional): Filter by dependencies. Defaults to False. - deviceName (str, optional): Filter deployments by device name. Defaults to None. + device_name (str, optional): Filter deployments by device name. Defaults to None. guids (list[str], optional): Filter by GUIDs. Defaults to None. label_selector (list[str], optional): Define labelSelector to get deployments from. Defaults to None. - limit (int, optional): Number of deployments to list. Defaults to 50. name (str, optional): Define name to get deployments from. Defaults to None. names (list[str], optional): Define names to get deployments from. Defaults to None. - packageName (str, optional): Filter by package name. Defaults to None. - packageVersion (str, optional): Filter by package version. Defaults to None. + package_name (str, optional): Filter by package name. Defaults to None. + package_version (str, optional): Filter by package version. Defaults to None. phases (list[str], optional): Filter by phases. Available values : InProgress, Provisioning, Succeeded, FailedToUpdate, FailedToStart, Stopped. Defaults to None. regions (list[str], optional): Filter by regions. Defaults to None. @@ -409,13 +413,13 @@ def list_deployments( "continue": cont, "limit": limit, "dependencies": dependencies, - "deviceName": deviceName, + "deviceName": device_name, "guids": guids, "labelSelector": label_selector, "name": name, "names": names, - "packageName": packageName, - "packageVersion": packageVersion, + "packageName": package_name, + "packageVersion": package_version, "phases": phases, "regions": regions, }, @@ -449,7 +453,7 @@ def get_deployment(self, name: str, guid: str = None, **kwargs) -> Munch: return self.c.get( url=f"{self.v2api_host}/v2/deployments/{name}/", headers=self.config.get_headers(**kwargs), - json={"guid": guid}, + params={"guid": guid}, ) @handle_and_munchify_response @@ -513,7 +517,6 @@ def list_disks( cont: int = 0, label_selector: list[str] = None, limit: int = 50, - name: str = None, names: list[str] = None, regions: list[str] = None, status: list[str] = None, @@ -525,7 +528,6 @@ def list_disks( cont (int, optional): Start index of disks. Defaults to 0. label_selector (list[str], optional): Define labelSelector to get disks from. Defaults to None. limit (int, optional): Number of disks to list. Defaults to 50. - name (str, optional): Define name to get disks from. Defaults to None. names (list[str], optional): Define names to get disks from. Defaults to None. regions (list[str], optional): Define regions to get disks from. Defaults to None. status (list[str], optional): Define status to get disks from. Available values : Available, Bound, Released, Failed, Pending.Defaults to None. @@ -541,7 +543,6 @@ def list_disks( "continue": cont, "limit": limit, "labelSelector": label_selector, - "name": name, "names": names, "regions": regions, "status": status, @@ -599,10 +600,9 @@ def delete_disk(self, name: str, **kwargs) -> Munch: def list_staticroutes( self, cont: int = 0, + limit: int = 50, guids: list[str] = None, label_selector: list[str] = None, - limit: int = 50, - name: str = None, names: list[str] = None, regions: list[str] = None, **kwargs, @@ -611,10 +611,9 @@ def list_staticroutes( Args: cont (int, optional): Start index of static routes. Defaults to 0. + limit (int, optional): Number of static routes to list. Defaults to 50. guids (list[str], optional): Define guids to get static routes from. Defaults to None. label_selector (list[str], optional): Define labelSelector to get static routes from. Defaults to None. - limit (int, optional): Number of static routes to list. Defaults to 50. - name (str, optional): Define name to get static routes from. Defaults to None. names (list[str], optional): Define names to get static routes from. Defaults to None. regions (list[str], optional): Define regions to get static routes from. Defaults to None. @@ -630,7 +629,6 @@ def list_staticroutes( "limit": limit, "guids": guids, "labelSelector": label_selector, - "name": name, "names": names, "regions": regions, }, @@ -705,12 +703,11 @@ def delete_staticroute(self, name: str, **kwargs) -> Munch: def list_networks( self, cont: int = 0, - deviceName: str = None, - label_selector: list[str] = None, limit: int = 50, - name: str = None, + device_name: str = None, + label_selector: list[str] = None, names: list[str] = None, - networkType: str = None, + network_type: str = None, phases: list[str] = None, regions: list[str] = None, status: list[str] = None, @@ -720,12 +717,11 @@ def list_networks( Args: cont (int, optional): Start index of networks. Defaults to 0. - deviceName (str, optional): Filter networks by device name. Defaults to None. - label_selector (list[str], optional): Define labelSelector to get networks from. Defaults to None. limit (int, optional): Number of networks to list. Defaults to 50. - name (str, optional): Define name to get networks from. Defaults to None. + device_name (str, optional): Filter networks by device name. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get networks from. Defaults to None. names (list[str], optional): Define names to get networks from. Defaults to None. - networkType (str, optional): Define network type to get networks from. Defaults to None. + network_type (str, optional): Define network type to get networks from. Defaults to None. phases (list[str], optional): Define phases to get networks from. Available values : InProgress, Provisioning, Succeeded, FailedToUpdate, FailedToStart, Stopped. Defaults to None. regions (list[str], optional): Define regions to get networks from. Defaults to None. status (list[str], optional): Define status to get networks from. Available values : Running, Pending, Error, Unknown, Stopped. Defaults to None. @@ -740,11 +736,10 @@ def list_networks( params={ "continue": cont, "limit": limit, - "deviceName": deviceName, + "deviceName": device_name, "labelSelector": label_selector, - "name": name, "names": names, - "networkType": networkType, + "networkType": network_type, "phases": phases, "regions": regions, "status": status, @@ -802,9 +797,8 @@ def delete_network(self, name: str, **kwargs) -> Munch: def list_secrets( self, cont: int = 0, - label_selector: list[str] = None, limit: int = 50, - name: str = None, + label_selector: list[str] = None, names: list[str] = None, regions: list[str] = None, **kwargs, @@ -813,9 +807,8 @@ def list_secrets( Args: cont (int, optional): Start index of secrets. Defaults to 0. - label_selector (list[str], optional): Define labelSelector to get secrets from. Defaults to None. limit (int, optional): Number of secrets to list. Defaults to 50. - name (str, optional): Define name to get secrets from. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get secrets from. Defaults to None. names (list[str], optional): Define names to get secrets from. Defaults to None. regions (list[str], optional): Define regions to get secrets from. Defaults to None. @@ -830,7 +823,6 @@ def list_secrets( "continue": cont, "limit": limit, "labelSelector": label_selector, - "name": name, "names": names, "regions": regions, }, @@ -905,20 +897,18 @@ def delete_secret(self, name: str, **kwargs) -> Munch: def list_configtrees( self, cont: int = 0, - label_selector: list[str] = None, limit: int = 50, - name: str = None, - regions: list[str] = None, + label_selector: list[str] = None, + with_project: bool = True, **kwargs, ) -> Munch: """List all config trees in a project. Args: cont (int, optional): Start index of config trees. Defaults to 0. - label_selector (list[str], optional): Define labelSelector to get config trees from. Defaults to None. limit (int, optional): Number of config trees to list. Defaults to 50. - name (str, optional): Define name to get config trees from. Defaults to None. - regions (list[str], optional): Define regions to get config trees from. Defaults to None. + label_selector (list[str], optional): Define labelSelector to get config trees from. Defaults to None. + with_project (bool, optional): Include project. Defaults to True. Returns: Munch: List of config trees as a Munch object. @@ -926,22 +916,21 @@ def list_configtrees( return self.c.get( url=f"{self.v2api_host}/v2/configtrees/", - headers=self.config.get_headers(**kwargs), + headers=self.config.get_headers(with_project=with_project, **kwargs), params={ "continue": cont, "limit": limit, "labelSelector": label_selector, - "name": name, - "regions": regions, }, ) @handle_and_munchify_response - def create_configtree(self, body: dict, **kwargs) -> Munch: + def create_configtree(self, body: dict, with_project: bool = True, **kwargs) -> Munch: """Create a new config tree. Args: body (object): Config tree details + with_project (bool, optional): Work in the project scope. Defaults to True. Returns: Munch: Config tree details as a Munch object. @@ -949,7 +938,7 @@ def create_configtree(self, body: dict, **kwargs) -> Munch: return self.c.post( url=f"{self.v2api_host}/v2/configtrees/", - headers=self.config.get_headers(**kwargs), + headers=self.config.get_headers(with_project=with_project, **kwargs), json=body, ) @@ -957,20 +946,22 @@ def create_configtree(self, body: dict, **kwargs) -> Munch: def get_configtree( self, name: str, - contentTypes: list[str] = None, - includeData: bool = False, - keyPrefixes: list[str] = None, + content_types: list[str] = None, + include_data: bool = False, + key_prefixes: list[str] = None, revision: str = None, + with_project: bool = True, **kwargs, ) -> Munch: """Get a config tree by its name. Args: name (str): Config tree name - contentTypes (list[str], optional): Define contentTypes to get config tree from. Defaults to None. - includeData (bool, optional): Include data. Defaults to False. - keyPrefixes (list[str], optional): Define keyPrefixes to get config tree from. Defaults to None. + content_types (list[str], optional): Define contentTypes to get config tree from. Defaults to None. + include_data (bool, optional): Include data. Defaults to False. + key_prefixes (list[str], optional): Define keyPrefixes to get config tree from. Defaults to None. revision (str, optional): Define revision to get config tree from. Defaults to None. + with_project (bool, optional): Work in the project scope. Defaults to True. Returns: Munch: Config tree details as a Munch object. @@ -978,11 +969,11 @@ def get_configtree( return self.c.get( url=f"{self.v2api_host}/v2/configtrees/{name}/", - headers=self.config.get_headers(**kwargs), + headers=self.config.get_headers(with_project=with_project, **kwargs), params={ - "contentTypes": contentTypes, - "includeData": includeData, - "keyPrefixes": keyPrefixes, + "contentTypes": content_types, + "includeData": include_data, + "keyPrefixes": key_prefixes, "revision": revision, }, ) @@ -1009,12 +1000,15 @@ def set_configtree_revision( ) @handle_and_munchify_response - def update_configtree(self, name: str, body: dict, **kwargs) -> Munch: + def update_configtree( + self, name: str, body: dict, with_project: bool = True, **kwargs + ) -> Munch: """Update a config tree by its name. Args: name (str): Config tree name body (dict): Update details + with_project (bool, optional): Work in the project scope. Defaults to True. Returns: Munch: Config tree details as a Munch object. @@ -1022,7 +1016,7 @@ def update_configtree(self, name: str, body: dict, **kwargs) -> Munch: return self.c.put( url=f"{self.v2api_host}/v2/configtrees/{name}/", - headers=self.config.get_headers(**kwargs), + headers=self.config.get_headers(with_project=with_project, **kwargs), json=body, ) @@ -1045,37 +1039,34 @@ def delete_configtree(self, name: str, **kwargs) -> Munch: @handle_and_munchify_response def list_revisions( self, - name: str, + tree_name: str, cont: int = 0, limit: int = 50, committed: bool = False, label_selector: list[str] = None, - regions: list[str] = None, **kwargs, ) -> Munch: """List all revisions of a config tree. Args: - name (str): Config tree name + tree_name (str): Config tree name cont (int, optional): Continue param . Defaults to 0. limit (int, optional): Limit param . Defaults to 50. committed (bool, optional): Committed. Defaults to False. label_selector (list[str], optional): Define labelSelector to get revisions from. Defaults to None. - regions (list[str], optional): Define regions to get revisions from. Defaults to None. Returns: Munch: List of revisions as a Munch object. """ return self.c.get( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/", headers=self.config.get_headers(**kwargs), params={ "continue": cont, "limit": limit, "committed": committed, "labelSelector": label_selector, - "regions": regions, }, ) @@ -1102,10 +1093,15 @@ def create_revision( @handle_and_munchify_response def put_keys_in_revision( - self, name: str, revision_id: str, configValues: list[(object)], **kwargs + self, name: str, revision_id: str, config_values: dict, **kwargs ) -> Munch: """Put keys in a revision. + Args: + name (str): Config tree name + revision_id (str): Config tree revision ID + config_values (dict): Config values + Returns: Munch: Revision details as a Munch object. """ @@ -1113,38 +1109,55 @@ def put_keys_in_revision( return self.c.put( url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/keys/", headers=self.config.get_headers(**kwargs), - json=configValues, + json=config_values, ) @handle_and_munchify_response def commit_revision( self, - name: str, + tree_name: str, revision_id: str, - configTreeRevision: dict, + author: str = None, + message: str = None, project_guid: str = None, **kwargs, ) -> Munch: """Commit a revision. + Args: + tree_name (str): Config tree name + revision_id (str): Config tree revision ID + author (str, optional): Revision Author. Defaults to None. + message (str, optional): Revision Message. Defaults to None. + project_guid (str, optional): Project GUID. Defaults to None. + Returns: Munch: Revision details as a Munch object. """ + config_tree_revision = { + "author": author, + "message": message, + } return self.c.patch( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/commit/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/commit/", headers=self.config.get_headers(project_guid=project_guid, **kwargs), - json=configTreeRevision, + json=config_tree_revision, ) @handle_and_munchify_response def get_key_in_revision( - self, name: str, revision_id: str, key: str, project_guid: str = None, **kwargs + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, ) -> Munch: """Get a key in a revision. Args: - name (str): Config tree name + tree_name (str): Config tree name revision_id (str): Config tree revision ID key (str): Key project_guid (str, optional): Project GUID. Defaults to None. @@ -1154,18 +1167,23 @@ def get_key_in_revision( """ return self.c.get( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/{key}/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", headers=self.config.get_headers(project_guid=project_guid, **kwargs), ) @handle_and_munchify_response def put_key_in_revision( - self, name: str, revision_id: str, key: str, project_guid: str = None, **kwargs + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, ) -> Munch: """Put a key in a revision. Args: - name (str): Config tree name + tree_name (str): Config tree name revision_id (str): Config tree revision ID key (str): Key project_guid (str, optional): Project GUID. Defaults to None. @@ -1175,18 +1193,23 @@ def put_key_in_revision( """ return self.c.put( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/{key}/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", headers=self.config.get_headers(project_guid=project_guid, **kwargs), ) @handle_and_munchify_response def delete_key_in_revision( - self, name: str, revision_id: str, key: str, project_guid: str = None, **kwargs + self, + tree_name: str, + revision_id: str, + key: str, + project_guid: str = None, + **kwargs, ) -> Munch: """Delete a key in a revision. Args: - name (str): Config tree name + tree_name (str): Config tree name revision_id (str): Config tree revision ID key (str): Key project_guid (str, optional): Project GUID. Defaults to None. @@ -1196,27 +1219,27 @@ def delete_key_in_revision( """ return self.c.delete( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/{key}/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", headers=self.config.get_headers(project_guid=project_guid, **kwargs), ) @handle_and_munchify_response def rename_key_in_revision( self, - name: str, + tree_name: str, revision_id: str, key: str, - configKeyRename: dict, + config_key_rename: dict, project_guid: str = None, **kwargs, ) -> Munch: """Rename a key in a revision. Args: - name (str): Config tree name + tree_name (str): Config tree name revision_id (str): Config tree revision ID key (str): Key - configKeyRename (object): Key rename details + config_key_rename (object): Key rename details project_guid (str, optional): Project GUID. Defaults to None. Returns: @@ -1224,9 +1247,9 @@ def rename_key_in_revision( """ return self.c.patch( - url=f"{self.v2api_host}/v2/configtrees/{name}/revisions/{revision_id}/{key}/", + url=f"{self.v2api_host}/v2/configtrees/{tree_name}/revisions/{revision_id}/{key}/", headers=self.config.get_headers(project_guid=project_guid, **kwargs), - json=configKeyRename, + json=config_key_rename, ) # Managed Service API @@ -1249,9 +1272,7 @@ def list_instances( cont: int = 0, limit: int = 50, label_selector: list[str] = None, - regions: list[str] = None, - guid: str = None, - name: str = None, + providers: list[str] = None, ): """List all instances in a project. @@ -1259,9 +1280,7 @@ def list_instances( cont (int, optional): Start index of instances. Defaults to 0. limit (int, optional): Number of instances to list. Defaults to 50. label_selector (list[str], optional): Define labelSelector to get instances from. Defaults to None. - regions (list[str], optional): Define regions to get instances from. Defaults to None. - guid (str, optional): Defaults to None. - name (str, optional): Defaults to None. + providers (list[str], optional): Define providers to get instances from. Defaults to None. Returns: Munch: List of instances as a Munch object. @@ -1273,9 +1292,7 @@ def list_instances( "continue": cont, "limit": limit, "labelSelector": label_selector, - "regions": regions, - "guid": guid, - "name": name, + "providers": providers, }, ) @@ -1329,9 +1346,6 @@ def list_instance_bindings( cont: int = 0, limit: int = 50, label_selector: list[str] = None, - regions: list[str] = None, - guid: str = None, - name: str = None, ): """List all instance bindings in a project. @@ -1340,9 +1354,6 @@ def list_instance_bindings( cont (int, optional): Start index of instance bindings. Defaults to 0. limit (int, optional): Number of instance bindings to list. Defaults to 50. label_selector (list[str], optional): Define labelSelector to get instance bindings from. Defaults to None. - regions (list[str], optional): Define regions to get instance bindings from. Defaults to None. - guid (str, optional): Defaults to None. - name (str, optional): Defaults to None. Returns: Munch: List of instance bindings as a Munch object. @@ -1354,9 +1365,6 @@ def list_instance_bindings( "continue": cont, "limit": limit, "labelSelector": label_selector, - "regions": regions, - "guid": guid, - "name": name, }, ) diff --git a/rapyuta_io_sdk_v2/config.py b/rapyuta_io_sdk_v2/config.py index 8c7f1d8..bd24e21 100644 --- a/rapyuta_io_sdk_v2/config.py +++ b/rapyuta_io_sdk_v2/config.py @@ -78,8 +78,9 @@ def get_headers( """Get the headers for the configuration. Args: + organization_guid (str): The organization guid. with_project (bool): Whether to include the project headers. - **kwargs: Arbitrary keyword arguments. + project_guid (str): The project guid. Returns: dict: Headers for the configuration. diff --git a/rapyuta_io_sdk_v2/utils.py b/rapyuta_io_sdk_v2/utils.py index c6ac788..e16fcd9 100644 --- a/rapyuta_io_sdk_v2/utils.py +++ b/rapyuta_io_sdk_v2/utils.py @@ -149,3 +149,38 @@ def walk_pages( cont = data.get("metadata", {}).get("continue") if cont is None: break + + +async def walk_pages_async( + func: typing.Callable, + *args, + limit: int = 50, + cont: int = 0, + **kwargs, +) -> typing.AsyncGenerator: + """A generator function to paginate through list API results. + + Args: + func (callable): The API function to call, must accept `cont` and `limit` as arguments. + *args: Positional arguments to pass to the API function. + limit (int, optional): Maximum number of items to return. Defaults to 50. + cont (int, optional): Initial continuation token. Defaults to 0. + **kwargs: Additional keyword arguments to pass to the API function. + + Yields: + Munch: Each item from the API response. + """ + while True: + data = await func(cont, limit, *args, **kwargs) + + items = data.get("items", []) + if not items: + break + + for item in items: + yield munchify(item) + + # Update `cont` for the next page + cont = data.get("metadata", {}).get("continue") + if cont is None: + break diff --git a/tests/async_tests/test_configtree_async.py b/tests/async_tests/test_configtree_async.py new file mode 100644 index 0000000..8976496 --- /dev/null +++ b/tests/async_tests/test_configtree_async.py @@ -0,0 +1,362 @@ +import httpx +import pytest +import pytest_asyncio # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import configtree_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_configtrees_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-configtree", "guid": "mock_configtree_guid"}], + }, + ) + + # Call the list_configtrees method + response = await client.list_configtrees() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-configtree", "guid": "mock_configtree_guid"} + ] + + +@pytest.mark.asyncio +async def test_list_configtrees_bad_gateway(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=502, + json={"error": "bad gateway"}, + ) + + # Call the list_configtrees method + with pytest.raises(Exception) as exc: + await client.list_configtrees() + + assert str(exc.value) == "bad gateway" + + +@pytest.mark.asyncio +async def test_create_configtree_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "test_configtree_guid", "name": "test_configtree"}, + }, + ) + + # Call the create_configtree method + response = await client.create_configtree(configtree_body) + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_configtree_guid" + + +@pytest.mark.asyncio +async def test_create_configtree_service_unavailable(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=503, + json={"error": "service unavailable"}, + ) + + # Call the create_configtree method + with pytest.raises(Exception) as exc: + await client.create_configtree(configtree_body) + + assert str(exc.value) == "service unavailable" + + +@pytest.mark.asyncio +async def test_get_configtree_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_configtree_guid", "name": "test_configtree"}, + }, + ) + + # Call the get_configtree method + response = await client.get_configtree(name="mock_configtree_name") + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_configtree_guid" + assert response.metadata.name == "test_configtree" + + +@pytest.mark.asyncio +async def test_set_configtree_revision_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_configtree_guid", "name": "test_configtree"}, + }, + ) + + # Call the set_configtree_revision method + response = await client.set_configtree_revision( + name="mock_configtree_name", configtree=configtree_body + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_configtree_guid" + assert response.metadata.name == "test_configtree" + + +@pytest.mark.asyncio +async def test_update_configtree_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_configtree_guid", "name": "test_configtree"}, + }, + ) + + # Call the update_configtree method + response = await client.update_configtree( + name="mock_configtree_name", body=configtree_body + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_configtree_guid" + assert response.metadata.name == "test_configtree" + + +@pytest.mark.asyncio +async def test_delete_configtree_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_configtree method + response = await client.delete_configtree(name="mock_configtree_name") + + # Validate the response + assert response["success"] is True + + +@pytest.mark.asyncio +async def test_list_revisions_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-configtree", "guid": "mock_configtree_guid"}], + }, + ) + + # Call the list_revisions method + response = await client.list_revisions(tree_name="mock_configtree_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-configtree", "guid": "mock_configtree_guid"} + ] + + +@pytest.mark.asyncio +async def test_create_revision_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + # Call the create_revision method + response = await client.create_revision( + name="mock_configtree_name", body=configtree_body + ) + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_revision_guid" + + +@pytest.mark.asyncio +async def test_put_keys_in_revision_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + # Call the put_keys_in_revision method + response = await client.put_keys_in_revision( + name="mock_configtree_name", + revision_id="mock_revision_id", + config_values=["mock_value1", "mock_value2"], + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_revision_guid" + assert response.metadata.name == "test_revision" + + +@pytest.mark.asyncio +async def test_commit_revision_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_patch = mocker.patch("httpx.AsyncClient.patch") + + # Set up the mock response + mock_patch.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + # Call the commit_revision method + response = await client.commit_revision( + tree_name="mock_configtree_name", + revision_id="mock_revision_id", + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_revision_guid" + assert response.metadata.name == "test_revision" + + +@pytest.mark.asyncio +async def test_get_key_in_revision(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + # Call the get_key_in_revision method + response = await client.get_key_in_revision( + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_revision_guid" + assert response.metadata.name == "test_revision" + + +@pytest.mark.asyncio +async def test_put_key_in_revision_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + # Call the put_key_in_revision method + response = await client.put_key_in_revision( + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_revision_guid" + assert response.metadata.name == "test_revision" + + +@pytest.mark.asyncio +async def test_delete_key_in_revision_success(client, mocker: AsyncMock): # noqa: F811 + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + response = await client.delete_key_in_revision( + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + ) + + assert response["success"] is True + + +@pytest.mark.asyncio +async def test_rename_key_in_revision_success(client, mocker: AsyncMock): # noqa: F811 + mock_patch = mocker.patch("httpx.AsyncClient.patch") + + mock_patch.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_revision_guid", "name": "test_revision"}, + }, + ) + + response = await client.rename_key_in_revision( + tree_name="mock_configtree_name", + revision_id="mock_revision_id", + key="mock_key", + config_key_rename={"metadata": {"name": "test_key"}}, + ) + + assert isinstance(response, Munch) + assert response.metadata.guid == "test_revision_guid" + assert response.metadata.name == "test_revision" diff --git a/tests/async_tests/test_deployment_async.py b/tests/async_tests/test_deployment_async.py new file mode 100644 index 0000000..f124148 --- /dev/null +++ b/tests/async_tests/test_deployment_async.py @@ -0,0 +1,153 @@ +import httpx +import pytest +import pytest_asyncio # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import deployment_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_deployments_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get") method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-deployment", "guid": "mock_deployment_guid"}], + }, + ) + + # Call the list_deployments method + response = await client.list_deployments() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-deployment", "guid": "mock_deployment_guid"} + ] + + +@pytest.mark.asyncio +async def test_list_deployments_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get") method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_deployments() + + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_get_deployment_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get") method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + # Call the get_deployment method + response = await client.get_deployment(name="mock_deployment_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +@pytest.mark.asyncio +async def test_get_deployment_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get") method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "deployment not found"}, + ) + + # Call the get_deployment method + with pytest.raises(Exception) as exc: + await client.get_deployment(name="mock_deployment_name") + + assert str(exc.value) == "deployment not found" + + +@pytest.mark.asyncio +async def test_create_deployment_success(client, deployment_body, mocker: AsyncMock): # noqa: F811 + mock_post = mocker.patch("httpx.AsyncClient.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + response = await client.create_deployment(body=deployment_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +@pytest.mark.asyncio +async def test_create_deployment_unauthorized(client, deployment_body, mocker: AsyncMock): # noqa: F811 + mock_post = mocker.patch("httpx.AsyncClient.post") + + mock_post.return_value = httpx.Response( + status_code=401, + json={"error": "unauthorized"}, + ) + + with pytest.raises(Exception) as exc: + await client.create_deployment(body=deployment_body) + + assert str(exc.value) == "unauthorized" + + +@pytest.mark.asyncio +async def test_update_deployment_success(client, deployment_body, mocker: AsyncMock): # noqa: F811 + mock_put = mocker.patch("httpx.AsyncClient.put") + + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + response = await client.update_deployment( + name="mock_deployment_name", body=deployment_body + ) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +@pytest.mark.asyncio +async def test_delete_deployment_success(client, mocker: AsyncMock): # noqa: F811 + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + mock_delete.return_value = httpx.Response(status_code=204, json={"success": True}) + + response = await client.delete_deployment(name="mock_deployment_name") + + assert response["success"] is True diff --git a/tests/async_tests/test_disk_async.py b/tests/async_tests/test_disk_async.py new file mode 100644 index 0000000..78f7d1a --- /dev/null +++ b/tests/async_tests/test_disk_async.py @@ -0,0 +1,142 @@ +import httpx +import pytest +import pytest_asyncio # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import disk_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_disks_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-disk", "guid": "mock_disk_guid"}], + }, + ) + + # Call the list_disks method + response = await client.list_disks() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-disk", "guid": "mock_disk_guid"}] + + +@pytest.mark.asyncio +async def test_list_disks_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_disks() + + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_get_disk_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Disk", + "metadata": {"guid": "test_disk_guid", "name": "mock_disk_name"}, + }, + ) + + # Call the get_disk method + response = await client.get_disk(name="mock_disk_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_disk_guid" + + +@pytest.mark.asyncio +async def test_get_disk_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "disk not found"}, + ) + + # Call the get_disk method + with pytest.raises(Exception) as exc: + await client.get_disk(name="mock_disk_name") + + assert str(exc.value) == "disk not found" + + +@pytest.mark.asyncio +async def test_create_disk_success(client, disk_body, mocker: AsyncMock): # noqa: F811 + mock_post = mocker.patch("httpx.AsyncClient.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Disk", + "metadata": {"guid": "test_disk_guid", "name": "test_disk"}, + }, + ) + + response = await client.create_disk(body=disk_body, project_guid="mock_project_guid") + + assert isinstance(response, Munch) + assert response.metadata.guid == "test_disk_guid" + assert response.metadata.name == "test_disk" + + +@pytest.mark.asyncio +async def test_delete_disk_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_disk method + response = await client.delete_disk(name="mock_disk_name") + + # Validate the response + assert response["success"] is True + + +@pytest.mark.asyncio +async def test_delete_disk_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=404, + json={"error": "disk not found"}, + ) + + # Call the delete_disk method + with pytest.raises(Exception) as exc: + await client.delete_disk(name="mock_disk_name") + + assert str(exc.value) == "disk not found" diff --git a/tests/async_tests/test_managedservice_async.py b/tests/async_tests/test_managedservice_async.py new file mode 100644 index 0000000..d670583 --- /dev/null +++ b/tests/async_tests/test_managedservice_async.py @@ -0,0 +1,208 @@ +import httpx +import pytest # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_providers_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-provider", "guid": "mock_provider_guid"}], + }, + ) + + # Call the list_providers method + response = await client.list_providers() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-provider", "guid": "mock_provider_guid"}] + + +@pytest.mark.asyncio +async def test_list_instances_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-instance", "guid": "mock_instance_guid"}], + }, + ) + + # Call the list_instances method + response = await client.list_instances() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-instance", "guid": "mock_instance_guid"}] + + +@pytest.mark.asyncio +async def test_get_instance_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_instance_guid", "name": "test_instance"}, + }, + ) + + # Call the get_instance method + response = await client.get_instance(name="mock_instance_name") + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_instance_guid" + + +@pytest.mark.asyncio +async def test_create_instance_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "test_instance_guid", "name": "test_instance"}, + }, + ) + + # Call the create_instance method + response = await client.create_instance(body={"name": "test_instance"}) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_instance_guid" + + +@pytest.mark.asyncio +async def test_delete_instance_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_instance method + response = await client.delete_instance(name="mock_instance_name") + + # Validate the response + assert response["success"] is True + + +@pytest.mark.asyncio +async def test_list_instance_bindings_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [ + {"name": "test-instance-binding", "guid": "mock_instance_binding_guid"} + ], + }, + ) + + # Call the list_instance_bindings method + response = await client.list_instance_bindings("mock_instance_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-instance-binding", "guid": "mock_instance_binding_guid"} + ] + + +@pytest.mark.asyncio +async def test_get_instance_binding_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": { + "guid": "test_instance_binding_guid", + "name": "test_instance_binding", + }, + }, + ) + + # Call the get_instance_binding method + response = await client.get_instance_binding( + name="mock_instance_binding_name", instance_name="mock_instance_name" + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_instance_binding_guid" + + +@pytest.mark.asyncio +async def test_create_instance_binding_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": { + "guid": "test_instance_binding_guid", + "name": "test_instance_binding", + }, + }, + ) + + # Call the create_instance_binding method + response = await client.create_instance_binding( + body={"name": "test_instance_binding"}, instance_name="mock_instance_name" + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_instance_binding_guid" + + +@pytest.mark.asyncio +async def test_delete_instance_binding_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_instance_binding method + response = await client.delete_instance_binding( + name="mock_instance_binding_name", instance_name="mock_instance_name" + ) + + # Validate the response + assert response["success"] is True diff --git a/tests/async_tests/test_network_async.py b/tests/async_tests/test_network_async.py new file mode 100644 index 0000000..0512404 --- /dev/null +++ b/tests/async_tests/test_network_async.py @@ -0,0 +1,124 @@ +import httpx +import pytest +import pytest_asyncio # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import network_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_networks_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-network", "guid": "mock_network_guid"}], + }, + ) + + # Call the list_networks method + response = await client.list_networks() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-network", "guid": "mock_network_guid"}] + + +@pytest.mark.asyncio +async def test_list_networks_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_networks() + + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_create_network_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "mock_network_guid", "name": "test-network"}, + }, + ) + + # Call the create_network method + response = await client.create_network(body=network_body) + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["name"] == "test-network" + + +@pytest.mark.asyncio +async def test_create_network_failure(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=409, + json={"error": "already exists"}, + ) + + with pytest.raises(Exception) as exc: + await client.create_network(body=network_body) + + assert str(exc.value) == "already exists" + + +@pytest.mark.asyncio +async def test_get_network_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "mock_network_guid", "name": "test-network"}, + }, + ) + + # Call the get_network method + response = await client.get_network(name="test-network") + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_network_guid" + + +@pytest.mark.asyncio +async def test_delete_network_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_network method + response = await client.delete_network(name="test-network") + + # Validate the response + assert response["success"] is True diff --git a/tests/async_tests/test_package_async.py b/tests/async_tests/test_package_async.py new file mode 100644 index 0000000..cc40cea --- /dev/null +++ b/tests/async_tests/test_package_async.py @@ -0,0 +1,106 @@ +import pytest +import pytest_asyncio # noqa: F401 +import httpx +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import package_body +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_packages_success(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test_package", "guid": "mock_package_guid"}], + }, + ) + + response = await client.list_packages() + + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test_package", "guid": "mock_package_guid"}] + + +@pytest.mark.asyncio +async def test_list_packages_not_found(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_packages() + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_create_package_success(client, mocker: AsyncMock): # noqa: F811 + mock_post = mocker.patch("httpx.AsyncClient.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Package", + "metadata": {"name": "test-package", "guid": "mock_package_guid"}, + "spec": {"users": [{"userGUID": "mock_user_guid", "emailID": "mock_email"}]}, + }, + ) + + response = await client.create_package(package_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_package_guid" + + +@pytest.mark.asyncio +async def test_get_package_success(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Package", + "metadata": {"name": "test-package", "guid": "mock_package_guid"}, + "spec": {"users": [{"userGUID": "mock_user_guid", "emailID": "mock_email"}]}, + }, + ) + + response = await client.get_package("mock_package_guid") + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_package_guid" + + +@pytest.mark.asyncio +async def test_get_package_not_found(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.get_package("mock_package_guid") + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_delete_package_success(client, mocker: AsyncMock): # noqa: F811 + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + response = await client.delete_package("mock_package_guid") + + assert response["success"] is True diff --git a/tests/async_tests/test_project_async.py b/tests/async_tests/test_project_async.py new file mode 100644 index 0000000..8f4956c --- /dev/null +++ b/tests/async_tests/test_project_async.py @@ -0,0 +1,97 @@ +import pytest +import pytest_asyncio # noqa: F401 +import httpx +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import project_body +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_projects_success(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-project", "guid": "mock_project_guid"}], + }, + ) + + response = await client.list_projects() + + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-project", "guid": "mock_project_guid"}] + + +@pytest.mark.asyncio +async def test_create_project_success(client, mocker: AsyncMock): # noqa: F811 + mock_post = mocker.patch("httpx.AsyncClient.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Project", + "metadata": {"name": "test-project", "guid": "mock_project_guid"}, + "spec": { + "users": [ + {"userGUID": "mock_user_guid", "emailID": "test.user@example.com"} + ] + }, + }, + ) + + response = await client.create_project(project_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_project_guid" + + +@pytest.mark.asyncio +async def test_get_project_success(client, mocker: AsyncMock): # noqa: F811 + mock_get = mocker.patch("httpx.AsyncClient.get") + + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Project", + "metadata": {"name": "test-project", "guid": "mock_project_guid"}, + }, + ) + + response = await client.get_project("mock_project_guid") + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_project_guid" + + +@pytest.mark.asyncio +async def test_update_project_success(client, mocker: AsyncMock): # noqa: F811 + mock_put = mocker.patch("httpx.AsyncClient.put") + + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Project", + "metadata": {"name": "test-project", "guid": "mock_project_guid"}, + }, + ) + + response = await client.update_project("mock_project_guid", project_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "mock_project_guid" + + +@pytest.mark.asyncio +async def test_delete_project_success(client, mocker: AsyncMock): # noqa: F811 + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + mock_delete.return_value = httpx.Response(status_code=200, json={"success": True}) + + response = await client.delete_project("mock_project_guid") + + assert isinstance(response, Munch) + assert response["success"] is True diff --git a/tests/async_tests/test_secret_async.py b/tests/async_tests/test_secret_async.py new file mode 100644 index 0000000..3e86a65 --- /dev/null +++ b/tests/async_tests/test_secret_async.py @@ -0,0 +1,146 @@ +import httpx +import pytest +import pytest_asyncio # noqa: F401 +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import secret_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_secrets_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-secret", "guid": "mock_secret_guid"}], + }, + ) + + # Call the list_secrets method + response = await client.list_secrets() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-secret", "guid": "mock_secret_guid"}] + + +@pytest.mark.asyncio +async def test_list_secrets_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_secrets() + + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_create_secret_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "test_secret_guid", "name": "test_secret"}, + }, + ) + + # Call the create_secret method + response = await client.create_secret(secret_body) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_secret_guid" + + +@pytest.mark.asyncio +async def test_create_secret_already_exists(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=409, + json={"error": "secret already exists"}, + ) + + with pytest.raises(Exception) as exc: + await client.create_secret(secret_body) + + assert str(exc.value) == "secret already exists" + + +@pytest.mark.asyncio +async def test_update_secret_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_secret_guid", "name": "test_secret"}, + }, + ) + + # Call the update_secret method + response = await client.update_secret("mock_secret_guid", body=secret_body) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_secret_guid" + + +@pytest.mark.asyncio +async def test_delete_secret_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_secret method + response = await client.delete_secret("mock_secret_guid") + + # Validate the response + assert response == {"success": True} + + +@pytest.mark.asyncio +async def test_get_secret_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_secret_guid", "name": "test_secret"}, + }, + ) + + # Call the get_secret method + response = await client.get_secret("mock_secret_guid") + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_secret_guid" + assert response.metadata.name == "test_secret" diff --git a/tests/async_tests/test_staticroute_async.py b/tests/async_tests/test_staticroute_async.py new file mode 100644 index 0000000..91e7da3 --- /dev/null +++ b/tests/async_tests/test_staticroute_async.py @@ -0,0 +1,148 @@ +import httpx +import pytest +from munch import Munch +from asyncmock import AsyncMock + +from tests.data.mock_data import staticroute_body # noqa: F401 +from tests.utils.fixtures import async_client as client # noqa: F401 + + +@pytest.mark.asyncio +async def test_list_staticroutes_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-staticroute", "guid": "mock_staticroute_guid"}], + }, + ) + + # Call the list_staticroutes method + response = await client.list_staticroutes() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-staticroute", "guid": "mock_staticroute_guid"} + ] + + +@pytest.mark.asyncio +async def test_list_staticroutes_not_found(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + await client.list_staticroutes() + + assert str(exc.value) == "not found" + + +@pytest.mark.asyncio +async def test_create_staticroute_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=201, + json={ + "metadata": {"guid": "test_staticroute_guid", "name": "test_staticroute"}, + }, + ) + + # Call the create_staticroute method + response = await client.create_staticroute(body=staticroute_body) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_staticroute_guid" + + +@pytest.mark.asyncio +async def test_create_staticroute_bad_request(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.post method + mock_post = mocker.patch("httpx.AsyncClient.post") + + # Set up the mock response + mock_post.return_value = httpx.Response( + status_code=409, + json={"error": "already exists"}, + ) + + with pytest.raises(Exception) as exc: + await client.create_staticroute(body=staticroute_body) + + assert str(exc.value) == "already exists" + + +@pytest.mark.asyncio +async def test_get_staticroute_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.get method + mock_get = mocker.patch("httpx.AsyncClient.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_staticroute_guid", "name": "test_staticroute"}, + }, + ) + + # Call the get_staticroute method + response = await client.get_staticroute(name="mock_staticroute_name") + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_staticroute_guid" + + +@pytest.mark.asyncio +async def test_update_staticroute_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.put method + mock_put = mocker.patch("httpx.AsyncClient.put") + + # Set up the mock response + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"guid": "test_staticroute_guid", "name": "test_staticroute"}, + }, + ) + + # Call the update_staticroute method + response = await client.update_staticroute( + name="mock_staticroute_name", body=staticroute_body + ) + + # Validate the response + assert isinstance(response, Munch) + assert response.metadata.guid == "test_staticroute_guid" + + +@pytest.mark.asyncio +async def test_delete_staticroute_success(client, mocker: AsyncMock): # noqa: F811 + # Mock the httpx.AsyncClient.delete method + mock_delete = mocker.patch("httpx.AsyncClient.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_staticroute method + response = await client.delete_staticroute(name="mock_staticroute_name") + + # Validate the response + assert response["success"] is True diff --git a/tests/utils/test_util.py b/tests/data/mock_data.py similarity index 86% rename from tests/utils/test_util.py rename to tests/data/mock_data.py index a18174d..08e5887 100644 --- a/tests/utils/test_util.py +++ b/tests/data/mock_data.py @@ -1,17 +1,6 @@ import pytest -from rapyuta_io_sdk_v2 import Client, Configuration - - -# Fixture to initialize the Client -@pytest.fixture -def client(): - client = Client() - client.config.hosts["v2api_host"] = "https://mock-api.rapyuta.io" - client.auth_token = "mock_token" - client.organization_guid = "mock_org_guid" - client.project = "mock_project_guid" - return client +from rapyuta_io_sdk_v2 import Configuration @pytest.fixture @@ -20,9 +9,7 @@ def mock_response_project(): "kind": "Project", "metadata": {"name": "test-project", "guid": "mock_project_guid"}, "spec": { - "users": [ - {"userGUID": "mock_user_guid", "emailID": "test.user@example.com"} - ] + "users": [{"userGUID": "mock_user_guid", "emailID": "test.user@example.com"}] }, } diff --git a/tests/test_config.py b/tests/sync_tests/test_config.py similarity index 97% rename from tests/test_config.py rename to tests/sync_tests/test_config.py index f15f745..3d5edf7 100644 --- a/tests/test_config.py +++ b/tests/sync_tests/test_config.py @@ -1,6 +1,6 @@ import json from rapyuta_io_sdk_v2.config import Configuration -from tests.utils.test_util import mock_config # noqa: F401 +from tests.data.mock_data import mock_config # noqa: F401 def test_from_file(mocker): diff --git a/tests/test_configtree.py b/tests/sync_tests/test_configtree.py similarity index 51% rename from tests/test_configtree.py rename to tests/sync_tests/test_configtree.py index f9efd85..3d2f27a 100644 --- a/tests/test_configtree.py +++ b/tests/sync_tests/test_configtree.py @@ -1,12 +1,13 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client, configtree_body # noqa: F401 +from tests.data.mock_data import configtree_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_configtrees_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_configtrees_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,17 +20,6 @@ def test_list_configtrees_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_configtrees method response = client.list_configtrees() @@ -40,7 +30,7 @@ def test_list_configtrees_success(client, mocker: MockerFixture): # noqa: F811 ] -def test_list_configtrees_bad_gateway(client, mocker: MockerFixture): # noqa: F811 +def test_list_configtrees_bad_gateway(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -50,13 +40,6 @@ def test_list_configtrees_bad_gateway(client, mocker: MockerFixture): # noqa: F json={"error": "bad gateway"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the list_configtrees method with pytest.raises(Exception) as exc: client.list_configtrees() @@ -64,7 +47,7 @@ def test_list_configtrees_bad_gateway(client, mocker: MockerFixture): # noqa: F assert str(exc.value) == "bad gateway" -def test_create_configtree_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_configtree_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -76,13 +59,6 @@ def test_create_configtree_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the create_configtree method response = client.create_configtree(configtree_body) @@ -91,7 +67,7 @@ def test_create_configtree_success(client, mocker: MockerFixture): # noqa: F811 assert response["metadata"]["guid"] == "test_configtree_guid" -def test_create_configtree_service_unavailable(client, mocker: MockerFixture): # noqa: F811 +def test_create_configtree_service_unavailable(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -101,13 +77,6 @@ def test_create_configtree_service_unavailable(client, mocker: MockerFixture): json={"error": "service unavailable"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the create_configtree method with pytest.raises(Exception) as exc: client.create_configtree(configtree_body) @@ -115,7 +84,7 @@ def test_create_configtree_service_unavailable(client, mocker: MockerFixture): assert str(exc.value) == "service unavailable" -def test_get_configtree_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_configtree_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -127,17 +96,6 @@ def test_get_configtree_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the get_configtree method response = client.get_configtree(name="mock_configtree_name") @@ -147,7 +105,7 @@ def test_get_configtree_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.name == "test_configtree" -def test_set_configtree_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_set_configtree_revision_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -159,17 +117,6 @@ def test_set_configtree_revision_success(client, mocker: MockerFixture): # noqa }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the set_configtree_revision method response = client.set_configtree_revision( name="mock_configtree_name", configtree=configtree_body @@ -181,7 +128,7 @@ def test_set_configtree_revision_success(client, mocker: MockerFixture): # noqa assert response.metadata.name == "test_configtree" -def test_update_configtree_success(client, mocker: MockerFixture): # noqa: F811 +def test_update_configtree_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -193,21 +140,8 @@ def test_update_configtree_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the update_configtree method - response = client.update_configtree( - name="mock_configtree_name", body=configtree_body - ) + response = client.update_configtree(name="mock_configtree_name", body=configtree_body) # Validate the response assert isinstance(response, Munch) @@ -215,7 +149,7 @@ def test_update_configtree_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.name == "test_configtree" -def test_delete_configtree_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_configtree_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -225,17 +159,6 @@ def test_delete_configtree_success(client, mocker: MockerFixture): # noqa: F811 json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the delete_configtree method response = client.delete_configtree(name="mock_configtree_name") @@ -243,7 +166,7 @@ def test_delete_configtree_success(client, mocker: MockerFixture): # noqa: F811 assert response["success"] is True -def test_list_revisions_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_revisions_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -256,19 +179,8 @@ def test_list_revisions_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_revisions method - response = client.list_revisions(name="mock_configtree_name") + response = client.list_revisions(tree_name="mock_configtree_name") # Validate the response assert isinstance(response, Munch) @@ -277,7 +189,7 @@ def test_list_revisions_success(client, mocker: MockerFixture): # noqa: F811 ] -def test_create_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_revision_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -289,13 +201,6 @@ def test_create_revision_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - } - # Call the create_revision method response = client.create_revision(name="mock_configtree_name", body=configtree_body) @@ -304,7 +209,7 @@ def test_create_revision_success(client, mocker: MockerFixture): # noqa: F811 assert response["metadata"]["guid"] == "test_revision_guid" -def test_put_keys_in_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_put_keys_in_revision_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -316,22 +221,11 @@ def test_put_keys_in_revision_success(client, mocker: MockerFixture): # noqa: F }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the put_keys_in_revision method response = client.put_keys_in_revision( name="mock_configtree_name", revision_id="mock_revision_id", - configValues=["mock_value1", "mock_value2"], + config_values=["mock_value1", "mock_value2"], ) # Validate the response @@ -340,7 +234,7 @@ def test_put_keys_in_revision_success(client, mocker: MockerFixture): # noqa: F assert response.metadata.name == "test_revision" -def test_commit_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_commit_revision_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_patch = mocker.patch("httpx.Client.patch") @@ -352,22 +246,10 @@ def test_commit_revision_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the commit_revision method response = client.commit_revision( - name="mock_configtree_name", + tree_name="mock_configtree_name", revision_id="mock_revision_id", - configTreeRevision=configtree_body, ) # Validate the response @@ -376,7 +258,7 @@ def test_commit_revision_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.name == "test_revision" -def test_get_key_in_revision(client, mocker: MockerFixture): # noqa: F811 +def test_get_key_in_revision(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -388,20 +270,9 @@ def test_get_key_in_revision(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the get_key_in_revision method response = client.get_key_in_revision( - name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" ) # Validate the response @@ -410,7 +281,7 @@ def test_get_key_in_revision(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.name == "test_revision" -def test_put_key_in_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_put_key_in_revision_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -422,20 +293,9 @@ def test_put_key_in_revision_success(client, mocker: MockerFixture): # noqa: F8 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the put_key_in_revision method response = client.put_key_in_revision( - name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" ) # Validate the response @@ -444,7 +304,7 @@ def test_put_key_in_revision_success(client, mocker: MockerFixture): # noqa: F8 assert response.metadata.name == "test_revision" -def test_delete_key_in_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_key_in_revision_success(client, mocker: MockFixture): # noqa: F811 mock_delete = mocker.patch("httpx.Client.delete") mock_delete.return_value = httpx.Response( @@ -452,24 +312,14 @@ def test_delete_key_in_revision_success(client, mocker: MockerFixture): # noqa: json={"success": True}, ) - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - response = client.delete_key_in_revision( - name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key" ) assert response["success"] is True -def test_rename_key_in_revision_success(client, mocker: MockerFixture): # noqa: F811 +def test_rename_key_in_revision_success(client, mocker: MockFixture): # noqa: F811 mock_patch = mocker.patch("httpx.Client.patch") mock_patch.return_value = httpx.Response( @@ -479,21 +329,11 @@ def test_rename_key_in_revision_success(client, mocker: MockerFixture): # noqa: }, ) - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - response = client.rename_key_in_revision( - name="mock_configtree_name", + tree_name="mock_configtree_name", revision_id="mock_revision_id", key="mock_key", - configKeyRename={"metadata": {"name": "test_key"}}, + config_key_rename={"metadata": {"name": "test_key"}}, ) assert isinstance(response, Munch) diff --git a/tests/sync_tests/test_deployment.py b/tests/sync_tests/test_deployment.py new file mode 100644 index 0000000..3e30af4 --- /dev/null +++ b/tests/sync_tests/test_deployment.py @@ -0,0 +1,142 @@ +import httpx +import pytest +from munch import Munch +from pytest_mock import MockFixture + +from tests.data.mock_data import deployment_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 + + +def test_list_deployments_success(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-deployment", "guid": "mock_deployment_guid"}], + }, + ) + + # Call the list_deployments method + response = client.list_deployments() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [ + {"name": "test-deployment", "guid": "mock_deployment_guid"} + ] + + +def test_list_deployments_not_found(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + client.list_deployments() + + assert str(exc.value) == "not found" + + +def test_get_deployment_success(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + # Call the get_deployment method + response = client.get_deployment(name="mock_deployment_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +def test_get_deployment_not_found(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "deployment not found"}, + ) + + # Call the get_deployment method + with pytest.raises(Exception) as exc: + client.get_deployment(name="mock_deployment_name") + + assert str(exc.value) == "deployment not found" + + +def test_create_deployment_success(client, deployment_body, mocker: MockFixture): # noqa: F811 + mock_post = mocker.patch("httpx.Client.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + response = client.create_deployment(body=deployment_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +def test_create_deployment_unauthorized(client, deployment_body, mocker: MockFixture): # noqa: F811 + mock_post = mocker.patch("httpx.Client.post") + + mock_post.return_value = httpx.Response( + status_code=401, + json={"error": "unauthorized"}, + ) + + with pytest.raises(Exception) as exc: + client.create_deployment(body=deployment_body) + + assert str(exc.value) == "unauthorized" + + +def test_update_deployment_success(client, deployment_body, mocker: MockFixture): # noqa: F811 + mock_put = mocker.patch("httpx.Client.put") + + mock_put.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Deployment", + "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, + }, + ) + + response = client.update_deployment(name="mock_deployment_name", body=deployment_body) + + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_deployment_guid" + + +def test_delete_deployment_success(client, mocker: MockFixture): # noqa: F811 + mock_delete = mocker.patch("httpx.Client.delete") + + mock_delete.return_value = httpx.Response(status_code=204, json={"success": True}) + + response = client.delete_deployment(name="mock_deployment_name") + + assert response["success"] is True diff --git a/tests/sync_tests/test_disk.py b/tests/sync_tests/test_disk.py new file mode 100644 index 0000000..cb9e01e --- /dev/null +++ b/tests/sync_tests/test_disk.py @@ -0,0 +1,134 @@ +import httpx +import pytest +from munch import Munch +from pytest_mock import MockFixture + +from tests.data.mock_data import disk_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 + + +def test_list_disks_success(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up mock responses for pagination + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "metadata": {"continue": 1}, + "items": [{"name": "test-disk", "guid": "mock_disk_guid"}], + }, + ) + + # Call the list_disks method + response = client.list_disks() + + # Validate the response + assert isinstance(response, Munch) + assert response["items"] == [{"name": "test-disk", "guid": "mock_disk_guid"}] + + +def test_list_disks_not_found(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "not found"}, + ) + + with pytest.raises(Exception) as exc: + client.list_disks() + + assert str(exc.value) == "not found" + + +def test_get_disk_success(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Disk", + "metadata": {"guid": "test_disk_guid", "name": "mock_disk_name"}, + }, + ) + + # Call the get_disk method + response = client.get_disk(name="mock_disk_name") + + # Validate the response + assert isinstance(response, Munch) + assert response["metadata"]["guid"] == "test_disk_guid" + + +def test_get_disk_not_found(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.get method + mock_get = mocker.patch("httpx.Client.get") + + # Set up the mock response + mock_get.return_value = httpx.Response( + status_code=404, + json={"error": "disk not found"}, + ) + + # Call the get_disk method + with pytest.raises(Exception) as exc: + client.get_disk(name="mock_disk_name") + + assert str(exc.value) == "disk not found" + + +def test_create_disk_success(client, disk_body, mocker: MockFixture): # noqa: F811 + mock_post = mocker.patch("httpx.Client.post") + + mock_post.return_value = httpx.Response( + status_code=200, + json={ + "kind": "Disk", + "metadata": {"guid": "test_disk_guid", "name": "test_disk"}, + }, + ) + + response = client.create_disk(body=disk_body, project_guid="mock_project_guid") + + assert isinstance(response, Munch) + assert response.metadata.guid == "test_disk_guid" + assert response.metadata.name == "test_disk" + + +def test_delete_disk_success(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.delete method + mock_delete = mocker.patch("httpx.Client.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=204, + json={"success": True}, + ) + + # Call the delete_disk method + response = client.delete_disk(name="mock_disk_name") + + # Validate the response + assert response["success"] is True + + +def test_delete_disk_not_found(client, mocker: MockFixture): # noqa: F811 + # Mock the httpx.Client.delete method + mock_delete = mocker.patch("httpx.Client.delete") + + # Set up the mock response + mock_delete.return_value = httpx.Response( + status_code=404, + json={"error": "disk not found"}, + ) + + # Call the delete_disk method + with pytest.raises(Exception) as exc: + client.delete_disk(name="mock_disk_name") + + assert str(exc.value) == "disk not found" diff --git a/tests/test_main.py b/tests/sync_tests/test_main.py similarity index 82% rename from tests/test_main.py rename to tests/sync_tests/test_main.py index a8fa660..b906dae 100644 --- a/tests/test_main.py +++ b/tests/sync_tests/test_main.py @@ -1,11 +1,11 @@ import httpx import pytest -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_get_auth_token_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_auth_token_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -26,7 +26,7 @@ def test_get_auth_token_success(client, mocker: MockerFixture): # noqa: F811 assert response == "mock_token" -def test_login_success(client, mocker: MockerFixture): # noqa: F811 +def test_login_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -42,7 +42,7 @@ def test_login_success(client, mocker: MockerFixture): # noqa: F811 assert client.config.auth_token == "mock_token_2" -def test_login_failure(client, mocker: MockerFixture): # noqa: F811 +def test_login_failure(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") diff --git a/tests/test_managedservice.py b/tests/sync_tests/test_managedservice.py similarity index 52% rename from tests/test_managedservice.py rename to tests/sync_tests/test_managedservice.py index f6304fc..cdd08d3 100644 --- a/tests/test_managedservice.py +++ b/tests/sync_tests/test_managedservice.py @@ -1,12 +1,12 @@ import httpx import pytest # noqa: F401 from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_providers_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_providers_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,28 +19,15 @@ def test_list_providers_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_providers method response = client.list_providers() # Validate the response assert isinstance(response, Munch) - assert response["items"] == [ - {"name": "test-provider", "guid": "mock_provider_guid"} - ] + assert response["items"] == [{"name": "test-provider", "guid": "mock_provider_guid"}] -def test_list_instances_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_instances_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -53,28 +40,15 @@ def test_list_instances_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_instances method response = client.list_instances() # Validate the response assert isinstance(response, Munch) - assert response["items"] == [ - {"name": "test-instance", "guid": "mock_instance_guid"} - ] + assert response["items"] == [{"name": "test-instance", "guid": "mock_instance_guid"}] -def test_get_instance_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_instance_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -86,17 +60,6 @@ def test_get_instance_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the get_instance method response = client.get_instance(name="mock_instance_name") @@ -105,7 +68,7 @@ def test_get_instance_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.guid == "test_instance_guid" -def test_create_instance_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_instance_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -117,17 +80,6 @@ def test_create_instance_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the create_instance method response = client.create_instance(body={"name": "test_instance"}) @@ -136,7 +88,7 @@ def test_create_instance_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.guid == "test_instance_guid" -def test_delete_instance_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_instance_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -146,17 +98,6 @@ def test_delete_instance_success(client, mocker: MockerFixture): # noqa: F811 json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the delete_instance method response = client.delete_instance(name="mock_instance_name") @@ -164,7 +105,7 @@ def test_delete_instance_success(client, mocker: MockerFixture): # noqa: F811 assert response["success"] is True -def test_list_instance_bindings_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_instance_bindings_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -179,17 +120,6 @@ def test_list_instance_bindings_success(client, mocker: MockerFixture): # noqa: }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_instance_bindings method response = client.list_instance_bindings("mock_instance_name") @@ -200,7 +130,7 @@ def test_list_instance_bindings_success(client, mocker: MockerFixture): # noqa: ] -def test_get_instance_binding_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_instance_binding_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -215,17 +145,6 @@ def test_get_instance_binding_success(client, mocker: MockerFixture): # noqa: F }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the get_instance_binding method response = client.get_instance_binding( name="mock_instance_binding_name", instance_name="mock_instance_name" @@ -236,7 +155,7 @@ def test_get_instance_binding_success(client, mocker: MockerFixture): # noqa: F assert response.metadata.guid == "test_instance_binding_guid" -def test_create_instance_binding_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_instance_binding_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -251,17 +170,6 @@ def test_create_instance_binding_success(client, mocker: MockerFixture): # noqa }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the create_instance_binding method response = client.create_instance_binding( body={"name": "test_instance_binding"}, instance_name="mock_instance_name" @@ -272,7 +180,7 @@ def test_create_instance_binding_success(client, mocker: MockerFixture): # noqa assert response.metadata.guid == "test_instance_binding_guid" -def test_delete_instance_binding_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_instance_binding_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -282,17 +190,6 @@ def test_delete_instance_binding_success(client, mocker: MockerFixture): # noqa json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the delete_instance_binding method response = client.delete_instance_binding( name="mock_instance_binding_name", instance_name="mock_instance_name" diff --git a/tests/test_network.py b/tests/sync_tests/test_network.py similarity index 50% rename from tests/test_network.py rename to tests/sync_tests/test_network.py index 11a6cf6..6fe9826 100644 --- a/tests/test_network.py +++ b/tests/sync_tests/test_network.py @@ -1,12 +1,13 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client, network_body # noqa: F401 +from tests.data.mock_data import network_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_networks_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_networks_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,17 +20,6 @@ def test_list_networks_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_networks method response = client.list_networks() @@ -38,7 +28,7 @@ def test_list_networks_success(client, mocker: MockerFixture): # noqa: F811 assert response["items"] == [{"name": "test-network", "guid": "mock_network_guid"}] -def test_list_networks_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_list_networks_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -48,20 +38,13 @@ def test_list_networks_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.list_networks() assert str(exc.value) == "not found" -def test_create_network_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_network_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -73,17 +56,6 @@ def test_create_network_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the create_network method response = client.create_network(body=network_body) @@ -92,7 +64,7 @@ def test_create_network_success(client, mocker: MockerFixture): # noqa: F811 assert response["metadata"]["name"] == "test-network" -def test_create_network_failure(client, mocker: MockerFixture): # noqa: F811 +def test_create_network_failure(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -102,20 +74,13 @@ def test_create_network_failure(client, mocker: MockerFixture): # noqa: F811 json={"error": "already exists"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.create_network(body=network_body) assert str(exc.value) == "already exists" -def test_get_network_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_network_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -127,17 +92,6 @@ def test_get_network_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the get_network method response = client.get_network(name="test-network") @@ -146,7 +100,7 @@ def test_get_network_success(client, mocker: MockerFixture): # noqa: F811 assert response["metadata"]["guid"] == "mock_network_guid" -def test_delete_network_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_network_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -156,17 +110,6 @@ def test_delete_network_success(client, mocker: MockerFixture): # noqa: F811 json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the delete_network method response = client.delete_network(name="test-network") diff --git a/tests/test_package.py b/tests/sync_tests/test_package.py similarity index 54% rename from tests/test_package.py rename to tests/sync_tests/test_package.py index 3f7d6d8..c8c8991 100644 --- a/tests/test_package.py +++ b/tests/sync_tests/test_package.py @@ -1,12 +1,13 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client, package_body # noqa: F401 +from tests.data.mock_data import package_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_packages_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_packages_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,17 +20,6 @@ def test_list_packages_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_packages method response = client.list_packages() @@ -38,7 +28,7 @@ def test_list_packages_success(client, mocker: MockerFixture): # noqa: F811 assert response["items"] == [{"name": "test_package", "guid": "mock_package_guid"}] -def test_list_packages_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_list_packages_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -48,13 +38,6 @@ def test_list_packages_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the list_packages method with pytest.raises(Exception) as exc: client.list_packages() @@ -64,7 +47,7 @@ def test_list_packages_not_found(client, mocker: MockerFixture): # noqa: F811 # assert response. == "not found" -def test_get_package_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_package_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -76,17 +59,6 @@ def test_get_package_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the get_package method response = client.get_package(name="mock_package_name") @@ -96,7 +68,7 @@ def test_get_package_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.name == "test_package" -def test_get_package_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_get_package_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -106,13 +78,6 @@ def test_get_package_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("package_guid") if with_project else None, - } - # Call the get_package method with pytest.raises(Exception) as exc: client.get_package(name="mock_package_name") @@ -121,7 +86,7 @@ def test_get_package_not_found(client, mocker: MockerFixture): # noqa: F811 assert str(exc.value) == "not found" -def test_create_package_success(client, package_body, mocker: MockerFixture): # noqa: F811 +def test_create_package_success(client, package_body, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -133,17 +98,6 @@ def test_create_package_success(client, package_body, mocker: MockerFixture): # }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the create_package method response = client.create_package(body=package_body) diff --git a/tests/test_project.py b/tests/sync_tests/test_project.py similarity index 50% rename from tests/test_project.py rename to tests/sync_tests/test_project.py index 8259f2e..b398052 100644 --- a/tests/test_project.py +++ b/tests/sync_tests/test_project.py @@ -1,17 +1,17 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import ( - client, # noqa: F401 +from tests.data.mock_data import ( mock_response_project, # noqa: F401 project_body, ) # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 # Test function for list_projects -def test_list_projects_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_projects_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -24,17 +24,6 @@ def test_list_projects_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return mocked headers without None values - client.config.get_headers = lambda with_project: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_projects method response = client.list_projects() @@ -43,7 +32,7 @@ def test_list_projects_success(client, mocker: MockerFixture): # noqa: F811 assert response["items"] == [{"name": "test-project", "guid": "mock_project_guid"}] -def test_list_projects_unauthorized(client, mocker: MockerFixture): # noqa: F811 +def test_list_projects_unauthorized(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -53,17 +42,6 @@ def test_list_projects_unauthorized(client, mocker: MockerFixture): # noqa: F81 json={"error": "unauthorized permission access"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_projects method with pytest.raises(Exception) as exc: client.list_projects() @@ -72,7 +50,7 @@ def test_list_projects_unauthorized(client, mocker: MockerFixture): # noqa: F81 assert str(exc.value) == "unauthorized permission access" -def test_list_projects_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_list_projects_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -82,17 +60,6 @@ def test_list_projects_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_projects method with pytest.raises(Exception) as exc: client.list_projects() @@ -101,7 +68,7 @@ def test_list_projects_not_found(client, mocker: MockerFixture): # noqa: F811 assert str(exc.value) == "not found" -def test_get_project_success(client, mock_response_project, mocker: MockerFixture): # noqa: F811 +def test_get_project_success(client, mock_response_project, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -114,17 +81,6 @@ def test_get_project_success(client, mock_response_project, mocker: MockerFixtur }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the get_project method response = client.get_project(project_guid="mock_project_guid") @@ -133,7 +89,7 @@ def test_get_project_success(client, mock_response_project, mocker: MockerFixtur assert response["metadata"]["guid"] == "test_project_guid" -def test_get_project_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_get_project_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -143,17 +99,6 @@ def test_get_project_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "project not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the get_project method with pytest.raises(Exception) as exc: client.get_project(project_guid="mock_project_guid") @@ -162,7 +107,7 @@ def test_get_project_not_found(client, mocker: MockerFixture): # noqa: F811 assert str(exc.value) == "project not found" -def test_create_project_success(client, mock_response_project, mocker: MockerFixture): # noqa: F811 +def test_create_project_success(client, mock_response_project, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -172,17 +117,6 @@ def test_create_project_success(client, mock_response_project, mocker: MockerFix json=mock_response_project, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the create_project method response = client.create_project(body=project_body) @@ -191,7 +125,7 @@ def test_create_project_success(client, mock_response_project, mocker: MockerFix assert response["metadata"]["guid"] == "mock_project_guid" -def test_create_project_unauthorized(client, mocker: MockerFixture): # noqa: F811 +def test_create_project_unauthorized(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -201,17 +135,6 @@ def test_create_project_unauthorized(client, mocker: MockerFixture): # noqa: F8 json={"error": "unauthorized permission access"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the create_project method with pytest.raises(Exception) as exc: client.create_project(body=project_body) @@ -220,7 +143,7 @@ def test_create_project_unauthorized(client, mocker: MockerFixture): # noqa: F8 assert str(exc.value) == "unauthorized permission access" -def test_update_project_success(client, mock_response_project, mocker: MockerFixture): # noqa: F811 +def test_update_project_success(client, mock_response_project, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -230,45 +153,21 @@ def test_update_project_success(client, mock_response_project, mocker: MockerFix json=mock_response_project, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the update_project method - response = client.update_project( - project_guid="mock_project_guid", body=project_body - ) + response = client.update_project(project_guid="mock_project_guid", body=project_body) # Validate the response assert isinstance(response, Munch) assert response["metadata"]["guid"] == "mock_project_guid" -def test_delete_project_success(client, mock_response_project, mocker: MockerFixture): # noqa: F811 +def test_delete_project_success(client, mock_response_project, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") # Set up the mock response mock_delete.return_value = httpx.Response(status_code=200, json={"success": True}) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - # Call the delete_project method response = client.delete_project(project_guid="mock_project_guid") diff --git a/tests/test_secret.py b/tests/sync_tests/test_secret.py similarity index 53% rename from tests/test_secret.py rename to tests/sync_tests/test_secret.py index 48a8054..5d1e6ad 100644 --- a/tests/test_secret.py +++ b/tests/sync_tests/test_secret.py @@ -1,12 +1,13 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client, secret_body # noqa: F401 +from tests.data.mock_data import secret_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_secrets_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_secrets_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,17 +20,6 @@ def test_list_secrets_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_secrets method response = client.list_secrets() @@ -38,7 +28,7 @@ def test_list_secrets_success(client, mocker: MockerFixture): # noqa: F811 assert response["items"] == [{"name": "test-secret", "guid": "mock_secret_guid"}] -def test_list_secrets_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_list_secrets_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -48,20 +38,13 @@ def test_list_secrets_not_found(client, mocker: MockerFixture): # noqa: F811 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.list_secrets() assert str(exc.value) == "not found" -def test_create_secret_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_secret_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -73,13 +56,6 @@ def test_create_secret_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the create_secret method response = client.create_secret(secret_body) @@ -88,7 +64,7 @@ def test_create_secret_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.guid == "test_secret_guid" -def test_create_secret_already_exists(client, mocker: MockerFixture): # noqa: F811 +def test_create_secret_already_exists(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -98,20 +74,13 @@ def test_create_secret_already_exists(client, mocker: MockerFixture): # noqa: F json={"error": "secret already exists"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.create_secret(secret_body) assert str(exc.value) == "secret already exists" -def test_update_secret_success(client, mocker: MockerFixture): # noqa: F811 +def test_update_secret_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -123,13 +92,6 @@ def test_update_secret_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the update_secret method response = client.update_secret("mock_secret_guid", body=secret_body) @@ -138,7 +100,7 @@ def test_update_secret_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.guid == "test_secret_guid" -def test_delete_secret_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_secret_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -148,13 +110,6 @@ def test_delete_secret_success(client, mocker: MockerFixture): # noqa: F811 json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the delete_secret method response = client.delete_secret("mock_secret_guid") @@ -162,7 +117,7 @@ def test_delete_secret_success(client, mocker: MockerFixture): # noqa: F811 assert response == {"success": True} -def test_get_secret_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_secret_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -174,13 +129,6 @@ def test_get_secret_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - # Call the get_secret method response = client.get_secret("mock_secret_guid") diff --git a/tests/test_staticroute.py b/tests/sync_tests/test_staticroute.py similarity index 51% rename from tests/test_staticroute.py rename to tests/sync_tests/test_staticroute.py index 8436a38..24bb1eb 100644 --- a/tests/test_staticroute.py +++ b/tests/sync_tests/test_staticroute.py @@ -1,12 +1,13 @@ import httpx import pytest from munch import Munch -from pytest_mock import MockerFixture +from pytest_mock import MockFixture -from tests.utils.test_util import client, staticroute_body # noqa: F401 +from tests.data.mock_data import staticroute_body # noqa: F401 +from tests.utils.fixtures import client # noqa: F401 -def test_list_staticroutes_success(client, mocker: MockerFixture): # noqa: F811 +def test_list_staticroutes_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -19,17 +20,6 @@ def test_list_staticroutes_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the list_staticroutes method response = client.list_staticroutes() @@ -40,7 +30,7 @@ def test_list_staticroutes_success(client, mocker: MockerFixture): # noqa: F811 ] -def test_list_staticroutes_not_found(client, mocker: MockerFixture): # noqa: F811 +def test_list_staticroutes_not_found(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -50,20 +40,13 @@ def test_list_staticroutes_not_found(client, mocker: MockerFixture): # noqa: F8 json={"error": "not found"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.list_staticroutes() assert str(exc.value) == "not found" -def test_create_staticroute_success(client, mocker: MockerFixture): # noqa: F811 +def test_create_staticroute_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -75,17 +58,6 @@ def test_create_staticroute_success(client, mocker: MockerFixture): # noqa: F81 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the create_staticroute method response = client.create_staticroute(body=staticroute_body) @@ -94,7 +66,7 @@ def test_create_staticroute_success(client, mocker: MockerFixture): # noqa: F81 assert response.metadata.guid == "test_staticroute_guid" -def test_create_staticroute_bad_request(client, mocker: MockerFixture): # noqa: F811 +def test_create_staticroute_bad_request(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.post method mock_post = mocker.patch("httpx.Client.post") @@ -104,20 +76,13 @@ def test_create_staticroute_bad_request(client, mocker: MockerFixture): # noqa: json={"error": "already exists"}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - with pytest.raises(Exception) as exc: client.create_staticroute(body=staticroute_body) assert str(exc.value) == "already exists" -def test_get_staticroute_success(client, mocker: MockerFixture): # noqa: F811 +def test_get_staticroute_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.get method mock_get = mocker.patch("httpx.Client.get") @@ -129,17 +94,6 @@ def test_get_staticroute_success(client, mocker: MockerFixture): # noqa: F811 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the get_staticroute method response = client.get_staticroute(name="mock_staticroute_name") @@ -148,7 +102,7 @@ def test_get_staticroute_success(client, mocker: MockerFixture): # noqa: F811 assert response.metadata.guid == "test_staticroute_guid" -def test_update_staticroute_success(client, mocker: MockerFixture): # noqa: F811 +def test_update_staticroute_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.put method mock_put = mocker.patch("httpx.Client.put") @@ -160,17 +114,6 @@ def test_update_staticroute_success(client, mocker: MockerFixture): # noqa: F81 }, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - # Call the update_staticroute method response = client.update_staticroute( name="mock_staticroute_name", body=staticroute_body @@ -181,7 +124,7 @@ def test_update_staticroute_success(client, mocker: MockerFixture): # noqa: F81 assert response.metadata.guid == "test_staticroute_guid" -def test_delete_staticroute_success(client, mocker: MockerFixture): # noqa: F811 +def test_delete_staticroute_success(client, mocker: MockFixture): # noqa: F811 # Mock the httpx.Client.delete method mock_delete = mocker.patch("httpx.Client.delete") @@ -191,17 +134,6 @@ def test_delete_staticroute_success(client, mocker: MockerFixture): # noqa: F81 json={"success": True}, ) - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": None, - }.items() - if v is not None - } - # Call the delete_staticroute method response = client.delete_staticroute(name="mock_staticroute_name") diff --git a/tests/test_deployment.py b/tests/test_deployment.py deleted file mode 100644 index 19ea9fe..0000000 --- a/tests/test_deployment.py +++ /dev/null @@ -1,223 +0,0 @@ -import httpx -import pytest -from munch import Munch -from pytest_mock import MockerFixture - -from tests.utils.test_util import client, deployment_body # noqa: F401 - - -def test_list_deployments_success(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock responses for pagination - mock_get.return_value = httpx.Response( - status_code=200, - json={ - "metadata": {"continue": 1}, - "items": [{"name": "test-deployment", "guid": "mock_deployment_guid"}], - }, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - - # Call the list_deployments method - response = client.list_deployments() - - # Validate the response - assert isinstance(response, Munch) - assert response["items"] == [ - {"name": "test-deployment", "guid": "mock_deployment_guid"} - ] - - -def test_list_deployments_not_found(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=404, - json={"error": "not found"}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - - with pytest.raises(Exception) as exc: - client.list_deployments() - - assert str(exc.value) == "not found" - - -def test_get_deployment_success(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=200, - json={ - "kind": "Deployment", - "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, - }, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the get_deployment method - response = client.get_deployment(name="mock_deployment_name") - - # Validate the response - assert isinstance(response, Munch) - assert response["metadata"]["guid"] == "test_deployment_guid" - - -def test_get_deployment_not_found(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=404, - json={"error": "deployment not found"}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the get_deployment method - with pytest.raises(Exception) as exc: - client.get_deployment(name="mock_deployment_name") - - assert str(exc.value) == "deployment not found" - - -def test_create_deployment_success(client, deployment_body, mocker: MockerFixture): # noqa: F811 - mock_post = mocker.patch("httpx.Client.post") - - mock_post.return_value = httpx.Response( - status_code=200, - json={ - "kind": "Deployment", - "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, - }, - ) - - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - response = client.create_deployment(body=deployment_body) - - assert isinstance(response, Munch) - assert response["metadata"]["guid"] == "test_deployment_guid" - - -def test_create_deployment_unauthorized(client, deployment_body, mocker: MockerFixture): # noqa: F811 - mock_post = mocker.patch("httpx.Client.post") - - mock_post.return_value = httpx.Response( - status_code=401, - json={"error": "unauthorized"}, - ) - - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - with pytest.raises(Exception) as exc: - client.create_deployment(body=deployment_body) - - assert str(exc.value) == "unauthorized" - - -def test_update_deployment_success(client, deployment_body, mocker: MockerFixture): # noqa: F811 - mock_put = mocker.patch("httpx.Client.put") - - mock_put.return_value = httpx.Response( - status_code=200, - json={ - "kind": "Deployment", - "metadata": {"guid": "test_deployment_guid", "name": "test_deployment"}, - }, - ) - - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - response = client.update_deployment( - name="mock_deployment_name", body=deployment_body - ) - - assert isinstance(response, Munch) - assert response["metadata"]["guid"] == "test_deployment_guid" - - -def test_delete_deployment_success(client, mocker: MockerFixture): # noqa: F811 - mock_delete = mocker.patch("httpx.Client.delete") - - mock_delete.return_value = httpx.Response(status_code=204, json={"success": True}) - - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - response = client.delete_deployment(name="mock_deployment_name") - - assert response["success"] is True diff --git a/tests/test_disk.py b/tests/test_disk.py deleted file mode 100644 index 6d194b9..0000000 --- a/tests/test_disk.py +++ /dev/null @@ -1,205 +0,0 @@ -import httpx -import pytest -from munch import Munch -from pytest_mock import MockerFixture - -from tests.utils.test_util import client, disk_body # noqa: F401 - - -def test_list_disks_success(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up mock responses for pagination - mock_get.return_value = httpx.Response( - status_code=200, - json={ - "metadata": {"continue": 1}, - "items": [{"name": "test-disk", "guid": "mock_disk_guid"}], - }, - ) - - # Override get_headers to return mocked headers without None values - client.config.get_headers = lambda with_project=True: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - }.items() - if v is not None - } - - # Call the list_disks method - response = client.list_disks() - - # Validate the response - assert isinstance(response, Munch) - assert response["items"] == [{"name": "test-disk", "guid": "mock_disk_guid"}] - - -def test_list_disks_not_found(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=404, - json={"error": "not found"}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=True: { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": "mock_project_guid" if with_project else None, - } - - with pytest.raises(Exception) as exc: - client.list_disks() - - assert str(exc.value) == "not found" - - -def test_get_disk_success(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=200, - json={ - "kind": "Disk", - "metadata": {"guid": "test_disk_guid", "name": "mock_disk_name"}, - }, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the get_disk method - response = client.get_disk(name="mock_disk_name") - - # Validate the response - assert isinstance(response, Munch) - assert response["metadata"]["guid"] == "test_disk_guid" - - -def test_get_disk_not_found(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.get method - mock_get = mocker.patch("httpx.Client.get") - - # Set up the mock response - mock_get.return_value = httpx.Response( - status_code=404, - json={"error": "disk not found"}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the get_disk method - with pytest.raises(Exception) as exc: - client.get_disk(name="mock_disk_name") - - assert str(exc.value) == "disk not found" - - -def test_create_disk_success(client, disk_body, mocker: MockerFixture): # noqa: F811 - mock_post = mocker.patch("httpx.Client.post") - - mock_post.return_value = httpx.Response( - status_code=200, - json={ - "kind": "Disk", - "metadata": {"guid": "test_disk_guid", "name": "test_disk"}, - }, - ) - - client.config.get_headers = lambda with_project=True, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - response = client.create_disk(body=disk_body, project_guid="mock_project_guid") - - assert isinstance(response, Munch) - assert response.metadata.guid == "test_disk_guid" - assert response.metadata.name == "test_disk" - - -def test_delete_disk_success(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.delete method - mock_delete = mocker.patch("httpx.Client.delete") - - # Set up the mock response - mock_delete.return_value = httpx.Response( - status_code=204, - json={"success": True}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the delete_disk method - response = client.delete_disk(name="mock_disk_name") - - # Validate the response - assert response["success"] is True - - -def test_delete_disk_not_found(client, mocker: MockerFixture): # noqa: F811 - # Mock the httpx.Client.delete method - mock_delete = mocker.patch("httpx.Client.delete") - - # Set up the mock response - mock_delete.return_value = httpx.Response( - status_code=404, - json={"error": "disk not found"}, - ) - - # Override get_headers to return the mocked headers without None values - client.config.get_headers = lambda with_project=False, **kwargs: { - k: v - for k, v in { - "Authorization": f"Bearer {client.auth_token}", - "organizationguid": client.organization_guid, - "project": kwargs.get("project_guid") if with_project else None, - }.items() - if v is not None - } - - # Call the delete_disk method - with pytest.raises(Exception) as exc: - client.delete_disk(name="mock_disk_name") - - assert str(exc.value) == "disk not found" diff --git a/tests/utils/fixtures.py b/tests/utils/fixtures.py new file mode 100644 index 0000000..2ec867b --- /dev/null +++ b/tests/utils/fixtures.py @@ -0,0 +1,25 @@ +import pytest +from rapyuta_io_sdk_v2 import Client, AsyncClient + + +# Fixture to initialize the Client +@pytest.fixture +def client(): + client = Client() + client.config.hosts["v2api_host"] = "https://mock-api.rapyuta.io" + client.config.auth_token = "mock_token" + client.config.organization_guid = "mock_org_guid" + client.config.project_guid = "mock_project_guid" + client.config.environment = "mock" + return client + + +@pytest.fixture +def async_client(): + client = AsyncClient() + client.config.hosts["v2api_host"] = "https://mock-api.rapyuta.io" + client.config.auth_token = "mock_token" + client.config.organization_guid = "mock_org_guid" + client.config.project_guid = "mock_project_guid" + client.config.environment = "mock" + return client diff --git a/uv.lock b/uv.lock index ef9d636..6071ac1 100644 --- a/uv.lock +++ b/uv.lock @@ -17,16 +17,15 @@ wheels = [ ] [[package]] -name = "asyncer" -version = "0.0.8" +name = "asyncmock" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, + { name = "mock" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ff/67/7ea59c3e69eaeee42e7fc91a5be67ca5849c8979acac2b920249760c6af2/asyncer-0.0.8.tar.gz", hash = "sha256:a589d980f57e20efb07ed91d0dbe67f1d2fd343e7142c66d3a099f05c620739c", size = 18217 } +sdist = { url = "https://files.pythonhosted.org/packages/c8/58/fa6b3147951a8d82cc78e628dffee0aa5838328c52ebfee4e0ddceb5d92b/asyncmock-0.4.2.tar.gz", hash = "sha256:c251889d542e98fe5f7ece2b5b8643b7d62b50a5657d34a4cbce8a1d5170d750", size = 3191 } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/04/15b6ca6b7842eda2748bda0a0af73f2d054e9344320f8bba01f994294bcb/asyncer-0.0.8-py3-none-any.whl", hash = "sha256:5920d48fc99c8f8f0f1576e1882f5022885589c5fcbc46ce4224ec3e53776eeb", size = 9209 }, + { url = "https://files.pythonhosted.org/packages/03/e3/873f433eca053c92d3cdb9336a379ee025bc1a86d4624ef87bf97a9ac7bc/asyncmock-0.4.2-py3-none-any.whl", hash = "sha256:fd8bc4e7813251a8959d1140924ccba3adbbc7af885dba7047c67f73c0b664b1", size = 4190 }, ] [[package]] @@ -249,6 +248,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 }, ] +[[package]] +name = "pytest-asyncio" +version = "0.24.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/6d/c6cf50ce320cf8611df7a1254d86233b3df7cc07f9b5f5cbcb82e08aa534/pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276", size = 49855 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", size = 18024 }, +] + [[package]] name = "pytest-cov" version = "5.0.0" @@ -285,11 +296,11 @@ dependencies = [ [package.dev-dependencies] dev = [ - { name = "anyio" }, - { name = "asyncer" }, + { name = "asyncmock" }, { name = "coverage" }, { name = "mock" }, { name = "pytest" }, + { name = "pytest-asyncio" }, { name = "pytest-cov" }, { name = "pytest-mock" }, { name = "typing-extensions" }, @@ -303,11 +314,11 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "anyio", specifier = ">=4.5.2" }, - { name = "asyncer", specifier = ">=0.0.8" }, + { name = "asyncmock", specifier = ">=0.4.2" }, { name = "coverage", specifier = ">=7.6.1" }, { name = "mock", specifier = ">=5.1.0" }, { name = "pytest", specifier = ">=8.3.3" }, + { name = "pytest-asyncio", specifier = ">=0.24.0" }, { name = "pytest-cov", specifier = ">=5.0.0" }, { name = "pytest-mock", specifier = ">=3.14.0" }, { name = "typing-extensions", specifier = ">=4.12.2" },