【问题标题】:Filtering cloudformation stack resources using JQ使用 JQ 过滤 cloudformation 堆栈资源
【发布时间】:2016-03-10 08:55:02
【问题描述】:

我正在尝试编写一个 JQ 过滤器,用于根据资源属性从 AWS cloudformation 模板中过滤特定资源。

例如,从以下(缩短的)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"
      }
    ]
  }
}
}
}

我想构建一个 jq 过滤器,使我能够根据(一个或多个)属性字段过滤掉特定资源。

例如:

当过滤 Type="AWS::EC2::InternetGateway" 时,结果应该是

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

一个额外的好处是能够过滤一个“或”的值组合。 因此,“AWS::EC2::InternetGateway”或“AWS::EC2::VPC”的过滤器应生成原始文档。

任何建议或见解将不胜感激。

发送!

【问题讨论】:

    标签: json amazon-cloudformation jq


    【解决方案1】:

    @hek2mgl 的建议可能足以满足您的目的,但它并不能完全产生您要求的答案。这是一个非常相似的解决方案。它使用了 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"))
    

    使用您的示例输入:

    $ 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"
          }
        }
      }
    

    正如@hek2mgl 指出的那样,现在指定一个更复杂的选择标准是微不足道的。 }

    【讨论】:

    • 嘿!好答案!我在问自己如何像你展示的那样产生输出,并且仍然保持合理的复杂性。意思是保持数据结构不变,只是过滤。我真的很喜欢 jq,但恕我直言,它在很多现实世界的问题上变得太复杂了。
    • @hek2mgl - 谢谢! jq当然有改进的余地。为什么不参加github.com/stedolan/jq/issues 特别是github.com/stedolan/jq/issues/1035 的一些讨论?
    • @peak:我的问题的通用解决方案!仍然试图抓住 JQ 的全部潜力,但这对我有很大帮助。
    【解决方案2】:

    使用select()函数:

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

    如果要按多个条件过滤,可以使用or,如下所示:

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

    【讨论】:

    • 感谢您的回答。我确实和你在同一时间到达,但正如峰值所示,这样我会丢失进一步处理所需的信息(对象名)。
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      这是一个解决方案,它使用单独的函数来选择与指定条件匹配的所有资源,该条件为每个资源传递一个 {key,value} 对。

      def condition:
        .value.Type == "AWS::EC2::VPC"
      ;
      
      {
        Resources: .Resources | with_entries(select(condition))
      }
      

      样本数据的输出:

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

      【讨论】:

        猜你喜欢
        • 2019-03-14
        • 1970-01-01
        • 2020-11-09
        • 2019-05-09
        • 2018-10-27
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多