分开存储数据和输出数据

时间:2018-09-04 13:53:04

标签: powershell

我有2个功能,一个用于获取数据,另一个用于输出数据。将这些内容拆分为允许“刷新”,而不必再次请求静态信息。

我希望Get-AllAP函数发出请求并存储数据。

我希望Show-APAll函数获取该数据并输出。

这样做的原因是在“刷新”上,我们可以运行Show-APAll,这只会从第一个请求输出数据,而不是发出整个其他请求。

function Get-AllAP {
    $functionName = $MyInvocation.MyCommand
    Write-Verbose "Function Start: Get-AllAP"
    Write-Log "Get-AllAp started for Store $Store" -Level INFO -logfile $logFile
    Write-Host "Getting all Access Points in Store $Store. This can take a moment."
    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 }
    Write-Log "Making Get request to $storeApReq" -Level INFO -logfile $logFile

    $global:apIdList =  $apIdListReq.queryResponse.entityId
    $global:apIdCount =  $apIdListReq.queryResponse."@count"
    $global:controllerName = $apData.unifiedApInfo.controllerName
    $global:apIdURL =  $apIdListReq.queryResponse.entityId
    $global:apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'

    ## Create array object of all aps on site
    Write-Verbose "Creating Access Point loop"
    $global:apArray = New-Object System.Collections.ArrayList
    Write-Host "Getting status on Access Points: " -NoNewLine

    ## Begin looping
    $global:apLoop = foreach ($apURL in $apURLs) {
        $apFullReq = Invoke-RestMethod -Uri $apURL'.json' -Method Get -ContentType 'application/json' -Headers @{ Authorization = $auth }
        $global:allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO

        ## Store our data
        $global:apStatus =$allApData.status
        $global:apName = $allApData.name
        $global:apPing = $allApData.reachabilitystatus
        $global:controllerName = $allApData.unifiedApInfo.controllerName
        $global:switch = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
        $global:switchPort = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
        $global:location = $allApData.locationHierarchy
        $global:clientCount = $allApData.clientCount

        ## Watch for errors in loop
        Write-Host "$apName " -NoNewline

        ## Output apName to array for use later
        $apArray.Add($apName)
        Write-Log "$apName discovered with $clientCount devices connected." -Level DEBUG -logfile $logFile
    }
}

此函数查询API,并获取有关我们稍后要使用的AP的信息。接下来,它将引用Show-APAll来显示此数据。

Function Show-APAll {
    $functionName = $MyInvocation.MyCommand
    Write-Log "Show-APAll started for Store $Store" -Level INFO -logfile $logFile
    Write-Verbose "Function start: Show-APAll"
    Clear
    Write-Host " "
    Write-Host '-------------------------------------------' -Foregroundcolor "DarkCyan"
    Write-Host "    All Access Points For Store $Store"
    Write-Host '-------------------------------------------' -Foregroundcolor "DarkCyan"

    foreach ($apName in $apArray) {
        ## Print to log for debugging
        Write-Log "$apName discovered with $clientCount devices connected." -Level DEBUG -logfile $logFile

        ## Output data for user
        Write-Host " "
        Write-Host "AP Name: $apName"
        if ($apPing -eq 'UNREACHABLE') {
            Write-Host "AP is Offline" -Foregroundcolor "Red"
        } else {
            Write-Host "AP is Online" -ForegroundColor "Green"
        }
        if ($apStatus -eq 'Critical') {
            Write-Host "AP Problem Level:$apStatus" -Foregroundcolor "Red"
        } else {
            Write-Host "AP Problem Level: $apStatus" -ForegroundColor "Green"

        }
        Write-Host "Clients Connected: $clientCount"
        Write-Host "Location: $location"
        Write-Host "Switch Port: $switchPort on $switch"
    }
    Management-AfterAll
}

正如您确定的那样,这里发生的事情是只有$apName是唯一的,而其余数据作为最后一个要循环通过的对象存储在变量中。以下是一些日志,它们准确显示了$clientCount发生的情况。

日志输出:

2018/09/04 08:39:42 INFO Making Get request to https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=0026 Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:42 DEBUG 0026AP4 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:43 DEBUG 0026AP7 discovered with 3 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:43 DEBUG 0026AP8 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:43 DEBUG 0026AP3 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:44 DEBUG 0026AP9 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:44 DEBUG 0026AP1 discovered with 9 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:44 DEBUG 0026AP6 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:44 DEBUG 0026AP10 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP2 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP5 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694
2018/09/04 08:39:45 INFO Show-APAll started for Store 0026 Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP4 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP7 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP8 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP3 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP9 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP1 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP6 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP10 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP2 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
2018/09/04 08:39:45 DEBUG 0026AP5 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694

$clientCount的响应值在Get-AllAp中很好,但是仅最后一个要循环的AP的值可用。我确实知道为什么会这样,因为显然变量在给定的时间内只能有一个赋值,但是我不确定如何解决此问题而不会造成混乱。

我尝试了很多事情,包括将数据添加到$apArray,但这在输出中造成混乱,只是将数组中的位置返回为整数。有人可以指出我正确的方向吗?

答案1编辑:

    Function Get-AllAP {
        $functionName = $MyInvocation.MyCommand
        Write-Verbose "Function Start: Get-AllAP"
        Write-Log "Get-AllAp started for Store $Store" -Level INFO -logfile $logFile
        Write-Host "Getting all Access Points in Store $Store. This can take a moment."
        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 }
        Write-Log "Making Get request to $storeApReq" -Level INFO -logfile $logFile

        $apIdList = $apIdListReq.queryResponse.entityId
        $apIdCount = $apIdListReq.queryResponse."@count"
        $controllerName = $apData.unifiedApInfo.controllerName
        $apIdURL = $apIdListReq.queryResponse.entityId
        $apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'  

        ## Create array object of all aps on site
        Write-Verbose "Creating Access Point loop"
        $Global:apArray = New-Object System.Collections.ArrayList
        Write-Host "Getting status on Access Points: " -NoNewLine

        ## Begin looping
        foreach ($apURL in $apURLs) {
        $apFullReq = Invoke-RestMethod -Uri "${apURL}.json" -Method Get -ContentType 'application/json' -Headers @{Authorization = $auth}
        $allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO

        $apArray = New-Object -Type PSObject -Property @{
            'apStatus'       = $allApData.status
            'apName'         = $allApData.name
            'apPing'         = $allApData.reachabilitystatus
            'controllerName' = $allApData.unifiedApInfo.controllerName
            'switch'         = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
            'switchPort'     = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
            'location'       = $allApData.locationHierarchy
            'clientCount'    = $allApData.clientCount
        }

    }
}

这确实有助于使数据与PS友好,并且我可以输出数据,但这不能解决问题中概述的问题。

  1. 在没有设置全局属性的情况下,其他函数仍然无法访问对象属性。

1 个答案:

答案 0 :(得分:2)

停止对所有内容使用全局变量。从REST响应中创建自定义对象,然后将其输出到函数中,然后将函数输出收集到调用方作用域中的变量中。

function Get-AllAP {
    ...

    $apIdList = $apIdListReq.queryResponse.entityId
    $apIdCount = $apIdListReq.queryResponse."@count"
    $controllerName = $apData.unifiedApInfo.controllerName
    $apIdURL = $apIdListReq.queryResponse.entityId
    $apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'

    ...

    foreach ($apURL in $apURLs) {
        $apFullReq = Invoke-RestMethod -Uri "${apURL}.json" -Method Get -ContentType 'application/json' -Headers @{Authorization = $auth}
        $allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO

        New-Object -Type PSObject -Property @{
            'apStatus'       = $allApData.status
            'apName'         = $allApData.name
            'apPing'         = $allApData.reachabilitystatus
            'controllerName' = $allApData.unifiedApInfo.controllerName
            'switch'         = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
            'switchPort'     = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
            'location'       = $allApData.locationHierarchy
            'clientCount'    = $allApData.clientCount
        }
    }
}

$apArray = Get-AllAP

向函数Show-AllAP添加参数,并将变量$apArray作为函数的参数传递:

function Show-AllAP {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [array]$apList
    )

    ...
    foreach ($ap in $apList) {
        Write-Host ('AP Name: {0}' -f $ap.apName)
        ...
    }
    ...
}

Show-AllAP $apArray

重点不是完全避免全局变量,而是避免在嵌套上下文中修改(甚至使用)全局变量。定义明确的界面使读者可以清楚地知道哪些信息(来自代码的其余部分)进入了该函数,以及该函数返回了哪些数据(尽管PowerShell当然承认后者有些模糊)。嵌套上下文中的全局变量基本上是数据流中的一个辅助渠道,通常会使故障排除更加复杂,尤其是当您的代码库增长时。

将代码封装在函数中的全部目的是提供一种抽象,您可以在其中更改函数的实现以及全局代码(例如重命名全局变量),而又不影响另一个。只要功能接口(参数集和返回的数据)不变,就可以。