Powershell - 使用INVOKE-RESTMETHOD

时间:2018-06-19 07:30:06

标签: powershell

我试图从其他API的某些多层JSON输出中返回某个值,并且似乎无法正确使用返回的输出,尤其是当您不知道可能存在的内容时那个输出(我已经看到关于这个ASSUME的大多数例子你已经知道返回的字段并且可以硬编码,但在这种情况下不是。)

有问题的API是F5本地流量管理器Rest API ...

返回的JSON看起来像这样。我希望从中获取 serverside.curConns 的价值...

{
      "generation": 263285,
      "kind": "tm:ltm:pool:members:membersstats",
      "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
      "entries": {
        "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats": {
          "nestedStats": {
            "kind": "tm:ltm:pool:members:membersstats",
            "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
            "entries": {
              "serverside.curConns": {
                "value": 0
              }
          }
        }
      }
    }
    }

我的问题是第一个"条目"上面的容器会在我运行它的每个服务器上改变,这就是我想要编写的代码,但到目前为止还没有成功。

我的Powershell脚本目前看起来像这样......

$f5partition = "Production"
# ======= CHANGE PER ENVIRONMENT ==========
$f5poolname = "Frontend_App_pool"
$f5port = 8080
$user = "myf5userid"
$pass = "myf5password"
$f5server = "myf5server.mydomain.local"
# ======= NO CHANGES BELOW THIS LINE! =======
$servername = $env:COMPUTERNAME
# ====== AUTHORISATION SECTION ==========
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
    Authorization = $basicAuthValue
}
#=== CONNECT TO F5 API =========
$reply = Invoke-RestMethod -Uri https://${f5server}/mgmt/tm/ltm/pool/~${f5partition}~${f5poolname}/members/~${f5partition}~${servername}:${f5port}/stats/?$select=serverside.curConns -Headers $Headers

当我第一次运行时,可以(使用Powershell' ISE)标记$ reply的结果,所以我最终得到的值为0 ...

Write-Host $reply.entries.'https://localhost/mgmt/tm/ltm/pool/~Production~Frontend-App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats'.nestedStats.entries.'serverside.curConns'.value

这很棒。但是对于服务器PROD_SERVER01。然后,我无法保存该脚本并针对PROD_SERVER02运行它,因为它现在在脚本中进行了硬编码。

我真正需要的是像$ reply.entries。* .nestedStats.entries。' serverside.curConns' .value,或者某种方式我可以查询和解决返回的未预先确定的JSON值无论如何。

对此非常感谢,谢谢

我试图编写一个没有行李的脚本或需要复制到其他服务器上运行的工具,例如模块或其他.exe。而这个Invoke-RestMethod几乎正在做我想要的,但是当我使用一个不是预期的字段时,我正在努力枚举输出。

由于

2 个答案:

答案 0 :(得分:3)

在这种情况下,您可以将JSON转换为XML并使用XPath获得所需的内容。经过测试并可以正常工作:

# question's original JSON sample above
$json = ConvertFrom-Json $s;

# change -depth to suit your needs
$xml = ConvertTo-Xml -NoTypeInformation $json -Depth 10;
# if you want to take a look at JSON => XML.
# pretty-print only works in PowerShell console, not ISE
$xml.Save([Console]::Out);

# 0, what you're looking for....
$wanted = $xml.DocumentElement.SelectSingleNode(
              '//Property[@Name="serverside.curConns"]'
          ).FirstChild.InnerText;

使用PowerShell用IMHO解析JSON是很痛苦的/非常缺乏-应该有内置的支持来解析嵌套的JSON对象。

答案 1 :(得分:-1)

神奇之处在于使用$ yourObject.psobject

$json = @"
{
      "generation": 263285,
      "kind": "tm:ltm:pool:members:membersstats",
      "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
      "entries": {
        "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats": {
          "nestedStats": {
            "kind": "tm:ltm:pool:members:membersstats",
            "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
            "entries": {
              "serverside.curConns": {
                "value": 0
              }
          }
        }
      }
    }
    }
"@ | ConvertFrom-Json

$entryName = $json.entries.psobject.Properties.Name

$json.entries.$($entryName).nestedStats.entries.'serverside.curConns'.value