简体   繁体   English

使用 JQ 过滤 cloudformation 堆栈资源

[英]Filtering cloudformation stack resources using JQ

I'm trying to write a JQ-filter for filtering specific resources from an AWS cloudformation template based on resource properties.我正在尝试编写一个 JQ 过滤器,用于根据资源属性从 AWS cloudformation 模板中过滤特定资源。

For example, when starting from the following (shortened) cloudformation template:例如,当从以下(缩短的)cloudformation 模板开始时:

{
"Resources": {
"vpc001": {
  "Type": "AWS::EC2::VPC",
  "Properties": {
    "CidrBlock": "10.1.0.0/16",
    "InstanceTenancy": "default",
    "EnableDnsSupport": "true",
    "EnableDnsHostnames": "true"
  }
},
"ig001": {
  "Type": "AWS::EC2::InternetGateway",
  "Properties": {
    "Tags": [
      {
        "Key": "Name",
        "Value": "ig001"
      }
    ]
  }
}
}
}

I would like to construct a jq-filter enabling me to filter out specific resources based on (one or multiple) of their property fields.我想构建一个 jq-filter,使我能够根据(一个或多个)属性字段过滤掉特定资源。

For example:例如:

when filtering for Type="AWS::EC2::Inte.netGateway" the result should be当过滤 Type="AWS::EC2::Inte.netGateway" 结果应该是

{
 "Resources": {
"ig001": {
  "Type": "AWS::EC2::InternetGateway",
  "Properties": {
    "Tags": [
      {
        "Key": "Name",
        "Value": "ig001"
      }
    ]
  }
}
}
}

An added bonus would be to be able to filter on a 'OR'-ed combination of values.一个额外的好处是能够过滤值的“或”组合。 As such a filter for "AWS::EC2::Inte.netGateway" OR "AWS::EC2::VPC" should yield the original document.因此,“AWS::EC2::Inte.netGateway”或“AWS::EC2::VPC”的过滤器应该产生原始文档。

Any suggestion or insight would be greatly appreciated.任何建议或见解将不胜感激。

Tx! TX!

@hek2mgl's suggestion may be sufficient for your purposes, but it doesn't quite produce the answer you requested. @ hek2mgl的建议可能足以满足您的目的,但并不能完全满足您的要求。 Here's one very similar solution that does. 这是一个非常类似的解决方案。 It uses a generalization of jq's map() and map_values() filters that is often useful anyway: 它使用jq的map()和map_values()过滤器的一般化方法,这些方法通常还是有用的:

def mapper(f):
  if type == "array" then map(f)
  elif type == "object" then
  . as $in
  | reduce keys[] as $key
      ({};
       [$in[$key] | f ] as $value
       | if $value | length == 0 then . else . + {($key): $value[0]}
         end)
  else .
  end;

.Resources |= mapper(select(.Type=="AWS::EC2::VPC"))

Using your example input: 使用示例输入:

$ jq -f resources.jq resources.json
{
  "Resources": {
    "vpc001": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "CidrBlock": "10.1.0.0/16",
        "InstanceTenancy": "default",
        "EnableDnsSupport": "true",
        "EnableDnsHostnames": "true"
      }
    }
  }

As @hek2mgl pointed out, it's now trivial to specify a more complex selection criterion. 正如@ hek2mgl指出的那样,现在指定一个更复杂的选择标准变得不那么容易了。 } }

Use the select() function: 使用select()函数:

jq '.Resources[]|select(.Type=="AWS::EC2::VPC")' aws.json

You can use or if you want to filter by multiple conditions, like this: 您可以使用or如果要按多个条件进行过滤,如下所示:

jq '.Resources[]|select(.Type=="AWS::EC2::VPC" or .Type=="foo")' aws.json

Use aws cli's --query parameter. 使用aws cli的--query参数。 Completely eliminates the need for jq. 完全消除了对jq的需要。 http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html#controlling-output-filter http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html#controlling-output-filter

Here is a solution which uses a separate function to select all resources matching a specified condition which is passed a {key,value} pair for each resource. 这是一个使用单独函数选择符合指定条件的所有资源的解决方案,并为每个资源传递了{key,value}对。

def condition:
  .value.Type == "AWS::EC2::VPC"
;

{
  Resources: .Resources | with_entries(select(condition))
}

Output from sample data: 样本数据的输出:

{
  "Resources": {
    "vpc001": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "CidrBlock": "10.1.0.0/16",
        "InstanceTenancy": "default",
        "EnableDnsSupport": "true",
        "EnableDnsHostnames": "true"
      }
    }
  }
}

I found one way to do this without defining a function:我找到了一种无需定义 function 即可执行此操作的方法:

jq '.Resources | to_entries[] | select(.value.Type == "AWS::EC2::InternetGateway")|[{key: .key, value: .value}]|from_entries' example.json

{
  "ig001": {
    "Type": "AWS::EC2::InternetGateway",
    "Properties": {
      "Tags": [
        {
          "Key": "Name",
          "Value": "ig001"
        }
      ]
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM