Get Octopus Usage

Octopus.Script exported 2024-02-07 by harrisonmeister belongs to ‘Octopus’ category.

Step template to gather Octopus usage details across spaces. The results will be output to the log and also as a downloadable artifact.

To 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.

Required: An API Key for a user or service account that has read access in every space on the instance.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Octopus Server URI

GetUsage.Octopus.ServerUri = #{Octopus.Web.ServerUri}

The URI of the Octopus Server. For use on the same server, #{Octopus.Web.ServerUri} will work.

Octopus Server API Key

GetUsage.Octopus.ApiKey =

The API key with read permissions to all spaces in the instance being inspected.

Script body

Steps based on this template will execute the following PowerShell script.

$OctopusDeployUrl = $OctopusParameters["GetUsage.Octopus.ServerUri"]
$OctopusDeployApiKey = $OctopusParameters["GetUsage.Octopus.ApiKey"]

function Get-OctopusUrl
{
    param (
        $EndPoint,
        $SpaceId,
        $OctopusUrl
    )

    $octopusUrlToUse = $OctopusUrl
    if ($OctopusUrl.EndsWith("/"))
    {
        $octopusUrlToUse = $OctopusUrl.Substring(0, $OctopusUrl.Length - 1)
    }

    if ($EndPoint -match "/api")
    {
        if (!$EndPoint.StartsWith("/api"))
        {
            $EndPoint = $EndPoint.Substring($EndPoint.IndexOf("/api"))
        }

        return "$octopusUrlToUse$EndPoint"
    }

    if ([string]::IsNullOrWhiteSpace($SpaceId))
    {
        return "$octopusUrlToUse/api/$EndPoint"
    }

    return "$octopusUrlToUse/api/$spaceId/$EndPoint"
}

function Invoke-OctopusApi
{
    param
    (
        $endPoint,
        $spaceId,
        $octopusUrl,        
        $apiKey
    )    

    try
    {        
        $url = Get-OctopusUrl -EndPoint $endPoint -SpaceId $spaceId -OctopusUrl $octopusUrl

        Write-Host "Invoking $url"
        return Invoke-RestMethod -Method Get -Uri $url -Headers @{"X-Octopus-ApiKey" = "$apiKey" } -ContentType 'application/json; charset=utf-8' -TimeoutSec 60        
    }
    catch
    {
        Write-Host "There was an error making a Get call to the $url.  Please check that for more information." -ForegroundColor Red

        if ($null -ne $_.Exception.Response)
        {
            if ($_.Exception.Response.StatusCode -eq 401)
            {
                Write-Host "Unauthorized error returned from $url, please verify API key and try again" -ForegroundColor Red
            }
            elseif ($_.ErrorDetails.Message)
            {                
                Write-Host -Message "Error calling $url StatusCode: $($_.Exception.Response) $($_.ErrorDetails.Message)" -ForegroundColor Red
                Write-Host $_.Exception -ForegroundColor Red
            }            
            else 
            {
                Write-Host $_.Exception -ForegroundColor Red
            }
        }
        else
        {
            Write-Host $_.Exception -ForegroundColor Red
        }

        Write-Host "Stopping the script from proceeding" -ForegroundColor Red
        exit 1
    }    
}

function Get-OctopusObjectCount
{
    param
    (
        $endPoint,
        $spaceId,
        $octopusUrl,        
        $apiKey
    )

    $itemCount = 0
    $currentPage = 1
    $pageSize = 50
    $skipValue = 0
    $haveReachedEndOfList = $false

    while ($haveReachedEndOfList -eq $false)
    {
        $currentEndPoint = "$($endPoint)?skip=$skipValue&take=$pageSize"

        $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey

        foreach ($item in $itemList.Items)
        {
            if ($null -ne (Get-Member -InputObject $item -Name "IsDisabled" -MemberType Properties))
            {          
                if ($item.IsDisabled -eq $false)
                {
                    $itemCount += 1
                }
            }
            else 
            {
                $itemCount += 1    
            }
        }

        if ($currentPage -lt $itemList.NumberOfPages)
        {
            $skipValue = $currentPage * $pageSize
            $currentPage += 1

            Write-Host "The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages.  Setting the skip value to $skipValue and re-querying"
        }
        else
        {
            $haveReachedEndOfList = $true    
        }
    }
    
    return $itemCount
}

function Get-OctopusDeploymentTargetsCount
{
    param
    (
        $spaceId,
        $octopusUrl,        
        $apiKey
    )

    $targetCount = @{
        TargetCount = 0 
        ActiveTargetCount = 0
        UnavailableTargetCount = 0        
        DisabledTargets = 0
        ActiveListeningTentacleTargets = 0
        ActivePollingTentacleTargets = 0
        ActiveSshTargets = 0        
        ActiveKubernetesCount = 0
        ActiveAzureWebAppCount = 0
        ActiveAzureServiceFabricCount = 0
        ActiveAzureCloudServiceCount = 0
        ActiveOfflineDropCount = 0    
        ActiveECSClusterCount = 0
        ActiveCloudRegions = 0  
        ActiveFtpTargets = 0
        DisabledListeningTentacleTargets = 0
        DisabledPollingTentacleTargets = 0
        DisabledSshTargets = 0        
        DisabledKubernetesCount = 0
        DisabledAzureWebAppCount = 0
        DisabledAzureServiceFabricCount = 0
        DisabledAzureCloudServiceCount = 0
        DisabledOfflineDropCount = 0    
        DisabledECSClusterCount = 0
        DisabledCloudRegions = 0  
        DisabledFtpTargets = 0            
    }

    $currentPage = 1
    $pageSize = 50
    $skipValue = 0
    $haveReachedEndOfList = $false

    while ($haveReachedEndOfList -eq $false)
    {
        $currentEndPoint = "machines?skip=$skipValue&take=$pageSize"

        $itemList = Invoke-OctopusApi -endPoint $currentEndPoint -spaceId $spaceId -octopusUrl $octopusUrl -apiKey $apiKey

        foreach ($item in $itemList.Items)
        {
            $targetCount.TargetCount += 1

            if ($item.IsDisabled -eq $true)
            {
                $targetCount.DisabledTargets += 1                  

                if ($item.EndPoint.CommunicationStyle -eq "None")
                {
                    $targetCount.DisabledCloudRegions += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "TentacleActive")
                {
                    $targetCount.DisabledPollingTentacleTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "TentaclePassive")
                {
                    $targetCount.DisabledListeningTentacleTargets += 1
                }
                # Cover newer k8s agent and traditional worker-API approach
                elseif ($item.EndPoint.CommunicationStyle -ilike "Kubernetes*")
                {
                    $targetCount.DisabledKubernetesCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureWebApp")
                {
                    $targetCount.DisabledAzureWebAppCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "Ssh")
                {
                    $targetCount.DisabledSshTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "Ftp")
                {
                    $targetCount.DisabledFtpTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureCloudService")
                {
                    $targetCount.DisabledAzureCloudServiceCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureServiceFabricCluster")
                {
                    $targetCount.DisabledAzureServiceFabricCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "OfflineDrop")
                {
                    $targetCount.DisabledOfflineDropCount += 1
                }
                else
                {
                    $targetCount.DisabledECSClusterCount += 1
                }
            }
            else
            {
                if ($item.HealthStatus -eq "Healthy" -or $item.HealthStatus -eq "HealthyWithWarnings")
                {
                    $targetCount.ActiveTargetCount += 1
                }
                else
                {
                    $targetCount.UnavailableTargetCount += 1    
                }

                if ($item.EndPoint.CommunicationStyle -eq "None")
                {
                    $targetCount.ActiveCloudRegions += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "TentacleActive")
                {
                    $targetCount.ActivePollingTentacleTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "TentaclePassive")
                {
                    $targetCount.ActiveListeningTentacleTargets += 1
                }
                # Cover newer k8s agent and traditional worker-API approach
                elseif ($item.EndPoint.CommunicationStyle -ilike "Kubernetes*")
                {
                    $targetCount.ActiveKubernetesCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureWebApp")
                {
                    $targetCount.ActiveAzureWebAppCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "Ssh")
                {
                    $targetCount.ActiveSshTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "Ftp")
                {
                    $targetCount.ActiveFtpTargets += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureCloudService")
                {
                    $targetCount.ActiveAzureCloudServiceCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "AzureServiceFabricCluster")
                {
                    $targetCount.ActiveAzureServiceFabricCount += 1
                }
                elseif ($item.EndPoint.CommunicationStyle -eq "OfflineDrop")
                {
                    $targetCount.ActiveOfflineDropCount += 1
                }
                else
                {
                    $targetCount.ActiveECSClusterCount += 1
                }
            }                                
        }

        if ($currentPage -lt $itemList.NumberOfPages)
        {
            $skipValue = $currentPage * $pageSize
            $currentPage += 1

            Write-Host "The endpoint $endpoint has reported there are $($itemList.NumberOfPages) pages.  Setting the skip value to $skipValue and re-querying"
        }
        else
        {
            $haveReachedEndOfList = $true    
        }
    }
    
    return $targetCount
}

$ObjectCounts = @{
    ProjectCount = 0
    TenantCount = 0        
    TargetCount = 0 
    DisabledTargets = 0
    ActiveTargetCount = 0
    UnavailableTargetCount = 0
    ActiveListeningTentacleTargets = 0
    ActivePollingTentacleTargets = 0
    ActiveSshTargets = 0        
    ActiveKubernetesCount = 0
    ActiveAzureWebAppCount = 0
    ActiveAzureServiceFabricCount = 0
    ActiveAzureCloudServiceCount = 0
    ActiveOfflineDropCount = 0    
    ActiveECSClusterCount = 0
    ActiveCloudRegions = 0
    ActiveFtpTargets = 0 
    DisabledListeningTentacleTargets = 0
    DisabledPollingTentacleTargets = 0
    DisabledSshTargets = 0        
    DisabledKubernetesCount = 0
    DisabledAzureWebAppCount = 0
    DisabledAzureServiceFabricCount = 0
    DisabledAzureCloudServiceCount = 0
    DisabledOfflineDropCount = 0    
    DisabledECSClusterCount = 0
    DisabledCloudRegions = 0  
    DisabledFtpTargets = 0             
    WorkerCount = 0
    ListeningTentacleWorkers = 0
    PollingTentacleWorkers = 0
    SshWorkers = 0
    ActiveWorkerCount = 0
    UnavailableWorkerCount = 0
    WindowsLinuxAgentCount = 0
    LicensedTargetCount = 0
    LicensedWorkerCount = 0
}

Write-Host "Getting Octopus Deploy Version Information"
$apiInformation = Invoke-OctopusApi -endPoint "/api" -spaceId $null -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey
$splitVersion = $apiInformation.Version -split "\."
$OctopusMajorVersion = [int]$splitVersion[0]
$OctopusMinorVersion = [int]$splitVersion[1]

$hasLicenseSummary = $OctopusMajorVersion -ge 4
$hasSpaces = $OctopusMajorVersion -ge 2019
$hasWorkers = ($OctopusMajorVersion -eq 2018 -and $OctopusMinorVersion -ge 7) -or $OctopusMajorVersion -ge 2019

$spaceIdList = @()
if ($hasSpaces -eq $true)
{
    $OctopusSpaceList = Invoke-OctopusApi -endPoint "spaces?skip=0&take=10000" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey
    foreach ($space in $OctopusSpaceList.Items)
    {
        $spaceIdList += $space.Id
    }
}
else
{
    $spaceIdList += $null    
}

if ($hasLicenseSummary -eq $true)
{
    Write-Host "Checking the license summary for this instance"
    $licenseSummary = Invoke-OctopusApi -endPoint "licenses/licenses-current-status" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey

    if ($null -ne (Get-Member -InputObject $licenseSummary -Name "NumberOfMachines" -MemberType Properties))
    {
        $ObjectCounts.LicensedTargetCount = $licenseSummary.NumberOfMachines
    }
    else
    {
        foreach ($limit in $licenseSummary.Limits)
        {
            if ($limit.Name -eq "Targets")
            {
                Write-Host "Your instance is currently using $($limit.CurrentUsage) Targets"
                $ObjectCounts.LicensedTargetCount = $limit.CurrentUsage
            }

            if ($limit.Name -eq "Workers")
            {
                Write-Host "Your instance is currently using $($limit.CurrentUsage) Workers"
                $ObjectCounts.LicensedWorkerCount = $limit.CurrentUsage
            }
        }
    }
}


foreach ($spaceId in $spaceIdList)
{    
    Write-Host "Getting project counts for $spaceId"
    $activeProjectCount = Get-OctopusObjectCount -endPoint "projects" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey

    Write-Host "$spaceId has $activeProjectCount active projects."
    $ObjectCounts.ProjectCount += $activeProjectCount

    Write-Host "Getting tenant counts for $spaceId"
    $activeTenantCount = Get-OctopusObjectCount -endPoint "tenants" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey

    Write-Host "$spaceId has $activeTenantCount tenants."
    $ObjectCounts.TenantCount += $activeTenantCount

    Write-Host "Getting Infrastructure Summary for $spaceId"
    $infrastructureSummary = Get-OctopusDeploymentTargetsCount -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey

    Write-host "$spaceId has $($infrastructureSummary.TargetCount) targets"
    $ObjectCounts.TargetCount += $infrastructureSummary.TargetCount

    Write-Host "$spaceId has $($infrastructureSummary.ActiveTargetCount) Healthy Targets"
    $ObjectCounts.ActiveTargetCount += $infrastructureSummary.ActiveTargetCount

    Write-Host "$spaceId has $($infrastructureSummary.DisabledTargets) Disabled Targets"
    $ObjectCounts.DisabledTargets += $infrastructureSummary.DisabledTargets

    Write-Host "$spaceId has $($infrastructureSummary.UnavailableTargetCount) Unhealthy Targets"
    $ObjectCounts.UnavailableTargetCount += $infrastructureSummary.UnavailableTargetCount    

    Write-host "$spaceId has $($infrastructureSummary.ActiveListeningTentacleTargets) Active Listening Tentacles Targets"
    $ObjectCounts.ActiveListeningTentacleTargets += $infrastructureSummary.ActiveListeningTentacleTargets

    Write-host "$spaceId has $($infrastructureSummary.ActivePollingTentacleTargets) Active Polling Tentacles Targets"
    $ObjectCounts.ActivePollingTentacleTargets += $infrastructureSummary.ActivePollingTentacleTargets

    Write-host "$spaceId has $($infrastructureSummary.ActiveCloudRegions) Active Cloud Region Targets"
    $ObjectCounts.ActiveCloudRegions += $infrastructureSummary.ActiveCloudRegions

    Write-host "$spaceId has $($infrastructureSummary.ActiveOfflineDropCount) Active Offline Packages"
    $ObjectCounts.ActiveOfflineDropCount += $infrastructureSummary.ActiveOfflineDropCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveSshTargets) Active SSH Targets"
    $ObjectCounts.ActiveSshTargets += $infrastructureSummary.ActiveSshTargets
    
    Write-host "$spaceId has $($infrastructureSummary.ActiveSshTargets) Active Kubernetes Targets"
    $ObjectCounts.ActiveKubernetesCount += $infrastructureSummary.ActiveKubernetesCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveAzureWebAppCount) Active Azure Web App Targets"
    $ObjectCounts.ActiveAzureWebAppCount += $infrastructureSummary.ActiveAzureWebAppCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveAzureServiceFabricCount) Active Azure Service Fabric Cluster Targets"
    $ObjectCounts.ActiveAzureServiceFabricCount += $infrastructureSummary.ActiveAzureServiceFabricCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveAzureCloudServiceCount) Active (Legacy) Azure Cloud Service Targets"
    $ObjectCounts.ActiveAzureCloudServiceCount += $infrastructureSummary.ActiveAzureCloudServiceCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveECSClusterCount) Active ECS Cluster Targets"
    $ObjectCounts.ActiveECSClusterCount += $infrastructureSummary.ActiveECSClusterCount

    Write-host "$spaceId has $($infrastructureSummary.ActiveFtpTargets) Active FTP Targets"
    $ObjectCounts.ActiveFtpTargets += $infrastructureSummary.ActiveFtpTargets

    Write-host "$spaceId has $($infrastructureSummary.DisabledListeningTentacleTargets) Disabled Listening Tentacles Targets"
    $ObjectCounts.DisabledListeningTentacleTargets += $infrastructureSummary.DisabledListeningTentacleTargets

    Write-host "$spaceId has $($infrastructureSummary.DisabledPollingTentacleTargets) Disabled Polling Tentacles Targets"
    $ObjectCounts.DisabledPollingTentacleTargets += $infrastructureSummary.DisabledPollingTentacleTargets

    Write-host "$spaceId has $($infrastructureSummary.DisabledCloudRegions) Disabled Cloud Region Targets"
    $ObjectCounts.DisabledCloudRegions += $infrastructureSummary.DisabledCloudRegions

    Write-host "$spaceId has $($infrastructureSummary.DisabledOfflineDropCount) Disabled Offline Packages"
    $ObjectCounts.DisabledOfflineDropCount += $infrastructureSummary.DisabledOfflineDropCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledSshTargets) Disabled SSH Targets"
    $ObjectCounts.DisabledSshTargets += $infrastructureSummary.DisabledSshTargets
    
    Write-host "$spaceId has $($infrastructureSummary.ActiveSshTargets) Disabled Kubernetes Targets"
    $ObjectCounts.DisabledKubernetesCount += $infrastructureSummary.DisabledKubernetesCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledAzureWebAppCount) Disabled Azure Web App Targets"
    $ObjectCounts.DisabledAzureWebAppCount += $infrastructureSummary.DisabledAzureWebAppCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledAzureServiceFabricCount) Disabled Azure Service Fabric Cluster Targets"
    $ObjectCounts.DisabledAzureServiceFabricCount += $infrastructureSummary.DisabledAzureServiceFabricCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledAzureCloudServiceCount) Disabled (Legacy) Azure Cloud Service Targets"
    $ObjectCounts.DisabledAzureCloudServiceCount += $infrastructureSummary.DisabledAzureCloudServiceCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledECSClusterCount) Disabled ECS Cluster Targets"
    $ObjectCounts.DisabledECSClusterCount += $infrastructureSummary.DisabledECSClusterCount

    Write-host "$spaceId has $($infrastructureSummary.DisabledFtpTargets) Disabled FTP Targets"
    $ObjectCounts.DisabledFtpTargets += $infrastructureSummary.DisabledFtpTargets

    if ($hasWorkers -eq $true)
    {
        Write-Host "Getting worker information for $spaceId"
        $workerPoolSummary = Invoke-OctopusApi -endPoint "workerpools/summary" -spaceId $spaceId -octopusUrl $OctopusDeployUrl -apiKey $OctopusDeployApiKey 

        Write-host "$spaceId has $($workerPoolSummary.TotalMachines) Workers"
        $ObjectCounts.WorkerCount += $workerPoolSummary.TotalMachines

        Write-Host "$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Healthy) Healthy Workers"
        $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Healthy
    
        Write-Host "$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.HasWarnings) Healthy with Warning Workers"
        $ObjectCounts.ActiveWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.HasWarnings
    
        Write-Host "$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unhealthy) Unhealthy Workers"
        $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unhealthy
    
        Write-Host "$spaceId has $($workerPoolSummary.MachineHealthStatusSummaries.Unknown) Workers with a Status of Unknown"
        $ObjectCounts.UnavailableWorkerCount += $workerPoolSummary.MachineHealthStatusSummaries.Unknown
        
        Write-host "$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentaclePassive) Listening Tentacles Workers"
        $ObjectCounts.ListeningTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentaclePassive

        Write-host "$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) Polling Tentacles Workers"
        $ObjectCounts.PollingTentacleWorkers += $workerPoolSummary.MachineEndpointSummaries.TentacleActive        

        if ($null -ne (Get-Member -InputObject $workerPoolSummary.MachineEndpointSummaries -Name "Ssh" -MemberType Properties))
        {
            Write-host "$spaceId has $($workerPoolSummary.MachineEndpointSummaries.TentacleActive) SSH Targets Workers"
            $ObjectCounts.SshWorkers += $workerPoolSummary.MachineEndpointSummaries.Ssh
        }
    }
}

Write-Host "Calculating Windows and Linux Agent Count"
$ObjectCounts.WindowsLinuxAgentCount = $ObjectCounts.ActivePollingTentacleTargets + $ObjectCounts.ActiveListeningTentacleTargets + $ObjectCounts.ActiveSshTargets

if ($hasLicenseSummary -eq $false)
{
    $ObjectCounts.LicensedTargetCount = $ObjectCounts.TargetCount - $ObjectCounts.ActiveCloudRegions - $ObjectCounts.DisabledTargets    
}


# Get node information
$nodeInfo = Invoke-OctopusApi -endPoint "octopusservernodes" -octopusUrl $OctopusDeployUrl -spaceId $null -apiKey $OctopusDeployApiKey

$text = @"
The item counts are as follows:
`tInstance ID: $($apiInformation.InstallationId)
`tServer Version: $($apiInformation.Version)
`tNumber of Server Nodes: $($nodeInfo.TotalResults)
`tLicensed Target Count: $($ObjectCounts.LicensedTargetCount) (these are active targets de-duped across the instance if running a modern version of Octopus)
`tProject Count: $($ObjectCounts.ProjectCount)
`tTenant Count: $($ObjectCounts.TenantCount)
`tAgent Counts: $($ObjectCounts.WindowsLinuxAgentCount)
`tDeployment Target Count: $($ObjectCounts.TargetCount)
`t`tActive and Available Targets: $($ObjectCounts.ActiveTargetCount)
`t`tActive but Unavailable Targets: $($ObjectCounts.UnavailableTargetCount)
`t`tActive Target Breakdown
`t`t`tListening Tentacle Target Count: $($ObjectCounts.ActiveListeningTentacleTargets)
`t`t`tPolling Tentacle Target Count: $($ObjectCounts.ActivePollingTentacleTargets)
`t`t`tSSH Target Count: $($ObjectCounts.ActiveSshTargets)
`t`t`tKubernetes Target Count: $($ObjectCounts.ActiveKubernetesCount)
`t`t`tAzure Web App Target Count: $($ObjectCounts.ActiveAzureWebAppCount)
`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.ActiveAzureServiceFabricCount)
`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.ActiveAzureCloudServiceCount)
`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.ActiveECSClusterCount)
`t`t`tOffline Target Count: $($ObjectCounts.ActiveOfflineDropCount)
`t`t`tCloud Region Target Count: $($ObjectCounts.ActiveCloudRegions)
`t`t`tFtp Target Count: $($ObjectCounts.ActiveFtpTargets)
`t`tDisabled Targets Targets: $($ObjectCounts.DisabledTargets)
`t`tDisabled Target Breakdown
`t`t`tListening Tentacle Target Count: $($ObjectCounts.DisabledListeningTentacleTargets)
`t`t`tPolling Tentacle Target Count: $($ObjectCounts.DisabledPollingTentacleTargets)
`t`t`tSSH Target Count: $($ObjectCounts.DisabledSshTargets)
`t`t`tKubernetes Target Count: $($ObjectCounts.DisabledKubernetesCount)
`t`t`tAzure Web App Target Count: $($ObjectCounts.DisabledAzureWebAppCount)
`t`t`tAzure Service Fabric Cluster Target Count: $($ObjectCounts.DisabledAzureServiceFabricCount)
`t`t`tAzure (Legacy) Cloud Service Target Count: $($ObjectCounts.DisabledAzureCloudServiceCount)
`t`t`tAWS ECS Cluster Target Count: $($ObjectCounts.DisabledECSClusterCount)
`t`t`tOffline Target Count: $($ObjectCounts.DisabledOfflineDropCount)
`t`t`tCloud Region Target Count: $($ObjectCounts.DisabledCloudRegions)
`t`t`tFtp Target Count: $($ObjectCounts.DisabledFtpTargets)
`tWorker Count: $($ObjectCounts.WorkerCount)
`t`tActive Workers: $($ObjectCounts.ActiveWorkerCount)
`t`tUnavailable Workers: $($ObjectCounts.UnavailableWorkerCount)
`t`tWorker Breakdown
`t`t`tListening Tentacle Target Count: $($ObjectCounts.ListeningTentacleWorkers)
`t`t`tPolling Tentacle Target Count: $($ObjectCounts.PollingTentacleWorkers)
`t`t`tSSH Target Count: $($ObjectCounts.SshWorkers)
"@

Write-Host $text
$text > octopus-usage.txt
New-OctopusArtifact "$($PWD)/octopus-usage.txt"

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "f70f16a9-7bf3-448c-9532-e5a69364581d",
  "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.",
  "Version": 4,
  "ExportedAt": "2024-02-07T15:56:59.084Z",
  "ActionType": "Octopus.Script",
  "Author": "harrisonmeister",
  "Packages": [],
  "Parameters": [
    {
      "Id": "afe5d565-c87a-481d-a9d1-005a32763b9e",
      "Name": "GetUsage.Octopus.ServerUri",
      "Label": "Octopus Server URI",
      "HelpText": "The URI of the Octopus Server. For use on the same server, #{Octopus.Web.ServerUri} will work.",
      "DefaultValue": "#{Octopus.Web.ServerUri}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "51bfc97d-d174-452d-a852-0e120cc4cba8",
      "Name": "GetUsage.Octopus.ApiKey",
      "Label": "Octopus Server API Key",
      "HelpText": "The API key with read permissions to all spaces in the instance being inspected.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    }
  ],
  "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\""
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/octopus-get-octopus-usage.json",
  "Website": "/step-templates/f70f16a9-7bf3-448c-9532-e5a69364581d",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Wednesday, February 7, 2024