Skip to content
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
6 changes: 4 additions & 2 deletions Config/FeatureFlags.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@
"ListCIPPUsers",
"ExecSSOSetup",
"ExecContainerManagement",
"ListContainerLogs"
"ListContainerLogs",
"ListWorkerHealth"
],
"Pages": [
"/cipp/advanced/super-admin/cipp-users",
"/cipp/advanced/super-admin/sso",
"/cipp/advanced/super-admin/container",
"/cipp/advanced/container-logs"
"/cipp/advanced/container-logs",
"/cipp/advanced/worker-health"
],
"Hidden": true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function Push-CIPPDBCacheApplyBatch {
Write-Information "Aggregated $($AllTasks.Count) cache tasks from all tenants"

# Start a single flat orchestrator to execute all cache tasks
$TenantSuffix = if ($Item.Parameters.TenantFilter) { "_$($Item.Parameters.TenantFilter)" } else { '' }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'CIPPDBCacheExecute'
OrchestratorName = "CIPPDBCacheExecute$TenantSuffix"
Batch = @($AllTasks)
SkipLog = $true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function Push-CIPPTestsApplyBatch {
Write-Information "Aggregated $($AllTasks.Count) test tasks from all tenants"

# Start a single flat orchestrator to execute all test tasks
$TenantSuffix = if ($Item.Parameters.TenantFilter) { "_$($Item.Parameters.TenantFilter)" } else { '' }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'CIPPTestsExecute'
OrchestratorName = "CIPPTestsExecute$TenantSuffix"
Batch = @($AllTasks)
SkipLog = $true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,16 @@ function Start-CIPPDBTestsRun {
Write-Information "Built batch of $($Batch.Count) tenant test list activities"

# Phase 2 via PostExecution: Aggregate all task lists and start flat execution orchestrator
$NameSuffix = if ($TenantFilter -ne 'allTenants') { "-$TenantFilter" } else { '' }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'TestsList'
OrchestratorName = "TestsList$NameSuffix"
Batch = @($Batch)
SkipLog = $true
PostExecution = @{
FunctionName = 'CIPPTestsApplyBatch'
Parameters = @{
TenantFilter = $TenantFilter
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
function Invoke-ListWorkerHealth {
<#
.FUNCTIONALITY
Entrypoint,AnyTenant
.ROLE
CIPP.SuperAdmin.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)

$APIName = $Request.Params.CIPPEndpoint
$Action = $Request.Query.Action ?? 'Snapshot'

try {
switch ($Action) {
'Snapshot' {
$Snapshot = [Craft.Services.WorkerMetricsBridge]::GetSnapshot()
$Body = @{ Results = $Snapshot }
}
'Summary' {
$Summary = [Craft.Services.WorkerMetricsBridge]::GetSummary()
$Body = @{ Results = $Summary }
}
'Pool' {
$PoolType = $Request.Query.PoolType ?? 'http'
$Pool = [Craft.Services.WorkerMetricsBridge]::GetPoolMetrics($PoolType)
$Body = @{ Results = $Pool }
}
'Jobs' {
$RunName = $Request.Query.RunName
$Status = $Request.Query.Status
$Limit = if ($Request.Query.Limit) { [int]$Request.Query.Limit } else { 100 }
$Jobs = [Craft.Services.WorkerMetricsBridge]::GetJobDetails($RunName, $Status, $Limit)
$Body = @{ Results = $Jobs }
}
'Runs' {
$Runs = [Craft.Services.WorkerMetricsBridge]::GetRunSummaries()
$Body = @{ Results = $Runs }
}
'CancelJob' {
$JobId = $Request.Query.JobId ?? $Request.Body.JobId
if (-not $JobId) {
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = @{ Results = 'JobId is required' }
}
}
$Result = [Craft.Services.WorkerMetricsBridge]::CancelJob($JobId)
$Body = @{ Results = @{ Success = $Result; JobId = $JobId } }
}
'CancelRun' {
$RunName = $Request.Query.RunName ?? $Request.Body.RunName
if (-not $RunName) {
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = @{ Results = 'RunName is required' }
}
}
$Cancelled = [Craft.Services.WorkerMetricsBridge]::CancelRun($RunName)
$Body = @{ Results = @{ Success = $true; RunName = $RunName; CancelledCount = $Cancelled } }
}
'DeleteJob' {
$JobId = $Request.Query.JobId ?? $Request.Body.JobId
if (-not $JobId) {
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = @{ Results = 'JobId is required' }
}
}
$Result = [Craft.Services.WorkerMetricsBridge]::DeleteJob($JobId)
$Body = @{ Results = @{ Success = $Result; JobId = $JobId } }
}
'PurgeCompleted' {
$Purged = [Craft.Services.WorkerMetricsBridge]::PurgeCompleted()
$Body = @{ Results = @{ Success = $true; PurgedCount = $Purged } }
}
'ChangePriority' {
$JobId = $Request.Query.JobId ?? $Request.Body.JobId
$NewPriority = $Request.Query.Priority ?? $Request.Body.Priority
if (-not $JobId -or $null -eq $NewPriority) {
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = @{ Results = 'JobId and Priority are required' }
}
}
$Result = [Craft.Services.WorkerMetricsBridge]::ChangePriority($JobId, [int]$NewPriority)
$Body = @{ Results = @{ Success = $Result; JobId = $JobId; NewPriority = [int]$NewPriority } }
}
default {
$Body = @{ Results = "Unknown action: $Action" }
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = $Body
}
}
}
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API $APIName -message "Worker health error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage
return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::InternalServerError
Body = @{ Results = "Failed: $($ErrorMessage.NormalizedError)" }
}
}

return [HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $Body
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ function Invoke-ExecTestRun {
@{
FunctionName = 'CIPPDBCacheData'
TenantFilter = $TenantFilter
QueueId = $Queue.RowKey
QueueName = "Cache - $TenantFilter"
}
)
$InputObject = [PSCustomObject]@{
OrchestratorName = 'TestDataCollectionAndRun'
OrchestratorName = "TestDataCollectionAndRun-$TenantFilter"
Batch = $Batch
SkipLog = $false
PostExecution = @{
Expand Down