diff --git a/step-templates/octopus-get-octopus-usage.json b/step-templates/octopus-get-octopus-usage.json index 2a3fe7e9c..9388f3ef9 100644 --- a/step-templates/octopus-get-octopus-usage.json +++ b/step-templates/octopus-get-octopus-usage.json @@ -3,14 +3,14 @@ "Name": "Get Octopus Usage", "Description": "Step template to gather Octopus usage details across spaces. The results will be output to the log and also as a downloadable artifact.\n\nTo avoid slowing down your instance, this script will pull back 50 items at a time and count them. It is designed to run on instances as old as 3.4.\n\n**Required:** An API Key for a user or service account that has read access in every space on the instance.", "ActionType": "Octopus.Script", - "Version": 4, + "Version": 5, "CommunityActionTemplateId": null, "Packages": [], "GitDependencies": [], "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "PowerShell", - "Octopus.Action.Script.ScriptBody": "$OctopusDeployUrl = $OctopusParameters[\"GetUsage.Octopus.ServerUri\"]\n$OctopusDeployApiKey = $OctopusParameters[\"GetUsage.Octopus.ApiKey\"]\n\nfunction Get-OctopusUrl\n{\n param (\n $EndPoint,\n $SpaceId,\n $OctopusUrl\n )\n\n $octopusUrlToUse = $OctopusUrl\n if ($OctopusUrl.EndsWith(\"/\"))\n {\n $octopusUrlToUse = $OctopusUrl.Substring(0, $OctopusUrl.Length - 1)\n }\n\n if ($EndPoint -match \"/api\")\n {\n if (!$EndPoint.StartsWith(\"/api\"))\n {\n $EndPoint = $EndPoint.Substring($EndPoint.IndexOf(\"/api\"))\n }\n\n return \"$octopusUrlToUse$EndPoint\"\n }\n\n if ([string]::IsNullOrWhiteSpace($SpaceId))\n {\n return \"$octopusUrlToUse/api/$EndPoint\"\n }\n\n return \"$octopusUrlToUse/api/$spaceId/$EndPoint\"\n}\n\nfunction Invoke-OctopusApi\n{\n param\n (\n $endPoint,\n $spaceId,\n $octopusUrl, \n $apiKey\n ) \n\n try\n { \n $url = Get-OctopusUrl -EndPoint $endPoint -SpaceId $spaceId -OctopusUrl $octopusUrl\n\n Write-Host \"Invoking $url\"\n return Invoke-RestMethod -Method Get -Uri $url -Headers @{\"X-Octopus-ApiKey\" = \"$apiKey\" } -ContentType 'application/json; charset=utf-8' -TimeoutSec 60 \n }\n catch\n {\n Write-Host \"There was an error making a Get call to the $url. Please check that for more information.\" -ForegroundColor Red\n\n if ($null -ne $_.Exception.Response)\n {\n if ($_.Exception.Response.StatusCode -eq 401)\n {\n Write-Host \"Unauthorized error returned from $url, please verify API key and try again\" -ForegroundColor Red\n }\n elseif ($_.ErrorDetails.Message)\n { \n Write-Host -Message \"Error calling $url StatusCode: $($_.Exception.Response) $($_.ErrorDetails.Message)\" -ForegroundColor Red\n Write-Host $_.Exception -ForegroundColor Red\n } \n else \n {\n Write-Host $_.Exception -ForegroundColor Red\n }\n }\n else\n {\n Write-Host $_.Exception -ForegroundColor Red\n }\n\n Write-Host \"Stopping the script from proceeding\" -ForegroundColor Red\n exit 1\n } \n}\n\nfunction Get-OctopusObjectCount\n{\n param\n (\n $endPoint,\n $spaceId,\n $octopusUrl, \n $apiKey\n )\n\n $itemCount = 0\n $currentPage = 1\n $pageSize = 50\n $skipValue = 0\n $haveReachedEndOfList = $false\n\n while ($haveReachedEndOfList -eq $false)\n {\n $currentEndPoint = \"$($endPoint)?skip=$skipValue&take=$pageSize\"\n\n $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey\n\n foreach ($item in $itemList.Items)\n {\n if ($null -ne (Get-Member -InputObject $item -Name \"IsDisabled\" -MemberType Properties))\n { \n if ($item.IsDisabled -eq $false)\n {\n $itemCount += 1\n }\n }\n else \n {\n $itemCount += 1 \n }\n }\n\n if ($currentPage -lt $itemList.NumberOfPages)\n {\n $skipValue = $currentPage * $pageSize\n $currentPage += 1\n\n Write-Host \"The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages. Setting the skip value to $skipValue and re-querying\"\n }\n else\n {\n $haveReachedEndOfList = $true \n }\n }\n \n return $itemCount\n}\n\nfunction Get-OctopusDeploymentTargetsCount\n{\n param\n (\n $spaceId,\n $octopusUrl, \n $apiKey\n )\n\n $targetCount = @{\n TargetCount = 0 \n ActiveTargetCount = 0\n UnavailableTargetCount = 0 \n DisabledTargets = 0\n ActiveListeningTentacleTargets = 0\n ActivePollingTentacleTargets = 0\n ActiveSshTargets = 0 \n ActiveKubernetesCount = 0\n ActiveAzureWebAppCount = 0\n ActiveAzureServiceFabricCount = 0\n ActiveAzureCloudServiceCount = 0\n ActiveOfflineDropCount = 0 \n ActiveECSClusterCount = 0\n ActiveCloudRegions = 0 \n ActiveFtpTargets = 0\n DisabledListeningTentacleTargets = 0\n DisabledPollingTentacleTargets = 0\n DisabledSshTargets = 0 \n DisabledKubernetesCount = 0\n DisabledAzureWebAppCount = 0\n DisabledAzureServiceFabricCount = 0\n DisabledAzureCloudServiceCount = 0\n DisabledOfflineDropCount = 0 \n DisabledECSClusterCount = 0\n DisabledCloudRegions = 0 \n DisabledFtpTargets = 0 \n }\n\n $currentPage = 1\n $pageSize = 50\n $skipValue = 0\n $haveReachedEndOfList = $false\n\n while ($haveReachedEndOfList -eq $false)\n {\n $currentEndPoint = \"machines?skip=$skipValue&take=$pageSize\"\n\n $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey\n\n foreach ($item in $itemList.Items)\n {\n $targetCount.TargetCount += 1\n\n if ($item.IsDisabled -eq $true)\n {\n $targetCount.DisabledTargets += 1 \n\n if ($item.EndPoint.CommunicationStyle -eq \"None\")\n {\n $targetCount.DisabledCloudRegions += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentacleActive\")\n {\n $targetCount.DisabledPollingTentacleTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentaclePassive\")\n {\n $targetCount.DisabledListeningTentacleTargets += 1\n }\n # Cover newer k8s agent and traditional worker-API approach\n elseif ($item.EndPoint.CommunicationStyle -ilike \"Kubernetes*\")\n {\n $targetCount.DisabledKubernetesCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureWebApp\")\n {\n $targetCount.DisabledAzureWebAppCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ssh\")\n {\n $targetCount.DisabledSshTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ftp\")\n {\n $targetCount.DisabledFtpTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureCloudService\")\n {\n $targetCount.DisabledAzureCloudServiceCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureServiceFabricCluster\")\n {\n $targetCount.DisabledAzureServiceFabricCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"OfflineDrop\")\n {\n $targetCount.DisabledOfflineDropCount += 1\n }\n else\n {\n $targetCount.DisabledECSClusterCount += 1\n }\n }\n else\n {\n if ($item.HealthStatus -eq \"Healthy\" -or $item.HealthStatus -eq \"HealthyWithWarnings\")\n {\n $targetCount.ActiveTargetCount += 1\n }\n else\n {\n $targetCount.UnavailableTargetCount += 1 \n }\n\n if ($item.EndPoint.CommunicationStyle -eq \"None\")\n {\n $targetCount.ActiveCloudRegions += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentacleActive\")\n {\n $targetCount.ActivePollingTentacleTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentaclePassive\")\n {\n $targetCount.ActiveListeningTentacleTargets += 1\n }\n # Cover newer k8s agent and traditional worker-API approach\n elseif ($item.EndPoint.CommunicationStyle -ilike \"Kubernetes*\")\n {\n $targetCount.ActiveKubernetesCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureWebApp\")\n {\n $targetCount.ActiveAzureWebAppCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ssh\")\n {\n $targetCount.ActiveSshTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ftp\")\n {\n $targetCount.ActiveFtpTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureCloudService\")\n {\n $targetCount.ActiveAzureCloudServiceCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureServiceFabricCluster\")\n {\n $targetCount.ActiveAzureServiceFabricCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"OfflineDrop\")\n {\n $targetCount.ActiveOfflineDropCount += 1\n }\n else\n {\n $targetCount.ActiveECSClusterCount += 1\n }\n } \n }\n\n if ($currentPage -lt $itemList.NumberOfPages)\n {\n $skipValue = $currentPage * $pageSize\n $currentPage += 1\n\n Write-Host \"The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages. Setting the skip value to $skipValue and re-querying\"\n }\n else\n {\n $haveReachedEndOfList = $true \n }\n }\n \n return $targetCount\n}\n\n$ObjectCounts = @{\n ProjectCount = 0\n TenantCount = 0 \n TargetCount = 0 \n DisabledTargets = 0\n ActiveTargetCount = 0\n UnavailableTargetCount = 0\n ActiveListeningTentacleTargets = 0\n ActivePollingTentacleTargets = 0\n ActiveSshTargets = 0 \n ActiveKubernetesCount = 0\n ActiveAzureWebAppCount = 0\n ActiveAzureServiceFabricCount = 0\n ActiveAzureCloudServiceCount = 0\n ActiveOfflineDropCount = 0 \n ActiveECSClusterCount = 0\n ActiveCloudRegions = 0\n ActiveFtpTargets = 0 \n DisabledListeningTentacleTargets = 0\n DisabledPollingTentacleTargets = 0\n DisabledSshTargets = 0 \n DisabledKubernetesCount = 0\n DisabledAzureWebAppCount = 0\n DisabledAzureServiceFabricCount = 0\n DisabledAzureCloudServiceCount = 0\n DisabledOfflineDropCount = 0 \n DisabledECSClusterCount = 0\n DisabledCloudRegions = 0 \n DisabledFtpTargets = 0 \n WorkerCount = 0\n ListeningTentacleWorkers = 0\n PollingTentacleWorkers = 0\n SshWorkers = 0\n ActiveWorkerCount = 0\n UnavailableWorkerCount = 0\n WindowsLinuxAgentCount = 0\n LicensedTargetCount = 0\n LicensedWorkerCount = 0\n}\n\nWrite-Host \"Getting Octopus Deploy Version Information\"\n$apiInformation = Invoke-OctopusApi -endPoint \"/api\" -spaceId $null -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n$splitVersion = $apiInformation.Version -split \"\\.\"\n$OctopusMajorVersion = [int]$splitVersion[0]\n$OctopusMinorVersion = [int]$splitVersion[1]\n\n$hasLicenseSummary = $OctopusMajorVersion -ge 4\n$hasSpaces = $OctopusMajorVersion -ge 2019\n$hasWorkers = ($OctopusMajorVersion -eq 2018 -and $OctopusMinorVersion -ge 7) -or $OctopusMajorVersion -ge 2019\n\n$spaceIdList = @()\nif ($hasSpaces -eq $true)\n{\n $OctopusSpaceList = Invoke-OctopusApi -endPoint \"spaces?skip=0&take=10000\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n foreach ($space in $OctopusSpaceList.Items)\n {\n $spaceIdList += $space.Id\n }\n}\nelse\n{\n $spaceIdList += $null \n}\n\nif ($hasLicenseSummary -eq $true)\n{\n Write-Host \"Checking the license summary for this instance\"\n $licenseSummary = Invoke-OctopusApi -endPoint \"licenses/licenses-current-status\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n\n if ($null -ne (Get-Member -InputObject $licenseSummary -Name \"NumberOfMachines\" -MemberType Properties))\n {\n $ObjectCounts.LicensedTargetCount = $licenseSummary.NumberOfMachines\n }\n else\n {\n foreach ($limit in $licenseSummary.Limits)\n {\n if ($limit.Name -eq \"Targets\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Targets\"\n $ObjectCounts.LicensedTargetCount = $limit.CurrentUsage\n }\n\n if ($limit.Name -eq \"Workers\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Workers\"\n $ObjectCounts.LicensedWorkerCount = $limit.CurrentUsage\n }\n }\n }\n}\n\n\nforeach ($spaceId in $spaceIdList)\n{ \n Write-Host \"Getting project counts for $spaceId\"\n $activeProjectCount = Get-OctopusObjectCount -endPoint \"projects\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-Host \"$spaceId has $activeProjectCount active projects.\"\n $ObjectCounts.ProjectCount += $activeProjectCount\n\n Write-Host \"Getting tenant counts for $spaceId\"\n $activeTenantCount = Get-OctopusObjectCount -endPoint \"tenants\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-Host \"$spaceId has $activeTenantCount tenants.\"\n $ObjectCounts.TenantCount += $activeTenantCount\n\n Write-Host \"Getting Infrastructure Summary for $spaceId\"\n $infrastructureSummary = Get-OctopusDeploymentTargetsCount -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-host \"$spaceId has $($infrastructureSummary.TargetCount) targets\"\n $ObjectCounts.TargetCount += $infrastructureSummary.TargetCount\n\n Write-Host \"$spaceId has $($infrastructureSummary.ActiveTargetCount) Healthy Targets\"\n $ObjectCounts.ActiveTargetCount += $infrastructureSummary.ActiveTargetCount\n\n Write-Host \"$spaceId has $($infrastructureSummary.DisabledTargets) Disabled Targets\"\n $ObjectCounts.DisabledTargets += $infrastructureSummary.DisabledTargets\n\n Write-Host \"$spaceId has $($infrastructureSummary.UnavailableTargetCount) Unhealthy Targets\"\n $ObjectCounts.UnavailableTargetCount += $infrastructureSummary.UnavailableTargetCount \n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveListeningTentacleTargets) Active Listening Tentacles Targets\"\n $ObjectCounts.ActiveListeningTentacleTargets += $infrastructureSummary.ActiveListeningTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActivePollingTentacleTargets) Active Polling Tentacles Targets\"\n $ObjectCounts.ActivePollingTentacleTargets += $infrastructureSummary.ActivePollingTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveCloudRegions) Active Cloud Region Targets\"\n $ObjectCounts.ActiveCloudRegions += $infrastructureSummary.ActiveCloudRegions\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveOfflineDropCount) Active Offline Packages\"\n $ObjectCounts.ActiveOfflineDropCount += $infrastructureSummary.ActiveOfflineDropCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Active SSH Targets\"\n $ObjectCounts.ActiveSshTargets += $infrastructureSummary.ActiveSshTargets\n \n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Active Kubernetes Targets\"\n $ObjectCounts.ActiveKubernetesCount += $infrastructureSummary.ActiveKubernetesCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureWebAppCount) Active Azure Web App Targets\"\n $ObjectCounts.ActiveAzureWebAppCount += $infrastructureSummary.ActiveAzureWebAppCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureServiceFabricCount) Active Azure Service Fabric Cluster Targets\"\n $ObjectCounts.ActiveAzureServiceFabricCount += $infrastructureSummary.ActiveAzureServiceFabricCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureCloudServiceCount) Active (Legacy) Azure Cloud Service Targets\"\n $ObjectCounts.ActiveAzureCloudServiceCount += $infrastructureSummary.ActiveAzureCloudServiceCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveECSClusterCount) Active ECS Cluster Targets\"\n $ObjectCounts.ActiveECSClusterCount += $infrastructureSummary.ActiveECSClusterCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveFtpTargets) Active FTP Targets\"\n $ObjectCounts.ActiveFtpTargets += $infrastructureSummary.ActiveFtpTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledListeningTentacleTargets) Disabled Listening Tentacles Targets\"\n $ObjectCounts.DisabledListeningTentacleTargets += $infrastructureSummary.DisabledListeningTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledPollingTentacleTargets) Disabled Polling Tentacles Targets\"\n $ObjectCounts.DisabledPollingTentacleTargets += $infrastructureSummary.DisabledPollingTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledCloudRegions) Disabled Cloud Region Targets\"\n $ObjectCounts.DisabledCloudRegions += $infrastructureSummary.DisabledCloudRegions\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledOfflineDropCount) Disabled Offline Packages\"\n $ObjectCounts.DisabledOfflineDropCount += $infrastructureSummary.DisabledOfflineDropCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledSshTargets) Disabled SSH Targets\"\n $ObjectCounts.DisabledSshTargets += $infrastructureSummary.DisabledSshTargets\n \n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Disabled Kubernetes Targets\"\n $ObjectCounts.DisabledKubernetesCount += $infrastructureSummary.DisabledKubernetesCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureWebAppCount) Disabled Azure Web App Targets\"\n $ObjectCounts.DisabledAzureWebAppCount += $infrastructureSummary.DisabledAzureWebAppCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureServiceFabricCount) Disabled Azure Service Fabric Cluster Targets\"\n $ObjectCounts.DisabledAzureServiceFabricCount += $infrastructureSummary.DisabledAzureServiceFabricCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureCloudServiceCount) Disabled (Legacy) Azure Cloud Service Targets\"\n $ObjectCounts.DisabledAzureCloudServiceCount += $infrastructureSummary.DisabledAzureCloudServiceCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledECSClusterCount) Disabled ECS Cluster Targets\"\n $ObjectCounts.DisabledECSClusterCount += $infrastructureSummary.DisabledECSClusterCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledFtpTargets) Disabled FTP Targets\"\n $ObjectCounts.DisabledFtpTargets += $infrastructureSummary.DisabledFtpTargets\n\n if ($hasWorkers -eq $true)\n {\n Write-Host \"Getting worker information for $spaceId\"\n $workerPoolSummary = Invoke-OctopusApi -endPoint \"workerpools/summary\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey \n\n Write-host \"$spaceId has $($workerPoolSummary.TotalMachines) Workers\"\n $ObjectCounts.WorkerCount += $workerPoolSummary.TotalMachines\n\n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Healthy) Healthy Workers\"\n $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Healthy\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.HasWarnings) Healthy with Warning Workers\"\n $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.HasWarnings\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unhealthy) Unhealthy Workers\"\n $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unhealthy\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unknown) Workers with a Status of Unknown\"\n $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unknown\n \n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentaclePassive) Listening Tentacles Workers\"\n $ObjectCounts.ListeningTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentaclePassive\n\n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) Polling Tentacles Workers\"\n $ObjectCounts.PollingTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentacleActive \n\n if ($null -ne (Get-Member -InputObject $workerPoolSummary.MachineEndpointSummaries -Name \"Ssh\" -MemberType Properties))\n {\n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) SSH Targets Workers\"\n $ObjectCounts.SshWorkers += $workerPoolSummary.MachineEndpointSummaries.Ssh\n }\n }\n}\n\nWrite-Host \"Calculating Windows and Linux Agent Count\"\n$ObjectCounts.WindowsLinuxAgentCount = $ObjectCounts.ActivePollingTentacleTargets + $ObjectCounts.ActiveListeningTentacleTargets + $ObjectCounts.ActiveSshTargets\n\nif ($hasLicenseSummary -eq $false)\n{\n $ObjectCounts.LicensedTargetCount = $ObjectCounts.TargetCount - $ObjectCounts.ActiveCloudRegions - $ObjectCounts.DisabledTargets \n}\n\n\n# Get node information\n$nodeInfo = Invoke-OctopusApi -endPoint \"octopusservernodes\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n\n$text = @\"\nThe item counts are as follows:\n`tInstance ID: $($apiInformation.InstallationId)\n`tServer Version: $($apiInformation.Version)\n`tNumber of Server Nodes: $($nodeInfo.TotalResults)\n`tLicensed Target Count: $($ObjectCounts.LicensedTargetCount) (these are active targets de-duped across the instance if running a modern version of Octopus)\n`tProject Count: $($ObjectCounts.ProjectCount)\n`tTenant Count: $($ObjectCounts.TenantCount)\n`tAgent Counts: $($ObjectCounts.WindowsLinuxAgentCount)\n`tDeployment Target Count: $($ObjectCounts.TargetCount)\n`t`tActive and Available Targets: $($ObjectCounts.ActiveTargetCount)\n`t`tActive but Unavailable Targets: $($ObjectCounts.UnavailableTargetCount)\n`t`tActive Target Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.ActiveListeningTentacleTargets)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.ActivePollingTentacleTargets)\n`t`t`tSSH Target Count: $($ObjectCounts.ActiveSshTargets)\n`t`t`tKubernetes Target Count: $($ObjectCounts.ActiveKubernetesCount)\n`t`t`tAzure Web App Target Count: $($ObjectCounts.ActiveAzureWebAppCount)\n`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.ActiveAzureServiceFabricCount)\n`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.ActiveAzureCloudServiceCount)\n`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.ActiveECSClusterCount)\n`t`t`tOffline Target Count: $($ObjectCounts.ActiveOfflineDropCount)\n`t`t`tCloud Region Target Count: $($ObjectCounts.ActiveCloudRegions)\n`t`t`tFtp Target Count: $($ObjectCounts.ActiveFtpTargets)\n`t`tDisabled Targets Targets: $($ObjectCounts.DisabledTargets)\n`t`tDisabled Target Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.DisabledListeningTentacleTargets)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.DisabledPollingTentacleTargets)\n`t`t`tSSH Target Count: $($ObjectCounts.DisabledSshTargets)\n`t`t`tKubernetes Target Count: $($ObjectCounts.DisabledKubernetesCount)\n`t`t`tAzure Web App Target Count: $($ObjectCounts.DisabledAzureWebAppCount)\n`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.DisabledAzureServiceFabricCount)\n`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.DisabledAzureCloudServiceCount)\n`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.DisabledECSClusterCount)\n`t`t`tOffline Target Count: $($ObjectCounts.DisabledOfflineDropCount)\n`t`t`tCloud Region Target Count: $($ObjectCounts.DisabledCloudRegions)\n`t`t`tFtp Target Count: $($ObjectCounts.DisabledFtpTargets)\n`tWorker Count: $($ObjectCounts.WorkerCount)\n`t`tActive Workers: $($ObjectCounts.ActiveWorkerCount)\n`t`tUnavailable Workers: $($ObjectCounts.UnavailableWorkerCount)\n`t`tWorker Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.ListeningTentacleWorkers)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.PollingTentacleWorkers)\n`t`t`tSSH Target Count: $($ObjectCounts.SshWorkers)\n\"@\n\nWrite-Host $text\n$text > octopus-usage.txt\nNew-OctopusArtifact \"$($PWD)/octopus-usage.txt\"" + "Octopus.Action.Script.ScriptBody": "$OctopusDeployUrl = $OctopusParameters[\"GetUsage.Octopus.ServerUri\"]\n$OctopusDeployApiKey = $OctopusParameters[\"GetUsage.Octopus.ApiKey\"]\n\n## To avoid nuking your instance, this script will pull back 50 items at a time and count them. It is designed to run on instances as far back as 3.4.\n\nfunction Get-OctopusUrl\n{\n param (\n $EndPoint,\n $SpaceId,\n $OctopusUrl \n )\n\n $octopusUrlToUse = $OctopusUrl\n if ($OctopusUrl.EndsWith(\"/\"))\n {\n $octopusUrlToUse = $OctopusUrl.Substring(0, $OctopusUrl.Length - 1)\n }\n\n if ($EndPoint -match \"/api\")\n {\n if (!$EndPoint.StartsWith(\"/api\"))\n {\n $EndPoint = $EndPoint.Substring($EndPoint.IndexOf(\"/api\"))\n }\n\n return \"$octopusUrlToUse$EndPoint\"\n }\n\n if ([string]::IsNullOrWhiteSpace($SpaceId))\n {\n return \"$octopusUrlToUse/api/$EndPoint\"\n }\n\n return \"$octopusUrlToUse/api/$spaceId/$EndPoint\"\n}\n\nfunction Invoke-OctopusApi\n{\n param\n (\n $endPoint,\n $spaceId,\n $octopusUrl, \n $apiKey\n ) \n\n try\n { \n $url = Get-OctopusUrl -EndPoint $endPoint -SpaceId $spaceId -OctopusUrl $octopusUrl\n\n Write-Host \"Invoking $url\"\n return Invoke-RestMethod -Method Get -Uri $url -Headers @{\"X-Octopus-ApiKey\" = \"$apiKey\" } -ContentType 'application/json; charset=utf-8' -TimeoutSec 60 \n }\n catch\n {\n Write-Host \"There was an error making a Get call to the $url. Please check that for more information.\" -ForegroundColor Red\n\n if ($null -ne $_.Exception.Response)\n {\n if ($_.Exception.Response.StatusCode -eq 401)\n {\n Write-Host \"Unauthorized error returned from $url, please verify API key and try again\" -ForegroundColor Red\n }\n elseif ($_.ErrorDetails.Message)\n { \n Write-Host -Message \"Error calling $url StatusCode: $($_.Exception.Response) $($_.ErrorDetails.Message)\" -ForegroundColor Red\n Write-Host $_.Exception -ForegroundColor Red\n } \n else \n {\n Write-Host $_.Exception -ForegroundColor Red\n }\n }\n else\n {\n Write-Host $_.Exception -ForegroundColor Red\n }\n\n Write-Host \"Stopping the script from proceeding\" -ForegroundColor Red\n exit 1\n } \n}\n\nfunction Get-OctopusObjectCount\n{\n param\n (\n $endPoint,\n $spaceId,\n $octopusUrl, \n $apiKey\n )\n\n $activeItemCount = 0\n $disabledItemCount = 0\n $currentPage = 1\n $pageSize = 50\n $skipValue = 0\n $haveReachedEndOfList = $false\n\n while ($haveReachedEndOfList -eq $false)\n {\n $currentEndPoint = \"$($endPoint)?skip=$skipValue&take=$pageSize\"\n\n $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey\n\n foreach ($item in $itemList.Items)\n {\n if ($null -ne (Get-Member -InputObject $item -Name \"IsDisabled\" -MemberType Properties))\n { \n if ($item.IsDisabled -eq $false)\n {\n $activeItemCount += 1\n }\n else\n {\n $disabledItemCount += 1\n }\n }\n else \n {\n $activeItemCount += 1 \n }\n }\n\n if ($currentPage -lt $itemList.NumberOfPages)\n {\n $skipValue = $currentPage * $pageSize\n $currentPage += 1\n\n Write-Host \"The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages. Setting the skip value to $skipValue and re-querying\"\n }\n else\n {\n $haveReachedEndOfList = $true \n }\n }\n \n return @{\n ActiveItemCount = $activeItemCount\n DisabledItemCount = $disabledItemCount\n TotalItemCount = $activeItemCount + $disabledItemCount\n }\n}\n\nfunction Get-EffectiveLimit \n{\n param (\n $limit\n )\n\n if ($null -ne (Get-Member -InputObject $limit -Name \"LicensedLimit\" -MemberType Properties))\n {\n if ($limit.LicensedLimit -eq 2147483647) # int.MaxValue means it is an unlimited license\n {\n return \"of Unlimited\"\n }\n else\n {\n return \"of $($limit.LicensedLimit)\"\n }\n }\n \n return \"\"\n}\n\nfunction Get-OctopusDeploymentTargetsCount\n{\n param\n (\n $spaceId,\n $octopusUrl, \n $apiKey\n )\n\n $targetCount = @{\n TargetCount = 0 \n ActiveTargetCount = 0\n UnavailableTargetCount = 0 \n DisabledTargets = 0\n ActiveListeningTentacleTargets = 0\n ActivePollingTentacleTargets = 0\n ActiveSshTargets = 0 \n ActiveKubernetesCount = 0\n ActiveAzureWebAppCount = 0\n ActiveAzureServiceFabricCount = 0\n ActiveAzureCloudServiceCount = 0\n ActiveOfflineDropCount = 0 \n ActiveECSClusterCount = 0\n ActiveCloudRegions = 0 \n ActiveFtpTargets = 0\n DisabledListeningTentacleTargets = 0\n DisabledPollingTentacleTargets = 0\n DisabledSshTargets = 0 \n DisabledKubernetesCount = 0\n DisabledAzureWebAppCount = 0\n DisabledAzureServiceFabricCount = 0\n DisabledAzureCloudServiceCount = 0\n DisabledOfflineDropCount = 0 \n DisabledECSClusterCount = 0\n DisabledCloudRegions = 0 \n DisabledFtpTargets = 0 \n }\n\n $currentPage = 1\n $pageSize = 50\n $skipValue = 0\n $haveReachedEndOfList = $false\n\n while ($haveReachedEndOfList -eq $false)\n {\n $currentEndPoint = \"machines?skip=$skipValue&take=$pageSize\"\n\n $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey\n\n foreach ($item in $itemList.Items)\n {\n $targetCount.TargetCount += 1\n\n if ($item.IsDisabled -eq $true)\n {\n $targetCount.DisabledTargets += 1 \n\n if ($item.EndPoint.CommunicationStyle -eq \"None\")\n {\n $targetCount.DisabledCloudRegions += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentacleActive\")\n {\n $targetCount.DisabledPollingTentacleTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentaclePassive\")\n {\n $targetCount.DisabledListeningTentacleTargets += 1\n }\n # Cover newer k8s agent and traditional worker-API approach\n elseif ($item.EndPoint.CommunicationStyle -ilike \"Kubernetes*\")\n {\n $targetCount.DisabledKubernetesCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureWebApp\")\n {\n $targetCount.DisabledAzureWebAppCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ssh\")\n {\n $targetCount.DisabledSshTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ftp\")\n {\n $targetCount.DisabledFtpTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureCloudService\")\n {\n $targetCount.DisabledAzureCloudServiceCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureServiceFabricCluster\")\n {\n $targetCount.DisabledAzureServiceFabricCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"OfflineDrop\")\n {\n $targetCount.DisabledOfflineDropCount += 1\n }\n else\n {\n $targetCount.DisabledECSClusterCount += 1\n }\n }\n else\n {\n if ($item.HealthStatus -eq \"Healthy\" -or $item.HealthStatus -eq \"HealthyWithWarnings\")\n {\n $targetCount.ActiveTargetCount += 1\n }\n else\n {\n $targetCount.UnavailableTargetCount += 1 \n }\n\n if ($item.EndPoint.CommunicationStyle -eq \"None\")\n {\n $targetCount.ActiveCloudRegions += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentacleActive\")\n {\n $targetCount.ActivePollingTentacleTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"TentaclePassive\")\n {\n $targetCount.ActiveListeningTentacleTargets += 1\n }\n # Cover newer k8s agent and traditional worker-API approach\n elseif ($item.EndPoint.CommunicationStyle -ilike \"Kubernetes*\")\n {\n $targetCount.ActiveKubernetesCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureWebApp\")\n {\n $targetCount.ActiveAzureWebAppCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ssh\")\n {\n $targetCount.ActiveSshTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"Ftp\")\n {\n $targetCount.ActiveFtpTargets += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureCloudService\")\n {\n $targetCount.ActiveAzureCloudServiceCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"AzureServiceFabricCluster\")\n {\n $targetCount.ActiveAzureServiceFabricCount += 1\n }\n elseif ($item.EndPoint.CommunicationStyle -eq \"OfflineDrop\")\n {\n $targetCount.ActiveOfflineDropCount += 1\n }\n else\n {\n $targetCount.ActiveECSClusterCount += 1\n }\n } \n }\n\n if ($currentPage -lt $itemList.NumberOfPages)\n {\n $skipValue = $currentPage * $pageSize\n $currentPage += 1\n\n Write-Host \"The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages. Setting the skip value to $skipValue and re-querying\"\n }\n else\n {\n $haveReachedEndOfList = $true \n }\n }\n \n return $targetCount\n}\n\n# Add support for both TLS 1.2 and TLS 1.3\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 -bor [System.Net.SecurityProtocolType]::Tls13\n\n$ObjectCounts = @{\n TotalProjectCount = 0\n ActiveProjectCount = 0\n DisabledProjectCount = 0\n TotalTenantCount = 0 \n ActiveTenantCount = 0\n DisabledTenantCount = 0\n TargetCount = 0 \n DisabledTargets = 0\n ActiveTargetCount = 0\n UnavailableTargetCount = 0\n ActiveListeningTentacleTargets = 0\n ActivePollingTentacleTargets = 0\n ActiveSshTargets = 0 \n ActiveKubernetesCount = 0\n ActiveAzureWebAppCount = 0\n ActiveAzureServiceFabricCount = 0\n ActiveAzureCloudServiceCount = 0\n ActiveOfflineDropCount = 0 \n ActiveECSClusterCount = 0\n ActiveCloudRegions = 0\n ActiveFtpTargets = 0 \n DisabledListeningTentacleTargets = 0\n DisabledPollingTentacleTargets = 0\n DisabledSshTargets = 0 \n DisabledKubernetesCount = 0\n DisabledAzureWebAppCount = 0\n DisabledAzureServiceFabricCount = 0\n DisabledAzureCloudServiceCount = 0\n DisabledOfflineDropCount = 0 \n DisabledECSClusterCount = 0\n DisabledCloudRegions = 0 \n DisabledFtpTargets = 0 \n WorkerCount = 0\n ListeningTentacleWorkers = 0\n PollingTentacleWorkers = 0\n SshWorkers = 0\n ActiveWorkerCount = 0\n UnavailableWorkerCount = 0\n WindowsLinuxMachineCount = 0\n LicensedTargetCount = $null\n LicensedTargetEntitlement = $null\n LicensedWorkerCount = 0\n LicensedWorkerEntitlement = $null\n LicensedUserCount = 0\n LicensedUserEntitlement = $null \n LicensedProjectCount = 0\n LicensedProjectEntitlement = $null\n LicensedTenantCount = $null\n LicensedTenantEntitlement = $null\n LicensedMachineCount = $null\n LicensedMachineEntitlement = $null\n}\n\nWrite-Host \"Getting Octopus Deploy Version Information\"\n$apiInformation = Invoke-OctopusApi -endPoint \"/api\" -spaceId $null -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n$splitVersion = $apiInformation.Version -split \"\\.\"\n$OctopusMajorVersion = [int]$splitVersion[0]\n$OctopusMinorVersion = [int]$splitVersion[1]\n$isPtm = $false\n\n$hasLicenseSummary = $OctopusMajorVersion -ge 4\n$hasSpaces = $OctopusMajorVersion -ge 2019\n$hasWorkers = ($OctopusMajorVersion -eq 2018 -and $OctopusMinorVersion -ge 7) -or $OctopusMajorVersion -ge 2019\n\n$spaceIdList = @()\nif ($hasSpaces -eq $true)\n{\n $OctopusSpaceList = Invoke-OctopusApi -endPoint \"spaces?skip=0&take=10000\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n foreach ($space in $OctopusSpaceList.Items)\n {\n $spaceIdList += $space.Id\n }\n}\nelse\n{\n $spaceIdList += $null \n}\n\nif ($hasLicenseSummary -eq $true)\n{\n Write-Host \"Checking the license summary for this instance\"\n $licenseSummary = Invoke-OctopusApi -endPoint \"licenses/licenses-current-status\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n\n if ($null -eq (Get-Member -InputObject $licenseSummary -Name \"IsPtm\" -MemberType Properties))\n {\n $isPtm = $false\n }\n elseif($licenseSummary.IsPtm -eq $true)\n {\n $isPtm = $true\n }\n else\n {\n $isPtm = $false\n }\n\n if ($null -ne (Get-Member -InputObject $licenseSummary -Name \"NumberOfMachines\" -MemberType Properties))\n {\n $ObjectCounts.LicensedTargetCount = $licenseSummary.NumberOfMachines\n }\n else\n {\n foreach ($limit in $licenseSummary.Limits)\n {\n if ($limit.Name -eq \"Projects\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Projects\"\n $ObjectCounts.LicensedProjectCount = $limit.CurrentUsage\n $objectCounts.LicensedProjectEntitlement = Get-EffectiveLimit $limit\n }\n\n if ($limit.Name -eq \"Tenants\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Tenants\"\n $ObjectCounts.LicensedTenantCount = $limit.CurrentUsage\n $objectCounts.LicensedTenantEntitlement = Get-EffectiveLimit $limit\n }\n\n if ($limit.Name -eq \"Targets\")\n {\n if ($isPtm -eq $true)\n { \n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Machines\"\n $ObjectCounts.LicensedMachineCount = $limit.CurrentUsage\n $objectCounts.LicensedMachineEntitlement = Get-EffectiveLimit $limit\n }\n else\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Targets\"\n $ObjectCounts.LicensedTargetCount = $limit.CurrentUsage\n $objectCounts.LicensedTargetEntitlement = Get-EffectiveLimit $limit\n } \n }\n\n if ($limit.Name -eq \"Workers\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Workers\"\n $ObjectCounts.LicensedWorkerCount = $limit.CurrentUsage\n $objectCounts.LicensedWorkerEntitlement = Get-EffectiveLimit $limit\n }\n\n if ($limit.Name -eq \"Users\")\n {\n Write-Host \"Your instance is currently using $($limit.CurrentUsage) Users\"\n $ObjectCounts.LicensedUserCount = $limit.CurrentUsage\n $objectCounts.LicensedUserEntitlement = Get-EffectiveLimit $limit\n } \n }\n }\n}\n\n\nforeach ($spaceId in $spaceIdList)\n{ \n Write-Host \"Getting project counts for $spaceId\"\n $projectCounts = Get-OctopusObjectCount -endPoint \"projects\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-Host \"$spaceId has $($projectCounts.ActiveItemCount) active projects.\"\n $ObjectCounts.ActiveProjectCount += $projectCounts.ActiveItemCount\n\n Write-Host \"$spaceId has $($projectCounts.DisabledItemCount) disabled projects.\"\n $ObjectCounts.DisabledProjectCount += $projectCounts.DisabledItemCount\n\n Write-Host \"$spaceId has $($projectCounts.TotalItemCount) total projects.\"\n $ObjectCounts.TotalProjectCount += $projectCounts.TotalItemCount\n\n Write-Host \"Getting tenant counts for $spaceId\"\n $tenantCounts = Get-OctopusObjectCount -endPoint \"tenants\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-Host \"$spaceId has $($tenantCounts.ActiveItemCount) active tenants.\"\n $ObjectCounts.ActiveTenantCount += $tenantCounts.ActiveItemCount\n\n Write-Host \"$spaceId has $($tenantCounts.InactiveItemCount) disabled tenants.\"\n $ObjectCounts.DisabledTenantCount += $tenantCounts.DisabledItemCount\n\n Write-Host \"$spaceId has $($tenantCounts.TotalItemCount) total tenants.\"\n $ObjectCounts.TotalTenantCount += $tenantCounts.TotalItemCount\n \n Write-Host \"Getting Infrastructure Summary for $spaceId\"\n $infrastructureSummary = Get-OctopusDeploymentTargetsCount -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey\n\n Write-host \"$spaceId has $($infrastructureSummary.TargetCount) targets\"\n $ObjectCounts.TargetCount += $infrastructureSummary.TargetCount\n\n Write-Host \"$spaceId has $($infrastructureSummary.ActiveTargetCount) Healthy Targets\"\n $ObjectCounts.ActiveTargetCount += $infrastructureSummary.ActiveTargetCount\n\n Write-Host \"$spaceId has $($infrastructureSummary.DisabledTargets) Disabled Targets\"\n $ObjectCounts.DisabledTargets += $infrastructureSummary.DisabledTargets\n\n Write-Host \"$spaceId has $($infrastructureSummary.UnavailableTargetCount) Unhealthy Targets\"\n $ObjectCounts.UnavailableTargetCount += $infrastructureSummary.UnavailableTargetCount \n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveListeningTentacleTargets) Active Listening Tentacles Targets\"\n $ObjectCounts.ActiveListeningTentacleTargets += $infrastructureSummary.ActiveListeningTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActivePollingTentacleTargets) Active Polling Tentacles Targets\"\n $ObjectCounts.ActivePollingTentacleTargets += $infrastructureSummary.ActivePollingTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveCloudRegions) Active Cloud Region Targets\"\n $ObjectCounts.ActiveCloudRegions += $infrastructureSummary.ActiveCloudRegions\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveOfflineDropCount) Active Offline Packages\"\n $ObjectCounts.ActiveOfflineDropCount += $infrastructureSummary.ActiveOfflineDropCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Active SSH Targets\"\n $ObjectCounts.ActiveSshTargets += $infrastructureSummary.ActiveSshTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Active Kubernetes Targets\"\n $ObjectCounts.ActiveKubernetesCount += $infrastructureSummary.ActiveKubernetesCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureWebAppCount) Active Azure Web App Targets\"\n $ObjectCounts.ActiveAzureWebAppCount += $infrastructureSummary.ActiveAzureWebAppCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureServiceFabricCount) Active Azure Service Fabric Cluster Targets\"\n $ObjectCounts.ActiveAzureServiceFabricCount += $infrastructureSummary.ActiveAzureServiceFabricCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveAzureCloudServiceCount) Active (Legacy) Azure Cloud Service Targets\"\n $ObjectCounts.ActiveAzureCloudServiceCount += $infrastructureSummary.ActiveAzureCloudServiceCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveECSClusterCount) Active ECS Cluster Targets\"\n $ObjectCounts.ActiveECSClusterCount += $infrastructureSummary.ActiveECSClusterCount\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveFtpTargets) Active FTP Targets\"\n $ObjectCounts.ActiveFtpTargets += $infrastructureSummary.ActiveFtpTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledListeningTentacleTargets) Disabled Listening Tentacles Targets\"\n $ObjectCounts.DisabledListeningTentacleTargets += $infrastructureSummary.DisabledListeningTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledPollingTentacleTargets) Disabled Polling Tentacles Targets\"\n $ObjectCounts.DisabledPollingTentacleTargets += $infrastructureSummary.DisabledPollingTentacleTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledCloudRegions) Disabled Cloud Region Targets\"\n $ObjectCounts.DisabledCloudRegions += $infrastructureSummary.DisabledCloudRegions\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledOfflineDropCount) Disabled Offline Packages\"\n $ObjectCounts.DisabledOfflineDropCount += $infrastructureSummary.DisabledOfflineDropCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledSshTargets) Disabled SSH Targets\"\n $ObjectCounts.DisabledSshTargets += $infrastructureSummary.DisabledSshTargets\n\n Write-host \"$spaceId has $($infrastructureSummary.ActiveSshTargets) Disabled Kubernetes Targets\"\n $ObjectCounts.DisabledKubernetesCount += $infrastructureSummary.DisabledKubernetesCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureWebAppCount) Disabled Azure Web App Targets\"\n $ObjectCounts.DisabledAzureWebAppCount += $infrastructureSummary.DisabledAzureWebAppCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureServiceFabricCount) Disabled Azure Service Fabric Cluster Targets\"\n $ObjectCounts.DisabledAzureServiceFabricCount += $infrastructureSummary.DisabledAzureServiceFabricCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledAzureCloudServiceCount) Disabled (Legacy) Azure Cloud Service Targets\"\n $ObjectCounts.DisabledAzureCloudServiceCount += $infrastructureSummary.DisabledAzureCloudServiceCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledECSClusterCount) Disabled ECS Cluster Targets\"\n $ObjectCounts.DisabledECSClusterCount += $infrastructureSummary.DisabledECSClusterCount\n\n Write-host \"$spaceId has $($infrastructureSummary.DisabledFtpTargets) Disabled FTP Targets\"\n $ObjectCounts.DisabledFtpTargets += $infrastructureSummary.DisabledFtpTargets\n\n if ($hasWorkers -eq $true)\n {\n Write-Host \"Getting worker information for $spaceId\"\n $workerPoolSummary = Invoke-OctopusApi -endPoint \"workerpools/summary\" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey \n\n Write-host \"$spaceId has $($workerPoolSummary.TotalMachines) Workers\"\n $ObjectCounts.WorkerCount += $workerPoolSummary.TotalMachines\n\n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Healthy) Healthy Workers\"\n $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Healthy\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.HasWarnings) Healthy with Warning Workers\"\n $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.HasWarnings\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unhealthy) Unhealthy Workers\"\n $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unhealthy\n \n Write-Host \"$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unknown) Workers with a Status of Unknown\"\n $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unknown\n \n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentaclePassive) Listening Tentacles Workers\"\n $ObjectCounts.ListeningTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentaclePassive\n\n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) Polling Tentacles Workers\"\n $ObjectCounts.PollingTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentacleActive \n\n if ($null -ne (Get-Member -InputObject $workerPoolSummary.MachineEndpointSummaries -Name \"Ssh\" -MemberType Properties))\n {\n Write-host \"$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) SSH Targets Workers\"\n $ObjectCounts.SshWorkers += $workerPoolSummary.MachineEndpointSummaries.Ssh\n }\n }\n}\n\nWrite-Host \"Calculating Windows and Linux Machine Count\"\n$ObjectCounts.WindowsLinuxMachineCount = $ObjectCounts.ActivePollingTentacleTargets + $ObjectCounts.ActiveListeningTentacleTargets + $ObjectCounts.ActiveSshTargets\n\nif ($hasLicenseSummary -eq $false)\n{\n $ObjectCounts.LicensedTargetCount = $ObjectCounts.TargetCount - $ObjectCounts.ActiveCloudRegions - $ObjectCounts.DisabledTargets \n}\n\n# Get node information\n$nodeInfo = Invoke-OctopusApi -endPoint \"octopusservernodes\" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey\n \n$text = @\"\nThe item counts are as follows:\n`tInstance ID: $($apiInformation.InstallationId)\n`tServer Version: $($apiInformation.Version)\n`tNumber of Server Nodes: $($nodeInfo.TotalResults)\n`tEntitlement Usage\n$(if ($isPtm) {\n\"`t`tLicensed Project Count: $($ObjectCounts.LicensedProjectCount) $($ObjectCounts.LicensedProjectEntitlement)\n`t`tLicensed Tenant Count: $($ObjectCounts.LicensedTenantCount) $($ObjectCounts.LicensedTenantEntitlement)\n`t`tLicensed Machine Count: $($ObjectCounts.LicensedMachineCount) $($ObjectCounts.LicensedMachineEntitlement)\"\n} else {\n\"`t`tLicensed Target Count: $($ObjectCounts.LicensedTargetCount) $($ObjectCounts.LicensedTargetEntitlement)\"\n})\n`t`tLicensed User Count: $($ObjectCounts.LicensedUserCount) $($ObjectCounts.LicensedUserEntitlement)\n`t`tLicensed Worker Count: $($ObjectCounts.LicensedWorkerCount) $($ObjectCounts.LicensedWorkerEntitlement)\n`tProject Count: $($ObjectCounts.TotalProjectCount)\n`t`tActive Project Count (Counted against entitlements for all licenses): $($ObjectCounts.ActiveProjectCount)\n`t`tDisabled Project Count (Counted against entitlements for free licenses): $($ObjectCounts.DisabledProjectCount)\n`tTenant Count: $($ObjectCounts.TotalTenantCount)\n`t`tActive Tenant Count (Counted against entitlements for all licenses): $($ObjectCounts.ActiveTenantCount)\n`t`tDisabled Tenant Count (Counted against entitlements for free licenses): $($ObjectCounts.DisabledTenantCount)\n`tMachine Counts (Active Linux and Windows Tentacles and SSH Connections): $($ObjectCounts.WindowsLinuxMachineCount)\n`tDeployment Target Count: $($ObjectCounts.TargetCount)\n`t`tActive and Available Targets: $($ObjectCounts.ActiveTargetCount)\n`t`tActive but Unavailable Targets: $($ObjectCounts.UnavailableTargetCount)\n`t`tActive Target Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.ActiveListeningTentacleTargets)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.ActivePollingTentacleTargets)\n`t`t`tSSH Target Count: $($ObjectCounts.ActiveSshTargets)\n`t`t`tKubernetes Target Count: $($ObjectCounts.ActiveKubernetesCount)\n`t`t`tAzure Web App Target Count: $($ObjectCounts.ActiveAzureWebAppCount)\n`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.ActiveAzureServiceFabricCount)\n`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.ActiveAzureCloudServiceCount)\n`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.ActiveECSClusterCount)\n`t`t`tOffline Target Count: $($ObjectCounts.ActiveOfflineDropCount)\n`t`t`tCloud Region Target Count: $($ObjectCounts.ActiveCloudRegions)\n`t`t`tFtp Target Count: $($ObjectCounts.ActiveFtpTargets)\n`t`tDisabled Targets Targets: $($ObjectCounts.DisabledTargets)\n`t`tDisabled Target Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.DisabledListeningTentacleTargets)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.DisabledPollingTentacleTargets)\n`t`t`tSSH Target Count: $($ObjectCounts.DisabledSshTargets)\n`t`t`tKubernetes Target Count: $($ObjectCounts.DisabledKubernetesCount)\n`t`t`tAzure Web App Target Count: $($ObjectCounts.DisabledAzureWebAppCount)\n`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.DisabledAzureServiceFabricCount)\n`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.DisabledAzureCloudServiceCount)\n`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.DisabledECSClusterCount)\n`t`t`tOffline Target Count: $($ObjectCounts.DisabledOfflineDropCount)\n`t`t`tCloud Region Target Count: $($ObjectCounts.DisabledCloudRegions)\n`t`t`tFtp Target Count: $($ObjectCounts.DisabledFtpTargets)\n`tWorker Count: $($ObjectCounts.WorkerCount)\n`t`tActive Workers: $($ObjectCounts.ActiveWorkerCount)\n`t`tUnavailable Workers: $($ObjectCounts.UnavailableWorkerCount)\n`t`tWorker Breakdown\n`t`t`tListening Tentacle Target Count: $($ObjectCounts.ListeningTentacleWorkers)\n`t`t`tPolling Tentacle Target Count: $($ObjectCounts.PollingTentacleWorkers)\n`t`t`tSSH Target Count: $($ObjectCounts.SshWorkers)\n\"@\n\nWrite-Host $text\n$text > octopus-usage.txt\nNew-OctopusArtifact \"$($PWD)/octopus-usage.txt\"" }, "Parameters": [ { @@ -36,8 +36,8 @@ ], "StepPackageId": "Octopus.Script", "$Meta": { - "ExportedAt": "2024-02-07T15:56:59.084Z", - "OctopusVersion": "2024.1.10309", + "ExportedAt": "2025-08-26T10:35:22.719Z", + "OctopusVersion": "2025.3.9781", "Type": "ActionTemplate" }, "Author": "ryanrousseau",