我正在尝试为不同的配置文件选择特定AWSMFADevice
的SerialNumber
。
该命令返回某个配置文件的MFADevices列表:
aws iam list-mfa-devices --profile xxx
,这是一个JSON输出示例:
{
"MFADevices": [
{
"UserName": "foobar@example.com",
"SerialNumber": "arn:aws:iam::000000000000:mfa/foo",
"EnableDate": "2022-12-06T16:23:41+00:00"
},
{
"UserName": "barfoo@example.com",
"SerialNumber": "arn:aws:iam::111111111111:mfa/bar_cli",
"EnableDate": "2022-12-12T09:13:10+00:00"
}
]
}
我想选择包含字符串cli
的设备的SerialNumber
。但是,如果列表中只有一个设备(无论字符串cli
是否存在),我想获得它的SerialNumber
。
我有这个表达式,它已经过滤了第一个条件,即所需的字符串:
aws iam list-mfa-devices --profile xxx --query 'MFADevices[].SerialNumber | [?contains(@,`cli`)] | [0]'
然而,我仍然没有能够弄清楚如何添加if number_of_devices == 1 then return the serial of that single device
.
我可以用这个命令得到MFADevices
的编号:
aws iam list-mfa-devices --profile yyy --query 'length(MFADevices)'
作为我最终解决方案的第一步,我想最初只在列表只有一个元素的情况下获得SerialNumber
,所以,我想到了这样的东西:
aws iam list-mfa-devices --profile yyy --query 'MFADevices[].SerialNumber | [?length(MFADevices) ==`1`]'
,但实际上已经在这个阶段,我得到下面的错误(单独的事实,我仍然需要结合它与cli
部分):
在函数长度()中,值的类型无效:None,期望为['string', 'array', 'object']之一,收到:"null">
有谁知道如何实现我想要的吗?
我知道我可以将原始输出管道到jq
并在那里进行过滤,但我想知道是否有一种方法可以使用一些JMESPath表达式直接在命令中执行。
为了在JMESPath中执行这些条件,您将不得不依赖于logical or (||
)和logical and (&&
),因为该语言本身没有条件关键字。
if length(MFADevices) == 1
MFADevices[0]
else
MFADevices[?someFilter]
你必须这样做,就像在bash中:
length(MFADevices) == 1 and MFADevices[0] or MFADevices[?someFilter]
所以,在JMESPath中:
length(MFADevices) == `1`
&& MFADevices[0].SerialNumber
|| (MFADevices[?contains(SerialNumber, `cli`)] | [0]).SerialNumber
注意:这假设,如果有多个元素,但没有包含cli
,我们应该得到null
。
如果你想要第一个元素,即使有多个设备,SerialNumber
不包含cli
,那么您可以进一步简化它,并简单地执行逻辑or
,当包含过滤器不返回任何内容时(因为null
的结果将计算为false
):
(MFADevices[?contains(SerialNumber, `cli`)] | [0]).SerialNumber
|| MFADevices[0].SerialNumber
使用stedolan/jq,您可以筛选子字符串并无条件添加第一个,然后取其中的第一个:
.MFADevices | map(.SerialNumber) | first((.[] | select(contains("cli"))), first)
演示或
[.MFADevices[].SerialNumber] | map(select(contains("cli"))) + .[:1] | first
演示输出:
arn:aws:iam::111111111111:mfa/bar_cli