functions/Get-WUGDeviceGroup.ps1

<#
.SYNOPSIS
Retrieves device groups and their configuration from WhatsUp Gold.
 
.DESCRIPTION
The `Get-WUGDeviceGroup` function retrieves device groups and their configuration from WhatsUp Gold using the REST API. It allows you to:
 
- Retrieve specific device groups by their `GroupId` using the `/api/v1/device-groups/{groupId}` endpoint.
- Search for device groups based on criteria such as name (`SearchValue`), group type (`GroupType`), and view level (`View`) using the `/api/v1/device-groups/-` endpoint.
- Retrieve a device group definition using the `/api/v1/device-groups/{groupId}/definition` endpoint.
- Retrieve child groups using the `/api/v1/device-groups/{groupId}/children` endpoint.
- Retrieve group status using the `/api/v1/device-groups/{groupId}/status` endpoint.
- Retrieve devices in a group using the `/api/v1/device-groups/{groupId}/devices/-` endpoint.
- Retrieve device template config using the `/api/v1/device-groups/{groupId}/devices/-/config/template` endpoint.
- Retrieve device credentials using the `/api/v1/device-groups/{groupId}/devices/-/credentials` endpoint.
 
The function supports pagination and handles large result sets efficiently.
 
.PARAMETER GroupId
Specifies one or more GroupId(s) of the device groups to retrieve. When this parameter is used, the function retrieves the specified device groups using the `/api/v1/device-groups/{groupId}` endpoint. This parameter belongs to the 'ByGroupId' parameter set.
 
.PARAMETER SearchValue
Specifies a search value to filter device groups by name. The function uses the `/api/v1/device-groups/-` endpoint to search for device groups whose names contain the specified value. This parameter belongs to the 'BySearch' parameter set.
 
.PARAMETER View
Specifies the level of detail for the device group information returned. Valid options are:
 
- `summary`: Returns basic information about the device groups.
- `detail`: Returns detailed information, including group type, monitor state, and device counts.
 
Default value is `detail`. This parameter is available in both parameter sets.
 
.PARAMETER GroupType
Specifies the type of device groups to retrieve. Valid options are:
 
- `all`: Retrieves all types of device groups.
- `static_group`: Retrieves static device groups.
- `dynamic_group`: Retrieves dynamic device groups.
- `layer2`: Retrieves Layer 2 device groups.
 
Default value is `all`. This parameter belongs to the 'BySearch' parameter set.
 
.PARAMETER Limit
Specifies the maximum number of device groups to return per page. Valid range is 1 to 250. Default is 250. This parameter belongs to the 'BySearch' parameter set.
 
.PARAMETER Definition
Switch to retrieve the group definition for the specified device group(s). Returns groupType, dynamicDefinition, layer2Definition, parentGroupId, name, and description via the `/api/v1/device-groups/{groupId}/definition` endpoint.
 
.PARAMETER Children
Switch to retrieve child groups for the specified device group(s). Supports -SearchValue, -View, -GroupType, -Limit, and -ReturnHierarchy query parameters matching the swagger /children endpoint.
 
.PARAMETER ReturnHierarchy
When used with -Children, returns the full group hierarchy tree instead of only immediate children. Default is $false.
 
.PARAMETER GroupStatus
Switch to retrieve status information for the specified device group(s).
 
.PARAMETER GroupDevices
Switch to retrieve devices belonging to the specified device group(s).
 
.PARAMETER GroupDeviceTemplates
Switch to retrieve device template configuration for devices in the specified device group(s).
 
.PARAMETER GroupDeviceCredentials
Switch to retrieve device credentials for devices in the specified device group(s).
 
.EXAMPLE
# Example 1: Retrieve specific device groups by GroupId
$groups = Get-WUGDeviceGroup -GroupId 101, 102, 103 -View 'detail'
 
.EXAMPLE
# Example 2: Search for device groups with "Server" in the name
$groups = Get-WUGDeviceGroup -SearchValue "Server" -GroupType "static_group" -Limit 100
 
.EXAMPLE
# Example 3: Get the group definition
Get-WUGDeviceGroup -ConfigGroupId 101 -Definition
 
.EXAMPLE
# Example 4: Get child groups
Get-WUGDeviceGroup -ConfigGroupId 0 -Children
 
.EXAMPLE
# Example 4b: Get child groups with search, filtering, and hierarchy
Get-WUGDeviceGroup -ConfigGroupId 0 -Children -SearchValue "Server" -GroupType static_group -View detail -ReturnHierarchy
 
.EXAMPLE
# Example 5: Get group status
Get-WUGDeviceGroup -ConfigGroupId 101 -GroupStatus
 
.EXAMPLE
# Example 6: Get devices in a group
Get-WUGDeviceGroup -ConfigGroupId 101 -GroupDevices
 
.NOTES
Author: Jason Alberino (jason@wug.ninja)
Created: 2023-04-15
Last Modified: 2026-03-15
Reference:
- [WhatsUp Gold REST API - Get Device Group by ID](https://docs.ipswitch.com/NM/WhatsUpGold2024/02_Guides/rest_api/index.html#operation/DeviceGroup_GetDeviceGroup)
- [WhatsUp Gold REST API - List Device Groups](https://docs.ipswitch.com/NM/WhatsUpGold2024/02_Guides/rest_api/index.html#operation/DeviceGroup_ListGroups)
 
This function uses parameter sets to distinguish between retrieving device groups by `GroupId` and searching with other parameters:
 
- **ByGroupId Parameter Set**: Uses the `/api/v1/device-groups/{groupId}` endpoint to retrieve specific device groups.
- **BySearch Parameter Set**: Uses the `/api/v1/device-groups/-` endpoint to search for device groups based on criteria.
- **Definition Parameter Set**: Uses the `/api/v1/device-groups/{groupId}/definition` endpoint to retrieve the group definition (groupType, dynamic/layer2 filters).
- **Children Parameter Set**: Uses the `/api/v1/device-groups/{groupId}/children` endpoint with optional search, view, groupType, limit, returnHierarchy, and pageId query parameters. Supports pagination.
 
#>

function Get-WUGDeviceGroup {
    [CmdletBinding(DefaultParameterSetName = 'BySearch')]
    param (
        [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'ByGroupId')][int[]]$GroupId,
        [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Definition')][Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Children')][Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'GroupStatus')][Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'GroupDevices')][Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'GroupDeviceTemplates')][Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'GroupDeviceCredentials')][int[]]$ConfigGroupId,
        [Parameter(ParameterSetName = 'BySearch')][Parameter(ParameterSetName = 'Children')][Parameter(ParameterSetName = 'GroupDevices')][Parameter(ParameterSetName = 'GroupDeviceTemplates')][Parameter(ParameterSetName = 'GroupDeviceCredentials')][string]$SearchValue,
        [Parameter(ParameterSetName = 'ByGroupId')][Parameter(ParameterSetName = 'BySearch')][Parameter(ParameterSetName = 'Children')][ValidateSet("summary", "detail")][string]$View = 'detail',
        [Parameter(ParameterSetName = 'BySearch')][Parameter(ParameterSetName = 'Children')][ValidateSet("all", "static_group", "dynamic_group", "layer2")][string]$GroupType = 'all',
        [Parameter(ParameterSetName = 'BySearch')][Parameter(ParameterSetName = 'Children')][Parameter(ParameterSetName = 'GroupDevices')][Parameter(ParameterSetName = 'GroupDeviceTemplates')][Parameter(ParameterSetName = 'GroupDeviceCredentials')][ValidateRange(1, 250)][int]$Limit = 250,
        [Parameter(ParameterSetName = 'Children')][Parameter(ParameterSetName = 'GroupDevices')][Parameter(ParameterSetName = 'GroupDeviceCredentials')][switch]$ReturnHierarchy,
        [Parameter(Mandatory = $true, ParameterSetName = 'Definition')][switch]$Definition,
        [Parameter(Mandatory = $true, ParameterSetName = 'Children')][switch]$Children,
        [Parameter(Mandatory = $true, ParameterSetName = 'GroupStatus')][switch]$GroupStatus,
        [Parameter(Mandatory = $true, ParameterSetName = 'GroupDevices')][switch]$GroupDevices,
        [Parameter(ParameterSetName = 'GroupDevices')][ValidateSet("id", "basic", "card", "overview")][string]$GroupDevicesView = 'card',
        [Parameter(ParameterSetName = 'GroupDevices')][ValidateSet("Unknown", "Up", "Down", "Maintenance", "Any", "UpWithDownMonitors")][string]$State,
        [Parameter(Mandatory = $true, ParameterSetName = 'GroupDeviceTemplates')][switch]$GroupDeviceTemplates,
        [Parameter(ParameterSetName = 'GroupDeviceTemplates')][switch]$IncludeHierarchy,
        [Parameter(ParameterSetName = 'GroupDeviceTemplates')][ValidateSet("all", "clone", "transfer", "update")][string]$TemplateOptions,
        [Parameter(Mandatory = $true, ParameterSetName = 'GroupDeviceCredentials')][switch]$GroupDeviceCredentials,
        [Parameter(ParameterSetName = 'GroupDeviceCredentials')][ValidateSet("id", "basic", "summary", "details")][string]$DeviceView,
        [Parameter(ParameterSetName = 'GroupDeviceCredentials')][ValidateSet("id", "basic", "summary", "details")][string]$CredentialView,
        [Parameter(ParameterSetName = 'GroupDeviceCredentials')][ValidateSet("all", "snmpV1", "snmpV2", "snmpV3", "windows", "ado", "telnet", "ssh", "vmware", "jmx", "smis", "aws", "azure", "meraki", "restapi", "ubiquiti", "redfish")][string]$CredentialType
    )

    begin {
        Write-Debug "Initializing Get-WUGDeviceGroup function."
        Write-Debug "ParameterSetName: $($PSCmdlet.ParameterSetName)"
        Write-Debug "GroupId: $GroupId"
        Write-Debug "SearchValue: $SearchValue"
        Write-Debug "View: $View"
        Write-Debug "GroupType: $GroupType"
        Write-Debug "Limit: $Limit"
        # Initialize the output collection
        $allGroups = @()
        # Base URI
        $baseUri = "${global:WhatsUpServerBaseURI}/api/v1/device-groups"
    }

    process {
        if ($PSCmdlet.ParameterSetName -eq 'ByGroupId') {
            Write-Debug "ParameterSet: ByGroupId"

            $totalGroups = $GroupId.Count
            $currentGroupIndex = 0

            foreach ($id in $GroupId) {
                $currentGroupIndex++
                $percentComplete = [Math]::Round(($currentGroupIndex / $totalGroups) * 100)

                Write-Progress -Activity "Fetching group information" -Status "Processing Group ID $id ($currentGroupIndex of $totalGroups)" -PercentComplete $percentComplete

                # Construct the URI for each group ID
                $uri = "${baseUri}/${id}?view=${View}"
                Write-Debug "Fetching group info from URI: $uri"

                # Make the API request
                try {
                    $response = Get-WUGAPIResponse -Uri $uri -Method 'GET'
                    $deviceGroup = $response.data

                    # Format the output object based on the 'View' parameter
                    if ($View -eq 'detail') {
                        $groupObject = [PSCustomObject]@{
                            Id                    = $deviceGroup.id
                            ParentGroupId         = $deviceGroup.parentGroupId
                            Name                  = $deviceGroup.name
                            Description           = $deviceGroup.description
                            GroupType             = $deviceGroup.details.groupType
                            MonitorState          = $deviceGroup.details.monitorState
                            ChildrenCount         = $deviceGroup.details.childrenCount
                            DeviceChildrenCount   = $deviceGroup.details.deviceChildrenCount
                            DeviceDescendantCount = $deviceGroup.details.deviceDescendantCount
                        }
                    }
                    else {
                        $groupObject = [PSCustomObject]@{
                            Id            = $deviceGroup.id
                            ParentGroupId = $deviceGroup.parentGroupId
                            Name          = $deviceGroup.name
                        }
                    }

                    # Add the group object to the output collection
                    $allGroups += $groupObject
                }
                catch {
                    Write-Error "Error getting device group with ID ${id}: $_"
                }
            }

            # Clear progress
            Write-Progress -Activity "Fetching group information" -Completed
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'BySearch') {
            Write-Debug "ParameterSet: BySearch"

            # Build query parameters
            $queryParams = @{}
            if ($View) { $queryParams['view'] = $View }
            if ($SearchValue) { $queryParams['search'] = $SearchValue }
            if ($GroupType) { $queryParams['groupType'] = $GroupType }
            if ($Limit) { $queryParams['limit'] = $Limit }

            # Build the query string
            $queryString = ($queryParams.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&'
            $searchUri = "${baseUri}/-?$queryString"
            Write-Debug "Search URI: $searchUri"

            $currentPageId = $null
            $pageNumber = 0

            do {
                # Check if there is a current page ID and modify the URI accordingly
                if ($null -ne $currentPageId) {
                    $currentUri = "$searchUri&pageId=$currentPageId"
                }
                else {
                    $currentUri = $searchUri
                }

                Write-Debug "Fetching groups from URI: $currentUri"

                try {
                    $result = Get-WUGAPIResponse -Uri $currentUri -Method 'GET'
                    Write-Debug "Result from Get-WUGAPIResponse: $result"

                    if ($null -ne $result.data.groups) {
                        foreach ($group in $result.data.groups) {
                            if ($View -eq 'detail') {
                                $groupObject = [PSCustomObject]@{
                                    Id                    = $group.id
                                    ParentGroupId         = $group.parentGroupId
                                    Name                  = $group.name
                                    Description           = $group.description
                                    GroupType             = $group.details.groupType
                                    MonitorState          = $group.details.monitorState
                                    ChildrenCount         = $group.details.childrenCount
                                    DeviceChildrenCount   = $group.details.deviceChildrenCount
                                    DeviceDescendantCount = $group.details.deviceDescendantCount
                                }
                            }
                            else {
                                $groupObject = [PSCustomObject]@{
                                    Id            = $group.id
                                    ParentGroupId = $group.parentGroupId
                                    Name          = $group.name
                                }
                            }
                            $allGroups += $groupObject
                        }
                    }

                    $currentPageId = $result.paging.nextPageId
                    $pageNumber++

                    # Update progress
                    if ($null -ne $result.paging.totalPages -and $result.paging.totalPages -gt 0) {
                        $percentComplete = ($pageNumber / $result.paging.totalPages) * 100
                        Write-Progress -Activity "Retrieving device groups" -Status "Page $pageNumber of $($result.paging.totalPages)" -PercentComplete $percentComplete
                    } else {
                        Write-Progress -Activity "Retrieving device groups" -Status "Processing page $pageNumber" -PercentComplete (($pageNumber % 100))
                    }
                }
                catch {
                    Write-Error "Error fetching device groups: $_"
                    break # Ensure exit from loop on error
                }
            } while ($null -ne $currentPageId)

            # Clear progress
            Write-Progress -Activity "Retrieving device groups" -Completed
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'Definition') {
            Write-Debug "ParameterSet: Definition"
            foreach ($gid in $ConfigGroupId) {
                $uri = "${baseUri}/${gid}/definition"
                Write-Debug "Fetching group definition from URI: $uri"
                try {
                    $result = Get-WUGAPIResponse -Uri $uri -Method 'GET'
                    if ($result.data) {
                        $result.data | Add-Member -NotePropertyName 'groupId' -NotePropertyValue $gid -Force
                        $allGroups += $result.data
                    }
                }
                catch {
                    Write-Error "Error fetching definition for group ${gid}: $_"
                }
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'Children') {
            Write-Debug "ParameterSet: Children"
            foreach ($gid in $ConfigGroupId) {
                # Build query parameters matching swagger: search, view, returnHierarchy, groupType, limit, pageId
                $queryParams = @{}
                if ($View)        { $queryParams['view']      = $View }
                if ($SearchValue) { $queryParams['search']    = $SearchValue }
                if ($GroupType)   { $queryParams['groupType'] = $GroupType }
                if ($Limit)       { $queryParams['limit']     = $Limit }
                if ($ReturnHierarchy) { $queryParams['returnHierarchy'] = 'true' }

                $queryString = ($queryParams.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&'
                $childrenBaseUri = "${baseUri}/${gid}/children"
                if ($queryString) { $childrenBaseUri += "?$queryString" }

                Write-Debug "Fetching children from URI: $childrenBaseUri"

                $currentPageId = $null
                $pageNumber = 0

                do {
                    $currentUri = if ($null -ne $currentPageId) {
                        $sep = if ($childrenBaseUri -match '\?') { '&' } else { '?' }
                        "${childrenBaseUri}${sep}pageId=$currentPageId"
                    } else { $childrenBaseUri }

                    try {
                        $result = Get-WUGAPIResponse -Uri $currentUri -Method 'GET'

                        if ($null -ne $result.data.groups) {
                            foreach ($group in $result.data.groups) {
                                if ($View -eq 'detail') {
                                    $groupObject = [PSCustomObject]@{
                                        Id                    = $group.id
                                        ParentGroupId         = $group.parentGroupId
                                        Name                  = $group.name
                                        Description           = $group.description
                                        GroupType             = $group.details.groupType
                                        MonitorState          = $group.details.monitorState
                                        ChildrenCount         = $group.details.childrenCount
                                        DeviceChildrenCount   = $group.details.deviceChildrenCount
                                        DeviceDescendantCount = $group.details.deviceDescendantCount
                                    }
                                }
                                else {
                                    $groupObject = [PSCustomObject]@{
                                        Id            = $group.id
                                        ParentGroupId = $group.parentGroupId
                                        Name          = $group.name
                                    }
                                }
                                $allGroups += $groupObject
                            }
                        }
                        elseif ($result.data) {
                            $allGroups += $result.data
                        }

                        $currentPageId = $result.paging.nextPageId
                        $pageNumber++

                        if ($null -ne $result.paging.totalPages -and $result.paging.totalPages -gt 0) {
                            Write-Progress -Activity "Retrieving children of group $gid" -Status "Page $pageNumber of $($result.paging.totalPages)" -PercentComplete (($pageNumber / $result.paging.totalPages) * 100)
                        }
                    }
                    catch {
                        Write-Error "Error fetching children for group ${gid}: $_"
                        break
                    }
                } while ($null -ne $currentPageId)

                Write-Progress -Activity "Retrieving children of group $gid" -Completed
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'GroupStatus') {
            Write-Debug "ParameterSet: GroupStatus"
            foreach ($gid in $ConfigGroupId) {
                $uri = "${baseUri}/${gid}/status"
                Write-Debug "Fetching status from URI: $uri"
                try {
                    $result = Get-WUGAPIResponse -Uri $uri -Method 'GET'
                    if ($result.data) {
                        $result.data | Add-Member -NotePropertyName 'groupId' -NotePropertyValue $gid -Force
                        $allGroups += $result.data
                    }
                }
                catch {
                    Write-Error "Error fetching status for group ${gid}: $_"
                }
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'GroupDevices') {
            Write-Debug "ParameterSet: GroupDevices"
            foreach ($gid in $ConfigGroupId) {
                $queryParams = @{}
                if ($GroupDevicesView)  { $queryParams['view']            = $GroupDevicesView }
                if ($SearchValue)     { $queryParams['search']          = $SearchValue }
                if ($State)           { $queryParams['state']           = $State }
                if ($Limit)           { $queryParams['limit']           = $Limit }
                if ($ReturnHierarchy) { $queryParams['returnHierarchy'] = 'true' }

                $queryString = ($queryParams.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&'
                $devicesBaseUri = "${baseUri}/${gid}/devices/-"
                if ($queryString) { $devicesBaseUri += "?$queryString" }

                Write-Debug "Fetching devices from URI: $devicesBaseUri"

                $currentPageId = $null
                $pageNumber = 0

                do {
                    $currentUri = if ($null -ne $currentPageId) {
                        $sep = if ($devicesBaseUri -match '\?') { '&' } else { '?' }
                        "${devicesBaseUri}${sep}pageId=$currentPageId"
                    } else { $devicesBaseUri }

                    try {
                        $result = Get-WUGAPIResponse -Uri $currentUri -Method 'GET'
                        if ($result.data.devices) { $allGroups += $result.data.devices }
                        elseif ($result.data) { $allGroups += $result.data }

                        $currentPageId = $result.paging.nextPageId
                        $pageNumber++

                        if ($null -ne $result.paging.totalPages -and $result.paging.totalPages -gt 0) {
                            Write-Progress -Activity "Retrieving devices in group $gid" -Status "Page $pageNumber of $($result.paging.totalPages)" -PercentComplete (($pageNumber / $result.paging.totalPages) * 100)
                        }
                    }
                    catch {
                        Write-Error "Error fetching devices for group ${gid}: $_"
                        break
                    }
                } while ($null -ne $currentPageId)

                Write-Progress -Activity "Retrieving devices in group $gid" -Completed
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'GroupDeviceTemplates') {
            Write-Debug "ParameterSet: GroupDeviceTemplates"
            foreach ($gid in $ConfigGroupId) {
                $queryParams = @{}
                if ($SearchValue)      { $queryParams['search']           = $SearchValue }
                if ($TemplateOptions)  { $queryParams['options']          = $TemplateOptions }
                if ($Limit)            { $queryParams['limit']            = $Limit }
                if ($IncludeHierarchy) { $queryParams['includeHierarchy'] = 'true' }

                $queryString = ($queryParams.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&'
                $templatesBaseUri = "${baseUri}/${gid}/devices/-/config/template"
                if ($queryString) { $templatesBaseUri += "?$queryString" }

                Write-Debug "Fetching device templates from URI: $templatesBaseUri"

                $currentPageId = $null
                $pageNumber = 0

                do {
                    $currentUri = if ($null -ne $currentPageId) {
                        $sep = if ($templatesBaseUri -match '\?') { '&' } else { '?' }
                        "${templatesBaseUri}${sep}pageId=$currentPageId"
                    } else { $templatesBaseUri }

                    try {
                        $result = Get-WUGAPIResponse -Uri $currentUri -Method 'GET'
                        if ($result.data) { $allGroups += $result.data }

                        $currentPageId = $result.paging.nextPageId
                        $pageNumber++

                        if ($null -ne $result.paging.totalPages -and $result.paging.totalPages -gt 0) {
                            Write-Progress -Activity "Retrieving device templates in group $gid" -Status "Page $pageNumber of $($result.paging.totalPages)" -PercentComplete (($pageNumber / $result.paging.totalPages) * 100)
                        }
                    }
                    catch {
                        Write-Error "Error fetching device templates for group ${gid}: $_"
                        break
                    }
                } while ($null -ne $currentPageId)

                Write-Progress -Activity "Retrieving device templates in group $gid" -Completed
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq 'GroupDeviceCredentials') {
            Write-Debug "ParameterSet: GroupDeviceCredentials"
            foreach ($gid in $ConfigGroupId) {
                $queryParams = @{}
                if ($SearchValue)      { $queryParams['search']          = $SearchValue }
                if ($DeviceView)       { $queryParams['deviceView']      = $DeviceView }
                if ($CredentialView)   { $queryParams['credentialView']  = $CredentialView }
                if ($CredentialType)   { $queryParams['type']            = $CredentialType }
                if ($Limit)            { $queryParams['limit']           = $Limit }
                if ($ReturnHierarchy)  { $queryParams['returnHierarchy'] = 'true' }

                $queryString = ($queryParams.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&'
                $credentialsBaseUri = "${baseUri}/${gid}/devices/-/credentials"
                if ($queryString) { $credentialsBaseUri += "?$queryString" }

                Write-Debug "Fetching device credentials from URI: $credentialsBaseUri"

                $currentPageId = $null
                $pageNumber = 0

                do {
                    $currentUri = if ($null -ne $currentPageId) {
                        $sep = if ($credentialsBaseUri -match '\?') { '&' } else { '?' }
                        "${credentialsBaseUri}${sep}pageId=$currentPageId"
                    } else { $credentialsBaseUri }

                    try {
                        $result = Get-WUGAPIResponse -Uri $currentUri -Method 'GET'
                        if ($result.data) { $allGroups += $result.data }

                        $currentPageId = $result.paging.nextPageId
                        $pageNumber++

                        if ($null -ne $result.paging.totalPages -and $result.paging.totalPages -gt 0) {
                            Write-Progress -Activity "Retrieving device credentials in group $gid" -Status "Page $pageNumber of $($result.paging.totalPages)" -PercentComplete (($pageNumber / $result.paging.totalPages) * 100)
                        }
                    }
                    catch {
                        Write-Error "Error fetching device credentials for group ${gid}: $_"
                        break
                    }
                } while ($null -ne $currentPageId)

                Write-Progress -Activity "Retrieving device credentials in group $gid" -Completed
            }
        }
        else {
            Write-Error "Invalid parameter set."
        }
    }

    end {
        Write-Debug "Completed Get-WUGDeviceGroup function"
        return $allGroups
    }
}
# End of Get-WUGDeviceGroup function
# End of script
#------------------------------------------------------------------
# This script is part of the WhatsUpGoldPS PowerShell module.
# It is designed to interact with the WhatsUp Gold API for network monitoring.
# The script is provided as-is and is not officially supported by WhatsUp Gold.
# Use at your own risk.
#------------------------------------------------------------------

# SIG # Begin signature block
# MIIVlwYJKoZIhvcNAQcCoIIViDCCFYQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCULuGq8Q+S8gEv
# OmMH4IhXSvXXf96xNOUxj91IGYcei6CCEdMwggVvMIIEV6ADAgECAhBI/JO0YFWU
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s
# hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD
# J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7
# P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme
# me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz
# T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q
# RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz
# mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc
# QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T
# OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/
# AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID
# AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD
# VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV
# HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE
# VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v
# ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE
# KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
# hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF
# OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC
# J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ
# pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl
# d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH
# +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M
# UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv
# ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5
# NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp
# BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI
# ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV
# DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3
# 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw
# mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm
# +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe
# dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4
# 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM
# dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY
# MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU
# pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV
# HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG
# A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1
# YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG
# AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl
# U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
# aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh
# w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd
# OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj
# cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc
# WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO
# hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs
# zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7
# 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J
# KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH
# j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2
# Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/
# L9Uo2bC5a4CH2RwwggY+MIIEpqADAgECAhAHnODk0RR/hc05c892LTfrMA0GCSqG
# SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0
# ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw
# HhcNMjYwMjA5MDAwMDAwWhcNMjkwNDIxMjM1OTU5WjBVMQswCQYDVQQGEwJVUzEU
# MBIGA1UECAwLQ29ubmVjdGljdXQxFzAVBgNVBAoMDkphc29uIEFsYmVyaW5vMRcw
# FQYDVQQDDA5KYXNvbiBBbGJlcmlubzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
# AgoCggIBAPN6aN4B1yYWkI5b5TBj3I0VV/peETrHb6EY4BHGxt8Ap+eT+WpEpJyE
# tRYPxEmNJL3A38Bkg7mwzPE3/1NK570ZBCuBjSAn4mSDIgIuXZnvyBO9W1OQs5d6
# 7MlJLUAEufl18tOr3ST1DeO9gSjQSAE5Nql0QDxPnm93OZBon+Fz3CmE+z3MwAe2
# h4KdtRAnCqwM+/V7iBdbw+JOxolpx+7RVjGyProTENIG3pe/hKvPb501lf8uBAAD
# LdjZr5ip8vIWbf857Yw1Bu10nVI7HW3eE8Cl5//d1ribHlzTzQLfttW+k+DaFsKZ
# BBL56l4YAlIVRsrOiE1kdHYYx6IGrEA809R7+TZA9DzGqyFiv9qmJAbL4fDwetDe
# yIq+Oztz1LvEdy8Rcd0JBY+J4S0eDEFIA3X0N8VcLeAwabKb9AjulKXwUeqCJLvN
# 79CJ90UTZb2+I+tamj0dn+IKMEsJ4v4Ggx72sxFr9+6XziodtTg5Luf2xd6+Phha
# mOxF2px9LObhBLLEMyRsCHZIzVZOFKu9BpHQH7ufGB+Sa80Tli0/6LEyn9+bMYWi
# 2ttn6lLOPThXMiQaooRUq6q2u3+F4SaPlxVFLI7OJVMhar6nW6joBvELTJPmANSM
# jDSRFDfHRCdGbZsL/keELJNy+jZctF6VvxQEjFM8/bazu6qYhrA7AgMBAAGjggGJ
# MIIBhTAfBgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQU
# 6YF0o0D5AVhKHbVocr8GaSIBibAwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQC
# MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIB
# AwIwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EM
# AQQBMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2Vj
# dGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBE
# BggrBgEFBQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGlj
# Q29kZVNpZ25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNl
# Y3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4IBgQAEIsm4xnOd/tZMVrKwi3doAXvC
# wOA/RYQnFJD7R/bSQRu3wXEK4o9SIefye18B/q4fhBkhNAJuEvTQAGfqbbpxow03
# J5PrDTp1WPCWbXKX8Oz9vGWJFyJxRGftkdzZ57JE00synEMS8XCwLO9P32MyR9Z9
# URrpiLPJ9rQjfHMb1BUdvaNayomm7aWLAnD+X7jm6o8sNT5An1cwEAob7obWDM6s
# X93wphwJNBJAstH9Ozs6LwISOX6sKS7CKm9N3Kp8hOUue0ZHAtZdFl6o5u12wy+z
# zieGEI50fKnN77FfNKFOWKlS6OJwlArcbFegB5K89LcE5iNSmaM3VMB2ADV1FEcj
# GSHw4lTg1Wx+WMAMdl/7nbvfFxJ9uu5tNiT54B0s+lZO/HztwXYQUczdsFon3pjs
# Nrsk9ZlalBi5SHkIu+F6g7tWiEv3rtVApmJRnLkUr2Xq2a4nbslUCt4jKs5UX4V1
# nSX8OM++AXoyVGO+iTj7z+pl6XE9Gw/Td6WKKKsxggMaMIIDFgIBATBoMFQxCzAJ
# BgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNl
# Y3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYCEAec4OTRFH+FzTlzz3Yt
# N+swDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZ
# BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB
# BAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgHF1qLH5BsNLqPEu9CKnNK+ITjafJqPkw
# yt2uqcre1f4wDQYJKoZIhvcNAQEBBQAEggIAS5sAVg+/rBEQERbcVIf/e+4yiajP
# Vy3hxVR2azTSh/l1+8iW94aKv+785kOeb8FUmBnw4asgOhug4T/bsfo61QNSBNp7
# V9qDmqmGy/W9u07Dm2D7QDIPtQHuGHkfv0rDMVqk3xAuzwpgqeEJk9JV+JPdv58A
# jIlVWoH6FewtLGO0+i/zuORkP8UkDKSULVFWBdIXsqYYCEuVPOlK6bGFqPOroHE+
# mDGHLzOdWFpZJLKxxKFmst8TgHTLIO/7/rhecqsIbEQvFWBoLFXngaXZPPhjwJI9
# nQBN6Acu98JyPL+AjLZ0MktIW03OZxsMX7XMKT9ov8X6a8b1p3K57VJKmYizjDfK
# 9TKrSZvFqSbofJGle7vwyvA2PDHlwPjuNk8J0LL4hiGyOabXqKU0Zl5xRjHjcK5P
# 7UyMc9Ge0HOSSFuUGzIhAx3+jEf4OSUvnBMWpObN2jO9SnExoBGBIEwNRIIAycGq
# sJwOeOd1aMYIT+WuU/6V4ImkO4+02egdFj50Xa4vEsxp7xDdGxbJ/AMFPW1lh1fX
# t2SNJHhuln6/uRqsqtsKEaPj1Zixmd5jOUEDaJ0Om/neO/O6j7EA1fO6cjOoXy8f
# JhFigcr4UlL5MnfgQ5ftLgXePMauj6aNlIPLrdPGoywbSMFFqppCdg3PEppI74Sk
# EP0UZ68zlKJhjFE=
# SIG # End signature block