Разделение хранения данных и вывода данных - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть 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 и получает информацию о точках доступа, которые мы хотим использовать позже. Затем он будет ссылаться на 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, но можно использовать только значение для последней зацикленной точки доступа. Я понимаю, почему это происходит, потому что, очевидно, переменная может иметь только одно назначение в данный момент времени, но я не уверен, как это исправить, не создавая путаницу циклов.

Я пробовал несколько вещей, включая добавление данных в $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. Свойства объекта по-прежнему недоступны для других функций, не делая Global.

1 Ответ

0 голосов
/ 04 сентября 2018

Хватит использовать глобальные переменные для всего. Создайте пользовательские объекты из ответа 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 немного нечеткая, когда речь идет о последней). Глобальные переменные во вложенных контекстах в основном являются побочным каналом в потоке данных и, как правило, значительно усложняют поиск и устранение неисправностей, особенно при расширении базы кода.

Весь смысл инкапсуляции кода в функциях состоит в том, чтобы предоставить абстракцию, в которой вы можете изменить реализацию функции, а также свой глобальный код (например, переименовать вашу глобальную переменную), не влияя на один другой. Пока интерфейс функции (набор параметров и возвращаемые данные) не изменяется, то есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...