Search code examples
powershellcisco

ForEach Invoke-RestMethod


I'm trying to make a request to the AccessPointsDetails endpoint of the Cisco Prime API and then loop through that to get all URL objects for the AccessPoints so I can get data on each of them.

I get the following output:

VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3373245; $=3373245}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3413720; $=3413720}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3432295; $=3432295}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3432310; $=3432310}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3462672; $=3462672}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3497980; $=3497980}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3497993; $=3497993}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3512621; $=3512621}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/3526872; $=3526872}
VERBOSE: Making request to: @{@type=AccessPointDetails; @url=https://cpist/webacs/api/v3/data/AccessPointDetails/16162527426; $=16162527426}
@type              @url                                                            $          
-----              ----                                                            -          
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3373245     3373245    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3413720     3413720    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3432295     3432295    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3432310     3432310    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3462672     3462672    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3497980     3497980    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3497993     3497993    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3512621     3512621    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/3526872     3526872    
AccessPointDetails https://cpist/webacs/api/v3/data/AccessPointDetails/16162527426 16162527426

Here is the response JSON for one store as well:

{
  "queryResponse": {
    "@last": 9,
    "@first": 0,
    "@count": 10,
    "@type": "AccessPointDetails",
    "@requestUrl": "https://cpist/webacs/api/v3/data/AccessPointDetails?.group=0026",
    "@responseType": "listEntityIds",
    "@rootUrl": "https://cpist/webacs/api/v3/data",
    "entityId": [
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3373245",
        "$": "3373245"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3413720",
        "$": "3413720"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3432295",
        "$": "3432295"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3432310",
        "$": "3432310"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3462672",
        "$": "3462672"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3497980",
        "$": "3497980"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3497993",
        "$": "3497993"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3512621",
        "$": "3512621"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3526872",
        "$": "3526872"
      },
      {
        "@type": "AccessPointDetails",
        "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/16162527426",
        "$": "16162527426"
      }
    ]
  }
}

I feel I may be a bit burnt and making a silly oversight?

Solution Code (See Accepted Answer):

Function allAP {
Write-Verbose "Getting all APs for Store $Store"
$storeApReq = "https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=$Store"
Write-Verbose "Making request to $storeApReq"
$Global:apIdListReq = Invoke-RestMethod -uri $storeApReq -method Get -ContentType 'application/json' -headers @{ Authorization = $auth }
$Global:apIdList =  $apIdListReq.queryResponse.entityId
$Global:apIdCount =  $apIdListReq.queryResponse."@count"

Write-Verbose "Found $siteAPCount APs in Sites Database. $apIdCount out of $siteAPCount APs found."
Write-Verbose "Response Received: $apIdList"
$Global:apIdURL =  $apIdListReq.queryResponse.entityId
$Global:apURL = $apIdUrl.'@url'

Write-Verbose "Starting a loop."
ForEach($apIdURL in $apIdList) {
Invoke-RestMethod -uri $apURL -method Get -ContentType 'application/json' -headers @{ Authorization = $auth }
Write-Verbose "Making request to: $apURL"
$apURL

}
}

Solution

  • The biggest issue you're having is accessing the members of your returned object incorrectly. The Invoke-RestMethod is returning a pscustomobject representation of the JSON the application returns to you. Your example JSON looked like this:

    {
      "queryResponse": {
        "@last": 9,
        "@first": 0,
        "@count": 10,
        "@type": "AccessPointDetails",
        "@requestUrl": "https://cpist/webacs/api/v3/data/AccessPointDetails?.group=0026",
        "@responseType": "listEntityIds",
        "@rootUrl": "https://cpist/webacs/api/v3/data",
        "entityId": [
          {
            "@type": "AccessPointDetails",
            "@url": "https://cpist/webacs/api/v3/data/AccessPointDetails/3373245",
            "$": "3373245"
          },
    
          ...
        ]
      }
    }
    

    This gets transformed into pscustomobject:

    [pscustomobject]@{
        'queryResponse' = [pscustomobject]@{
            '@last'         = 9
            '@first'        = 0
            '@count'        = 10
            '@type'         = 'AccessPointDetails'
            '@requestUrl'   = 'https://cpist/webacs/api/v3/data/AccessPointDetails?.group=0026'
            '@responseType' = 'listEntityIds'
            '@rootUrl'      = 'https://cpist/webacs/api/v3/data'
            'entityId'      = @(
                [pscustomobject]@{
                    '@type' = 'AccessPointDetails'
                    '@url'  = 'https://cpist/webacs/api/v3/data/AccessPointDetails/3373245'
                    '$'     = '3373245'
                }
    
                ...
            )
        }
    }
    

    I'm unsure why accessing .'@url' isn't working for you. Below is a working implementation of what you're trying to do.


    function Get-AccessPoint
    {
        param
        (
            [Parameter(Position = 0, Mandatory)]
            [ValidateNotNullOrEmpty()]
            [string]
            $Store
        )
    
        # function is accessing above-scope variables $auth and $siteAPCount
    
        Write-Verbose "Retrieving APs for store $Store"
        $uri = "https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=$Store"
        Write-Verbose "Request: $uri"
        $global:apIdListReq = Invoke-RestMethod -Uri $uri -ContentType application/json -Headers @{Authorization = $auth}
        $global:apIdList = $apIdListReq.queryResponse.entityId
        $global:apIdCount = $apIdListReq.'@count'
    
        Write-Verbose "Found $siteAPCount APs in Sites Database. $apIdCount out of $siteAPCount APs found."
        foreach ($entity in $apIdList)
        {
            Write-Verbose "Making request to $($entity.'@url')"
            Invoke-RestMethod -Uri $entity.'@url' -ContentType application/json -Headers @{Authorization = $auth}
        }
    }