Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sites with model, test, doco, and additions to classic_api.py #25

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/reference/models_classic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ Packages
ClassicPackage
ClassicPackageItem

Sites
-----

.. currentmodule:: jamf_pro_sdk.models.classic.sites

.. autosummary::
:toctree: _autosummary

ClassicSite
ClassicSiteItem

Group and Search Criteria
-------------------------

Expand Down
93 changes: 93 additions & 0 deletions src/jamf_pro_sdk/clients/classic_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
ClassicComputersItem,
)
from ..models.classic.packages import ClassicPackage, ClassicPackageItem
from ..models.classic.sites import ClassicSite, ClassicSiteItem

if TYPE_CHECKING:
import requests
Expand All @@ -45,6 +46,7 @@
int, ClassicAdvancedComputerSearch, ClassicAdvancedComputerSearchesItem
]
PackageId = Union[int, ClassicPackage, ClassicPackageItem]
SiteId = Union[int, ClassicSite, ClassicSiteItem]


def parse_response_id(xml: str) -> int:
Expand Down Expand Up @@ -554,3 +556,94 @@ def delete_package_by_id(self, package: PackageId) -> None:
"""
package_id = ClassicApi._parse_id(package)
self.api_request(method="delete", resource_path=f"packages/id/{package_id}")


# /sites APIs


def create_site(self, data: Union[str, ClassicSite]) -> int:
"""Create a new site.

Only the ``name`` is required.

:param data: Can be an XML string or a
:class:`~jamf_pro_sdk.models.classic.sites.ClassicSite` object.
:type data: Union[str, ClassicSite]

:return: ID of the new site.
:rtype: int

"""
resp = self.api_request(method="post", resource_path="sites/id/0", data=data)
return parse_response_id(resp.text)


def list_all_sites(self) -> List[ClassicSiteItem]:
"""Returns a list of all sites.

:return: List of sites.
:rtype: List[~jamf_pro_sdk.models.classic.sites.ClassicSiteItem]

"""
resp = self.api_request(method="get", resource_path="sites")
return [ClassicSiteItem(**i) for i in resp.json()["sites"]]


def get_site_by_id(self, site: SiteId) -> ClassicSite:
"""Returns a single site record using the ID.

:param site: A site ID or supported Classic API model.
:type site: Union[int, ClassicSite, ClassicSiteItem]

:return: Site.
:rtype: ~jamf_pro_sdk.models.classic.sites.ClassicSite

"""
site_id = ClassicApi._parse_id(site)
resp = self.api_request(method="get", resource_path=f"sites/id/{site_id}")
return ClassicSite(**resp.json()["site"])


def update_site_by_id(
self, site: SiteId, data: Union[str, ClassicSite], return_updated: bool = False
):
"""Update a site using the ID.

:param site: A site ID or supported Classic API model.
:type site: Union[int, ClassicSite, ClassicSiteItem]

:param data: Can be an XML string or a
:class:`~jamf_pro_sdk.models.classic.sites.ClassicSite` object.
:type data: Union[str, ClassicSite]

"""
site_id = ClassicApi._parse_id(site)
self.api_request(method="put", resource_path=f"sites/id/{site_id}", data=data)
if return_updated:
return self.get_site_by_id(site_id)


def delete_site_by_id(self, site: SiteId) -> None:
"""Delete a site using the ID.

:param site: A site ID or supported Classic API model.
:type site: Union[int, ClassicSite, ClassicSiteItem]

"""
site_id = ClassicApi._parse_id(site)
self.api_request(method="delete", resource_path=f"sites/id/{site_id}")


def create_site(self, data: Union[str, ClassicSite]) -> int:
"""Create a new site.

:param data: Can be an XML string or a
:class:`~jamf_pro_sdk.models.classic.sites.ClassicSite` object.
:type data: Union[str, ClassicSite]

:return: ID of the new site.
:rtype: int

"""
resp = self.api_request(method="post", resource_path="sites/id/0", data=data)
return parse_response_id(resp.text)
31 changes: 31 additions & 0 deletions src/jamf_pro_sdk/models/classic/sites.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Optional

from pydantic import Extra

from .. import BaseModel
from . import ClassicApiModel

_XML_ARRAY_ITEM_NAMES = {}


class ClassicSiteItem(BaseModel, extra=Extra.allow):
"""Represents a site record returned by the
:meth:`~jamf_pro_sdk.clients.classic_api.ClassicApi.list_sites` operation.
"""

id: Optional[int]
name: Optional[str]


class ClassicSite(ClassicApiModel):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class already exists at jamf_pro_sdk.models.classic.__init__.ClassicSite. The site object is used across numerous models in the API (same for Pro). This duplicate model name will cause errors during doc builds. Refactor your PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I will have a look.

"""Represents a site record returned by the
:meth:`~jamf_pro_sdk.clients.classic_api.ClassicApi.get_site_by_id` operation.
Note that due to the simplicity of the model this information is available in the list.
"""

_xml_root_name = "site"
_xml_array_item_names = _XML_ARRAY_ITEM_NAMES
_xml_write_fields = {"name"}

id: Optional[int]
name: Optional[str]
24 changes: 24 additions & 0 deletions tests/models/test_models_classic_sites.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import json

from deepdiff import DeepDiff
from src.jamf_pro_sdk.models.classic.sites import ClassicSite

SITE_JSON = {"site": {"id": 1, "name": "Test Site"}}


def test_site_model_parsings():
"""Verify select attributes across the Site model."""
site = ClassicSite(**SITE_JSON["site"])

assert site is not None # mypy
assert site.name == "Test Site"
assert site.id == 1


def test_site_model_json_output_matches_input():
site = ClassicSite(**SITE_JSON["site"])
serialized_output = json.loads(site.json(exclude_none=True))

diff = DeepDiff(SITE_JSON["site"], serialized_output, ignore_order=True)

assert not diff