Public/ConnectedSystems/Remove-JIMConnectedSystem.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Remove-JIMConnectedSystem { <# .SYNOPSIS Removes a Connected System from JIM. .DESCRIPTION Deletes a Connected System and all its related data from JIM. By default the deletion runs as "Deprovision through synchronisation" (recommended): the system is fenced and a background run processes every Connected System Object through the synchronisation engine's obsoletion semantics; attribute recall with surviving-contributor re-election, Metaverse Object Deletion Rule evaluation, and Pending Export staging all happen exactly as a normal synchronisation disconnect would, before the system itself is deleted. The cmdlet then returns a tracking object carrying the Activity id; monitor progress with Get-JIMActivity. Use -DeleteImmediately for "Delete immediately and keep contributed data" (today's fast path): - Small systems (< 1000 objects): deleted immediately - Large systems: queued as a background job (a tracking object is returned) - Systems with a running sync: queued to run after the sync completes WARNING: the attribute values this system contributed are kept but lose their provenance, so nothing can ever recall them; surviving contributors are not re-elected and downstream systems are not corrected. Deletion Rules are still evaluated in bulk for orphaned Metaverse Objects, but no per-object synchronisation processing occurs. If a deprovisioning run fails partway, the system stays fenced (its Status remains Deleting) and never returns to service. Re-running this cmdlet retries the run: it resumes from its checkpoint rather than starting again. Running it with -DeleteImmediately instead finishes the deletion immediately, abandoning the remaining deprovisioning work (the Activity records the abandonment). Unless -Force is used, the cmdlet retrieves the deletion preview first so the confirmation states the impact of the chosen mode. Use Get-JIMConnectedSystem -Id <id> -DeletionPreview to review the headline counts yourself before deleting. For the full consequences of deprovisioning through synchronisation (which values other systems would take over, which would be cleared, which Metaverse Objects would become eligible for deletion, and what would be staged for the other Connected Systems), run New-JIMConfigurationChangePreview -ConnectedSystemId <id> -Deletion first, and pass its ActivityId to -PreviewActivityId so the deletion's Activity records that the preview informed it. .PARAMETER Id The ID of the Connected System to delete. .PARAMETER InputObject A Connected System from Get-JIMConnectedSystem, through the pipeline. .PARAMETER DeleteImmediately Deletes the Connected System immediately instead of deprovisioning through synchronisation. The values the Connected System contributed are kept with no provenance, so nothing can ever recall them; surviving contributors are not re-elected and downstream systems are not corrected. On a system whose deprovisioning run failed partway, this finishes the deletion immediately, abandoning the remaining deprovisioning work. .PARAMETER PassThru Returns the outcome of a deletion that completes at once. A deletion that queues returns its tracking object either way. .PARAMETER Force Suppresses the confirmation prompt, and the deletion preview it states. .PARAMETER ChangeReason Why the Connected System was deleted, recorded on the deletion's Activity and in its change history. .PARAMETER PreviewActivityId The ID of the deletion preview this deletion was made after reading: the Activity that New-JIMConfigurationChangePreview -Deletion returns for this Connected System. Recorded on the deletion's Activity so "previewed, then deleted" is auditable rather than a claim. JIM refuses the deletion, deleting nothing, when the id is not a deletion preview of this same Connected System. A preview that a later run or configuration change has overtaken is still recorded, and the deletion's Activity says it was out of date and what overtook it; the cmdlet writes a warning saying so. .OUTPUTS Depends on how the deletion runs. One that runs in the background, as every deletion that deprovisions does, returns an object to follow it by. One that completes at once returns nothing, or its outcome with -PassThru. JIM.ConnectedSystemDeletionQueued: When the deletion queues ActivityId (guid): The ID of the deletion's Activity; follow it with Get-JIMActivity. WorkerTaskId (guid): The ID of the worker task carrying out the deletion. Outcome (string): QueuedAsBackgroundJob, or QueuedAfterSync when a running synchronisation delays it. ConnectedSystemObjectCount (int): How many Connected System Objects the deletion removes, from the deletion preview; empty with -Force, which skips the preview. ContributedValueCount (int): How many Metaverse attribute values the Connected System contributed; empty with -Force. ContributedValueObjectCount (int): How many Metaverse Objects hold those values; empty with -Force. JIM.ConnectedSystemDeletionResult: With -PassThru, when the deletion completes at once .EXAMPLE Remove-JIMConnectedSystem -Id 1 Deprovisions the Connected System with ID 1 through synchronisation (prompts for confirmation, stating the impact from the deletion preview) and returns a tracking object for the queued run. .EXAMPLE $tracking = Remove-JIMConnectedSystem -Id 1 -Force Get-JIMActivity -Id $tracking.ActivityId Deprovisions the Connected System without confirmation, capturing the tracking object, then retrieves the deletion Activity to monitor the run's progress. .EXAMPLE Remove-JIMConnectedSystem -Id 1 -DeleteImmediately -Force Deletes the Connected System immediately, KEEPING the attribute values it contributed. The kept values lose their provenance, so nothing can ever recall them, and downstream systems are not corrected. Only choose this when the data should outlive the system, or for disposable test data. .EXAMPLE Remove-JIMConnectedSystem -Id 1 -Force Run again after a failed deprovisioning run, this RETRIES the run: the system is still fenced and the run resumes from its checkpoint. Use -DeleteImmediately instead to finish the deletion immediately, abandoning the remaining deprovisioning work. .EXAMPLE Get-JIMConnectedSystem -Name "Test*" | Remove-JIMConnectedSystem -DeleteImmediately -Force Force-deletes every Connected System whose name starts with "Test", immediately and keeping contributed data; the usual choice for disposable test systems. Review the matches first by running the Get-JIMConnectedSystem filter on its own, or run the pipeline without -Force to confirm each deletion individually. .EXAMPLE Remove-JIMConnectedSystem -Id 1 -Force -ChangeReason "Decommissioned (CHG0123)" Deprovisions the Connected System, recording the reason on the deletion's change history tombstone. .EXAMPLE $preview = New-JIMConfigurationChangePreview -ConnectedSystemId 1 -Deletion -Wait $preview.ImpactCounts Remove-JIMConnectedSystem -Id 1 -PreviewActivityId $preview.ActivityId Previews the deletion, shows how many objects each consequence reaches, then deprovisions the Connected System (prompting for confirmation) and records the preview on the deletion's Activity. .LINK Get-JIMConnectedSystem New-JIMConnectedSystem New-JIMConfigurationChangePreview Get-JIMActivity #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'ById')] [OutputType('JIM.ConnectedSystemDeletionQueued')] [OutputType('JIM.ConnectedSystemDeletionResult')] param( [Parameter(Mandatory, ParameterSetName = 'ById', ValueFromPipelineByPropertyName)] [int]$Id, [Parameter(Mandatory, ParameterSetName = 'ByInputObject', ValueFromPipeline)] [PSCustomObject]$InputObject, [switch]$DeleteImmediately, [switch]$PassThru, [switch]$Force, [string]$ChangeReason, [guid]$PreviewActivityId ) process { # Check connection first if (-not $script:JIMConnection) { Write-Error "You are not connected to JIM. Run Connect-JIM -Url <your JIM URL> to authenticate, then try again." return } # Get the ID from InputObject if provided $systemId = if ($PSCmdlet.ParameterSetName -eq 'ByInputObject') { $InputObject.id } else { $Id } # Get system name for confirmation message $systemName = if ($PSCmdlet.ParameterSetName -eq 'ByInputObject') { $InputObject.name } else { try { $system = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/connected-systems/$systemId" $system.name } catch { "ID $systemId" } } # Retrieve the deletion preview so the confirmation states the impact of the chosen mode # (the #1537 precedent). -Force suppresses the confirmation, so the lookup would be wasted there # (the documented bulk-pipeline path); the tracking object's counts are then null. $preview = $null $confirmAction = if ($DeleteImmediately) { 'Delete Connected System immediately, keeping contributed data' } else { 'Deprovision Connected System through synchronisation' } if (-not $Force) { try { $preview = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/connected-systems/$systemId/deletion-preview" } catch { # An unavailable preview must not block the deletion; the server still applies the chosen # mode regardless of what the confirmation could state. Write-Verbose "Could not retrieve the deletion preview for Connected System ${systemId}: $_" } $impactText = Get-JIMConnectedSystemDeletionImpactText -Preview $preview -DeleteImmediately:$DeleteImmediately if ($impactText) { $confirmAction = "$confirmAction ($impactText)" } } if (Confirm-JIMAction -Cmdlet $PSCmdlet -Target $systemName -Action $confirmAction -Force:$Force) { Write-Verbose "Deleting Connected System: $systemName (ID: $systemId)" try { # The mode and the reason are supplied as query parameters because HTTP DELETE bodies are # awkward for clients. The deprovisioning default is the server's own, so it is only the # immediate mode that needs saying. $deleteEndpoint = "/api/v1/synchronisation/connected-systems/$systemId" $queryParts = @() if ($DeleteImmediately) { $queryParts += 'synchronisedDeprovisioning=false' } if ($PSBoundParameters.ContainsKey('ChangeReason')) { $queryParts += "changeReason=$([System.Uri]::EscapeDataString($ChangeReason))" } if ($PSBoundParameters.ContainsKey('PreviewActivityId')) { $queryParts += "previewActivityId=$PreviewActivityId" } if ($queryParts.Count -gt 0) { $deleteEndpoint += '?' + ($queryParts -join '&') } $result = Invoke-JIMApi -Endpoint $deleteEndpoint -Method 'DELETE' Write-Verbose "Deletion result: $($result.outcome)" # What the server wants the caller to know about a deletion that went ahead, such as the preview it # cites having been out of date, which its Activity records. foreach ($warning in @($result.warnings)) { if ($warning) { Write-Warning $warning } } if ($result -and $result.WorkerTaskId) { # 202 Accepted: the deletion queued (always the case for deprovisioning). Surface the # tracking object so scripts can monitor the Activity; headline counts come from the # preview when it was retrieved. [PSCustomObject]@{ ActivityId = $result.ActivityId WorkerTaskId = $result.WorkerTaskId Outcome = $result.Outcome ConnectedSystemObjectCount = if ($preview) { $preview.ConnectedSystemObjectCount } else { $null } ContributedValueCount = if ($preview) { $preview.ContributedValueCount } else { $null } ContributedValueObjectCount = if ($preview) { $preview.ContributedValueObjectCount } else { $null } } } elseif ($PassThru) { $result } } catch { Write-Error "Failed to delete Connected System '$systemName': $_" } } } } |