diff --git a/docs/reference/models_pro.rst b/docs/reference/models_pro.rst index 0763c09..70b4595 100644 --- a/docs/reference/models_pro.rst +++ b/docs/reference/models_pro.rst @@ -88,6 +88,7 @@ MDM Commands ShutDownDeviceCommand SendMdmCommandResponse RenewMdmProfileResponse + RedeployManagementFrameworkResponse MdmCommandStatus MdmCommandStatusClient MdmCommandStatusClientTypes diff --git a/src/jamf_pro_sdk/clients/pro_api/__init__.py b/src/jamf_pro_sdk/clients/pro_api/__init__.py index d3083f3..a9d5afa 100644 --- a/src/jamf_pro_sdk/clients/pro_api/__init__.py +++ b/src/jamf_pro_sdk/clients/pro_api/__init__.py @@ -29,6 +29,7 @@ MdmCommandClientRequest, MdmCommandRequest, MdmCommandStatus, + RedeployManagementFrameworkResponse, RenewMdmProfileResponse, SendMdmCommand, SendMdmCommandClientData, @@ -608,6 +609,28 @@ def renew_mdm_profile_v1(self, udids: List[Union[str, UUID]]) -> RenewMdmProfile except KeyError: return RenewMdmProfileResponse(udidsNotProcessed=[]) + def redeploy_management_framework_v1( + self, computer_id: Union[int, str] + ) -> RedeployManagementFrameworkResponse: + """Redeploy the Jamf management framework to a computer. + + This reinstalls the Jamf binary and management framework on the target computer. It is + useful for client remediation workflows, such as when the management framework becomes + unresponsive or needs to be reinstalled for re-enrollment scenarios. + + :param computer_id: The ID of the computer to redeploy the management framework to. + :type computer_id: Union[int, str] + + :return: A response containing the device ID and the UUID of the issued command. + :rtype: RedeployManagementFrameworkResponse + """ + resp = self.api_request( + method="post", + resource_path=f"v1/jamf-management-framework/redeploy/{computer_id}", + ) + + return RedeployManagementFrameworkResponse(**resp.json()) + def send_mdm_command_preview( self, management_ids: List[Union[str, UUID]], diff --git a/src/jamf_pro_sdk/models/pro/mdm.py b/src/jamf_pro_sdk/models/pro/mdm.py index 126ac88..73533ff 100644 --- a/src/jamf_pro_sdk/models/pro/mdm.py +++ b/src/jamf_pro_sdk/models/pro/mdm.py @@ -485,6 +485,15 @@ class RenewMdmProfileResponse(BaseModel): udidsNotProcessed: Optional[List[UUID]] +class RedeployManagementFrameworkResponse(BaseModel): + """The response returned when redeploying the Jamf management framework to a computer.""" + + model_config = ConfigDict(extra="allow") + + deviceId: Optional[str] = None + commandUuid: Optional[str] = None + + # MDM Command Status Models diff --git a/tests/unit/models/test_models_pro_mdm.py b/tests/unit/models/test_models_pro_mdm.py index 61d61f1..48ca9bd 100644 --- a/tests/unit/models/test_models_pro_mdm.py +++ b/tests/unit/models/test_models_pro_mdm.py @@ -24,6 +24,7 @@ MdmCommandRequest, PlayLostModeSoundCommand, ProvisioningProfileListCommand, + RedeployManagementFrameworkResponse, RefreshCellularPlansCommand, RequestMirroringCommand, RestartDeviceCommand, @@ -226,3 +227,11 @@ def test_mdm_command_request_parsing_from_dict(): assert len(request.clientData) == 2 assert request.commandData.commandType == "ERASE_DEVICE" assert request.commandData.pin == "654321" + + +def test_redeploy_management_framework_response_parsing(): + """Verify the redeploy management framework response parses from the API JSON.""" + raw = {"deviceId": "123", "commandUuid": "4eecc1fb-f52d-48c5-9560-c246b23601d3"} + response = RedeployManagementFrameworkResponse.model_validate(raw) + assert response.deviceId == "123" + assert response.commandUuid == "4eecc1fb-f52d-48c5-9560-c246b23601d3"