【问题标题】:JQ Cross reference or how to replace one value with another part of the inputJQ 交叉引用或如何用输入的另一部分替换一个值
【发布时间】:2018-07-19 07:50:02
【问题描述】:

我想解析 terraform.tfstate(使用 openstack 提供程序的地方),返回实例名称及其内部 + 浮动 IP(如果已分配)。

首先选择我们感兴趣的:

jq -r '.modules?[]|.resources[]?|select(.type == "openstack_compute_floatingip_v2", .type == "openstack_compute_instance_v2")' < terraform.tfstate

为简单起见,使用上述部分预解析示例(一个 FIP 和一个实例):

{
  "type": "openstack_compute_floatingip_v2",
  "depends_on": [
    "openstack_networking_router_interface_v2.management"
  ],
  "primary": {
    "id": "48b039fc-a9fa-4672-934a-32d6d267f280",
    "attributes": {
      "address": "209.66.89.143",
      "fixed_ip": "10.10.10.5",
      "id": "48b039fc-a9fa-4672-934a-32d6d267f280",
      "instance_id": "597e75e8-834d-4f05-8408-e2e6e733577e",
      "pool": "public",
      "region": "RegionOne"
    },
    "meta": {},
    "tainted": false
  },
  "deposed": [],
  "provider": "provider.openstack"
}
{
  "type": "openstack_compute_instance_v2",
  "depends_on": [
    "openstack_compute_floatingip_v2.management",
    "openstack_compute_secgroup_v2.ssh_only",
    "openstack_networking_network_v2.management"
  ],
  "primary": {
    "id": "597e75e8-834d-4f05-8408-e2e6e733577e",
    "attributes": {
      "access_ip_v4": "10.10.10.5",
      "access_ip_v6": "",
      "all_metadata.%": "1",
      "all_metadata.habitat": "sup",
      "availability_zone": "nova",
      "flavor_id": "eb36e84e-17c1-42ab-b359-4380f6f524ae",
      "flavor_name": "m1.large",
      "force_delete": "false",
      "id": "597e75e8-834d-4f05-8408-e2e6e733577e",
      "image_id": "c574aeed-e47c-4fb7-9da0-75550b76ee56",
      "image_name": "ubuntu-16.04",
      "key_pair": "vault-etcd_test_tf",
      "metadata.%": "1",
      "metadata.habitat": "sup",
      "name": "ctl01",
      "network.#": "1",
      "network.0.access_network": "false",
      "network.0.fixed_ip_v4": "10.10.10.5",
      "network.0.fixed_ip_v6": "",
      "network.0.floating_ip": "",
      "network.0.mac": "02:c6:61:f9:ee:7e",
      "network.0.name": "management",
      "network.0.port": "",
      "network.0.uuid": "f2468669-e321-4eb4-9ede-003e362a8988",
      "region": "RegionOne",
      "security_groups.#": "1",
      "security_groups.1845949017": "vault-etcd_test_ssh_only",
      "stop_before_destroy": "false"
    },
    "meta": {
      "e2bfb730-ecaa-11e6-8f88-34363bc7c4c0": {
        "create": 1800000000000,
        "delete": 1800000000000,
        "update": 1800000000000
      }
    },
    "tainted": false
  },
  "deposed": [],
  "provider": "provider.openstack"
}

需要从"type": "openstack_compute_floatingip_v2" 替换.primary.attributes.address.fixed_ip 并从相应的.instance_id 中获取.name

所以,比如:

{"address": "209.66.89.143",
"fixed_ip": "10.10.10.5",
"name": "ctl01"}

好吧,我在使用 walk 时想到了一个想法,但错过了如何从相应的实例 id 实际分配正确的值:

jq -r "$(cat floating.jq)" terraform.tfstate

浮动.jq:

def walk(f):
      . as $in
      | if type == "object" then
          reduce keys[] as $key
            ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
      elif type == "array" then map( walk(f) ) | f
      else f
      end;
.modules?[]|.resources[]?|select(.type == 
    "openstack_compute_floatingip_v2", .type == 
    "openstack_compute_instance_v2")|
    .primary|walk( if  type == "object" and .attributes.address then 
    .attributes.instance_id |= "REFERRED VALUE HERE") else . end)

【问题讨论】:

  • 为什么不直接使用 Terraform 输出而不是尝试解析 JSON 状态文件?
  • 您可以使用terraform state show 获取一个资源的所有相关信息的列表。这可能更容易解析。
  • tf 输出很好,但也需要正确的格式,我正在编写一个模块来将 .tfstate 数据转换为另一个配置,所以 IP 只是我希望从中获取的一个子集
  • terraform state show 主要给我我已经拥有的数据,我可以去那个级别并使用它,但问题是如何在一个查询中替换 instance_id 的值与内容id = instance_id的“记录”。

标签: openstack jq terraform


【解决方案1】:

假设这两个相关对象位于名为 two.json 的文件中。然后合并来自两个对象的信息的一种方法是使用-s 命令行选项,例如

jq -s '
  (.[0].primary.attributes | {address, fixed_ip})
  + {name: .[1].primary.attributes.name}' two.json

输出

使用您的示例输入,输出将是:

{
  "address": "209.66.89.143",
  "fixed_ip": "10.10.10.5",
  "name": "ctl01"
}

【讨论】:

  • 很好,可用,但假设:{"id": "nic_record", "attributes": {"address": "111", "name_id": "bbb"}} 并且您想从 {{"id": "aaa", "attributes": {"name"aaa"}}},{"id": "aaa", "attributes": {"name"bbb"}}}} 替换/引用名称 id 但 select 应该可以解决这个问题。
  • 原始问题和评论都不是很清楚(至少对我而言)。我建议您尽可能遵循minimal reproducible example 指南,并可能提出一个新的 SO 问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多