diff --git a/docs/reference/models_classic.rst b/docs/reference/models_classic.rst index 166f93f..d17334d 100644 --- a/docs/reference/models_classic.rst +++ b/docs/reference/models_classic.rst @@ -113,6 +113,17 @@ Packages ClassicPackage ClassicPackageItem +Sites +----- + +.. currentmodule:: jamf_pro_sdk.models.classic.sites + +.. autosummary:: + :toctree: _autosummary + + ClassicSite + ClassicSiteItem + Group and Search Criteria ------------------------- diff --git a/src/jamf_pro_sdk/clients/classic_api.py b/src/jamf_pro_sdk/clients/classic_api.py index 02af4c8..7d29d19 100644 --- a/src/jamf_pro_sdk/clients/classic_api.py +++ b/src/jamf_pro_sdk/clients/classic_api.py @@ -10,18 +10,24 @@ ClassicAdvancedComputerSearch, ClassicAdvancedComputerSearchesItem, ) + from ..models.classic.categories import ClassicCategoriesItem, ClassicCategory + from ..models.classic.computer_groups import ( ClassicComputerGroup, ClassicComputerGroupMember, ClassicComputerGroupMembershipUpdate, ) + from ..models.classic.computers import ( ClassicComputer, ClassicComputersItem, ) + from ..models.classic.packages import ClassicPackage, ClassicPackageItem +from ..models.classic.sites import ClassicSite, ClassicSitesItem + if TYPE_CHECKING: import requests @@ -45,6 +51,7 @@ int, ClassicAdvancedComputerSearch, ClassicAdvancedComputerSearchesItem ] PackageId = Union[int, ClassicPackage, ClassicPackageItem] +SiteId = Union[int, ClassicSite, ClassicSitesItem] def parse_response_id(xml: str) -> int: @@ -554,3 +561,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[ClassicSitesItem]: + """Returns a list of all sites. + + :return: List of sites. + :rtype: List[~jamf_pro_sdk.models.classic.sites.ClassicSitesItem] + + """ + resp = self.api_request(method="get", resource_path="sites") + return [ClassicSitesItem(**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, ClassicSitesItem] + + :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, ClassicSitesItem] + + :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, ClassicSitesItem] + + """ + 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) diff --git a/src/jamf_pro_sdk/models/classic/sites.py b/src/jamf_pro_sdk/models/classic/sites.py new file mode 100644 index 0000000..f89ab66 --- /dev/null +++ b/src/jamf_pro_sdk/models/classic/sites.py @@ -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): + """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] diff --git a/tests/models/test_models_classic_sites.py b/tests/models/test_models_classic_sites.py new file mode 100644 index 0000000..a6e22ce --- /dev/null +++ b/tests/models/test_models_classic_sites.py @@ -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