Цикл Foreach против if / elseif во вложенной хеш-таблице с использованием Powershell - PullRequest
0 голосов
/ 03 июля 2018

Моя цель - создать сценарий PowerShell, который отслеживает состояние оборудования хоста и выдает предупреждения (с помощью кодов выхода), если состояние компонента не «ЗЕЛЕНЫЙ». Следующая информация извлекается из программного API как хеш-таблица по умолчанию.

Для удобства чтения это информация в формате JSON, которую я преобразовал с помощью командлета convertto-json :

"host":  {
             "serial_number":  "55555",
             "status":  "GREEN",
             "name":  "hostname",
             "raid_card":  {
                               "serial_number":  "55555",
                               "status":  "GREEN",
                               "product_name":  "PRODUCT",
                           },
             "battery":  {
                             "percent_charged":  100,
                             "health":  "HEALTHY",
                             "status":  "GREEN"
                         },
             "accelerator":  {
                                      "temperature":  36,
                                      "status":  "GREEN"
                                  },
             "logical_drives":  [
                                    "@{serial_number=55555555555; health=HEALTHY}",
                                    "@{serial_number=55555555556; health=HEALTHY}"
                                ]
         }
}

Если какой-либо из компонентов (батарея, raid_card, accelerator или logic_drives) не зеленый, то значение верхнего хоста.status изменится на «КРАСНЫЙ».

Логика, которую я предполагаю, состоит в том, чтобы сделать начальную инструкцию if, в которой если host.value имеет значение «ЗЕЛЕНЫЙ», затем завершить 0 (что означает, что он работает) и просто вывести сообщение.

В противном случае выполните цикл foreach для поиска и определения того, какой компонент не «ЗЕЛЕНЫЙ». Вот где я застрял с логикой.

Первая проблема, с которой я столкнулся, это не знание, подходит ли цикл foreach для этой проблемы. Если это так, как вы можете структурировать цикл foreach, так как один из компонентов, логические диски, имеет вложенную хеш-таблицу внутри.

Вторая проблема, с которой я столкнулся, - как вы можете получить имя компонента, если статус не «ЗЕЛЕНЫЙ»?

Я не продвинулся далеко, но это структура, с которой я изначально собирался:

if (host.value -eq "GREEN"){
Write-Host "Message: host hardware is healthy"
Exit 0;
}

else{
    foreach ($components in $response.host){
       if ($_.status -ne "GREEN){
       Write-Host "Message: host.??? is not healthy"
       Exit 1;
       }
}

Одной из альтернативных структур является выполнение операторов if / elseif вместо цикла foreach. Проблема в том, что он не очень элегантный, и его повторяемость предполагает, что есть лучший способ.

if (host.value -eq "GREEN"){
Write-Host "Message: host hardware is healthy"
Exit 0;
}

else{
    if (host.raid_card.status -ne "GREEN"){
    Write-Host "Message: host.raid_card.product_name is not healthy"
    Exit 1;
    }

    elseif (host.battery.status -ne "GREEN"){
    Write-Host "Message: host battery is host.battery.status"
    Exit 1;
    }

    elseif (host.accelerator.status -ne "GREEN"{
    Write-Host "Message: accelerator temperature is host.accelerator.temperature"
    Exit 1;
    }
}

Буду признателен за любые рекомендации по улучшению структуры!

1 Ответ

0 голосов
/ 05 июля 2018

Я бы посоветовал поместить компоненты, которые вы хотели бы сделать, на одну ступень глубже в структуре, а также убедиться, что у каждого компонента есть похожие свойства status для проверки (что не так в вашем примере с json), например так:

{
    "host": {
        "serial_number": "55555",
        "status": "GREEN",
        "name": "hostname",
        "components": {
            "raid_card": {
                "serial_number": "55555",
                "status": "GREEN",
                "product_name": "PRODUCT"
            },
            "battery": {
                "percent_charged": 100,
                "health": "HEALTHY",
                "status": "GREEN"
            },
            "accelerator": {
                "temperature": 36,
                "status": "GREEN"
            },
            "logical_drives": {
                "serial_number": "55555555555",
                "health": "HEALTHY",
                "status": "GREEN"
            }
        }
    }
}

Если у вас это есть, вы можете использовать такой код для проверки состояния каждого компонента:

# Set up an return variable (exit code)
[int]$exitCode = 0

# $machine is the variable name i used to import the json above
if ($machine.host.status -eq "GREEN") {
    Write-Host "Message: Machine $($machine.host.name) - hardware is healthy"
}
else {
    foreach ($component in $machine.host.components.PSObject.Properties) { 
        if ($component.Value.status -ne "GREEN") {
            Write-Host "Message: Machine $($machine.host.name) - $($component.Name) is not healthy"
            $exitCode = 1
        }
    }
}

Exit $exitCode

Конечно, у вас есть разные предметы, и сейчас я вижу, что массив логических дисков может быть проблемой. Если вы хотите, чтобы скрипт сообщал вам, какой логический диск вызывает состояние «не ЗЕЛЕНЫЙ», вам нужно предоставить оператор if внутри цикла foreach для итерации по каждому диску.

...