Skip to content

Commit 3e93489

Browse files
committed
(feat) Adding feature to pin assets within an OU
1 parent 8be81cd commit 3e93489

1 file changed

Lines changed: 123 additions & 5 deletions

File tree

Segment/Segment/Asset Management/Pin Assets To Clusters/Pin-AssetsToClusters.ps1

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
.PARAMETER AssetId
1717
Asset ID to pin or unpin. Required for ByAssetId parameter set.
1818
19+
.PARAMETER OUPath
20+
Organizational Unit (OU) path to pin or unpin all assets within. Required for ByOuPath parameter set.
21+
1922
.PARAMETER DeploymentClusterId
20-
Deployment cluster ID to pin/unpin assets to. Required for ByAssetId parameter set.
23+
Deployment cluster ID to pin/unpin assets to. Required for ByAssetId and ByOuPath parameter sets.
2124
2225
.PARAMETER Unpin
23-
Switch to unpin assets instead of pinning them. Available for ByAssetId and ByCsvPath parameter sets.
26+
Switch to unpin assets instead of pinning them. Available for ByAssetId, ByOuPath, and ByCsvPath parameter sets.
2427
2528
.PARAMETER SkipSegmentServerValidation
26-
Skip validation that deployment clusters have online segment servers. Available for ByAssetId and ByCsvPath parameter sets.
29+
Skip validation that deployment clusters have online segment servers. Available for ByAssetId, ByOuPath, and ByCsvPath parameter sets.
2730
2831
.PARAMETER DryRun
29-
Preview changes without applying them. Available for ByAssetId and ByCsvPath parameter sets.
32+
Preview changes without applying them. Available for ByAssetId, ByOuPath, and ByCsvPath parameter sets.
3033
3134
.PARAMETER ListDeploymentClusters
3235
Switch to list all deployment clusters with detailed information.
@@ -52,6 +55,10 @@
5255
.EXAMPLE
5356
.\Pin-AssetsToClusters.ps1 -ApiKey "your-api-key" -CsvPath ".\assets.csv" -DryRun
5457
Previews what changes would be made without actually applying them.
58+
59+
.EXAMPLE
60+
.\Pin-AssetsToClusters.ps1 -ApiKey "your-api-key" -OUPath "OU=Computers,DC=domain,DC=com" -DeploymentClusterId "C:d:00fd409f"
61+
Pins all assets within the specified OU path to a deployment cluster.
5562
#>
5663

5764
<#PSScriptInfo
@@ -66,11 +73,13 @@
6673
param(
6774
# Shared parameter for sets that require authentication
6875
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $true)]
76+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $true)]
6977
[Parameter(ParameterSetName = "ListDeploymentClusters", Mandatory = $true)]
7078
[Parameter(ParameterSetName = "ByCsvPath", Mandatory = $true)]
7179
[string]$ApiKey,
7280

7381
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $false)]
82+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $false)]
7483
[Parameter(ParameterSetName = "ListDeploymentClusters", Mandatory = $false)]
7584
[Parameter(ParameterSetName = "ByCsvPath", Mandatory = $false)]
7685
[string]$PortalUrl = "https://portal.zeronetworks.com",
@@ -79,21 +88,29 @@ param(
7988
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $true)]
8089
[string]$AssetId,
8190

91+
# ParameterSet: Pin by OU Path and Deployment Cluster ID
92+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $true)]
93+
[string]$OUPath,
94+
8295
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $true)]
96+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $true)]
8397
[string]$DeploymentClusterId,
8498

85-
# Shared switch parameter for unpinning (available in ByAssetId and ByCsvPath sets)
99+
# Shared switch parameter for unpinning (available in ByAssetId, ByOuPath, and ByCsvPath sets)
86100
[Parameter(ParameterSetName = "ByAssetId")]
101+
[Parameter(ParameterSetName = "ByOuPath")]
87102
[Parameter(ParameterSetName = "ByCsvPath")]
88103
[switch]$Unpin,
89104

90105
# Shared switch parameter to skip segment server validation (available in all sets with ApiKey)
91106
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $false)]
107+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $false)]
92108
[Parameter(ParameterSetName = "ByCsvPath", Mandatory = $false)]
93109
[switch]$SkipSegmentServerValidation,
94110

95111
# Shared switch parameter for dry run mode (available in all sets with ApiKey)
96112
[Parameter(ParameterSetName = "ByAssetId", Mandatory = $false)]
113+
[Parameter(ParameterSetName = "ByOuPath", Mandatory = $false)]
97114
[Parameter(ParameterSetName = "ByCsvPath", Mandatory = $false)]
98115
[switch]$DryRun,
99116

@@ -316,6 +333,60 @@ function Get-AssetDetails {
316333
}
317334
}
318335

336+
<#
337+
.SYNOPSIS
338+
Retrieves all assets within a specified Organizational Unit (OU) path from the Zero Networks API.
339+
.PARAMETER OUPath
340+
The OU path to retrieve assets for.
341+
.OUTPUTS
342+
Returns an array of asset entity objects that match the OU path.
343+
.NOTES
344+
Throws an exception if no assets are found or if the API response is malformed.
345+
#>
346+
function Get-AssetsByOUPath {
347+
param(
348+
[Parameter(Mandatory = $true)]
349+
[string]$OUPath
350+
)
351+
Write-Host "Getting assets for OU path: $OUPath"
352+
try {
353+
# Query assets API with OU path filter
354+
$FilterArray = @(
355+
@{
356+
id = "name"
357+
includesValues = @(
358+
$OUPath
359+
)
360+
}
361+
)
362+
$FilterJson = $FilterArray | ConvertTo-Json -Compress -AsArray
363+
$response = Invoke-ApiRequest -Method "GET" -ApiEndpoint "assets?_limit=1&_filter=$FilterJson"
364+
365+
# Validate response structure
366+
if ($null -eq $response.items) {
367+
throw "Assets response is malformed and does not contain 'items' property"
368+
}
369+
370+
# Ensure items is an array (handle single item responses)
371+
if ($response.items -isnot [System.Array]) {
372+
$assets = @($response.items)
373+
}
374+
else {
375+
$assets = $response.items
376+
}
377+
378+
if ($assets.Count -eq 0) {
379+
throw "No assets found for OU path: $OUPath"
380+
}
381+
382+
Write-Host "Found $($assets.Count) assets for OU path: $OUPath"
383+
return $assets
384+
}
385+
catch {
386+
throw "Failed to retrieve assets for OU path $OUPath : $_"
387+
}
388+
}
389+
319390
<#
320391
.SYNOPSIS
321392
Pins or unpins assets to a deployment cluster via the Zero Networks API.
@@ -879,6 +950,53 @@ switch ($PSCmdlet.ParameterSetName) {
879950

880951
Write-Host "$($DryRun ? "[DRY RUN] " : '') Finished workflow to $($Unpin ? "unpin" : "pin") asset $AssetId to deployment cluster $DeploymentClusterId"
881952
}
953+
"ByOuPath" {
954+
Write-Host "$($DryRun ? "[DRY RUN] " : '') Starting workflow to $($Unpin ? "unpin" : "pin") assets in OU path $OUPath to deployment cluster $DeploymentClusterId"
955+
Initialize-ApiContext
956+
957+
958+
# Validate deployment cluster exists and has online segment servers
959+
Invoke-ValidateDeploymentClusterId -DeploymentClusterId $DeploymentClusterId -SkipSegmentServerValidation:$SkipSegmentServerValidation
960+
961+
# Get assets by OU path
962+
$assets = Get-AssetsByOUPath -OUPath $OUPath
963+
964+
# Extract asset IDs from assets array
965+
$assetIds = $assets | ForEach-Object { $_.id }
966+
967+
# Validate each asset can be pinned/unpinned
968+
foreach ($assetId in $assetIds) {
969+
Test-AssetCanBePinned -AssetId $assetId -AssetMustBePinned:$Unpin
970+
}
971+
Write-Host "Validated that all assets can be $($Unpin ? "unpinned" : "pinned") to deployment cluster"
972+
973+
$totalAssets = $assetIds.Count
974+
Write-Host "$($Unpin ? "Unpinning" : "Pinning") $totalAssets assets to deployment cluster $($script:DeploymentClusterHashtable[$DeploymentClusterId].name)"
975+
976+
# Batch processing for large asset lists (>50 assets)
977+
if ($totalAssets -gt 50) {
978+
$batchSize = 50
979+
$batchNumber = 1
980+
$totalBatches = [math]::Ceiling($totalAssets / $batchSize)
981+
982+
for ($i = 0; $i -lt $totalAssets; $i += $batchSize) {
983+
# Create batch using array slicing
984+
$batch = $assetIds[$i..([math]::Min($i + $batchSize - 1, $totalAssets - 1))]
985+
Write-Host "Processing batch $batchNumber of $totalBatches ($($batch.Count) assets)..."
986+
Set-AssetsToDeploymentCluster -AssetIdsArray $batch -DeploymentClusterId $DeploymentClusterId -Unpin:$Unpin -DryRun:$DryRun
987+
if (-not $DryRun) {
988+
Write-Host "Successfully $($Unpin ? "unpinned" : "pinned") $($batch.Count) assets to deployment cluster $($script:DeploymentClusterHashtable[$DeploymentClusterId].name)"
989+
}
990+
$batchNumber++
991+
}
992+
}
993+
else {
994+
# Process all assets at once for smaller lists
995+
Set-AssetsToDeploymentCluster -AssetIdsArray $assetIds -DeploymentClusterId $DeploymentClusterId -Unpin:$Unpin -DryRun:$DryRun
996+
}
997+
998+
Write-Host "$($DryRun ? "[DRY RUN] " : '') Finished workflow to $($Unpin ? "unpin" : "pin") assets in OU path $OUPath to deployment cluster $DeploymentClusterId"
999+
}
8821000
"ByCsvPath" {
8831001
Write-Host "$($DryRun ? "[DRY RUN] " : '') Starting workflow to $($Unpin ? "unpin" : "pin") assets from CSV file $CsvPath"
8841002
Initialize-ApiContext

0 commit comments

Comments
 (0)