0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

アレイから、あるキーが特定の値であるハッシュを取り出す (Terraform, Ansible, Chef)

Last updated at Posted at 2020-06-26

備忘

やりたい事

**terraformにて、**以下の様なハッシュ(マップ)のアレイ(リスト)から、nameがn2のattrを取り出す。
キーはユニークとする。


array_01:
  - name: n1
    attr: attr1
  - name: n2
    attr: attr2
  - name: n3
    attr: attr3

なお、ansibleならば、selectattrフィルターが、chef|rubyならばselectメソッドが使用可能。

追記 方法2: forループを使用 (2023/02)

terraformの場合、for文でも可能

main.tf
locals {
  array_01 = [
    {
      name = "n1",
      attr = "attr1"
    },
    {
      name = "n2",
      attr = "attr2"
    },
    {
      name = "n3",
      attr = "attr3"
    }
  ]
}

output "out1" {
  value = local.array_01[index(local.array_01.*.name, "n2")].attr  # 方法1
}

output "out2" {
  value = [for x in local.array_01 : x.attr if x.name == "n2"][0]  # 方法2
}
$ terraform apply --auto-approve

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

out1 = "attr2"
out2 = "attr2"

方法1は以下の方法1
方法2が追記した方法で、forループで回しつつif文で要素を選択。結果はlistなので[0]にて最初の要素を取り出し

方法2の方が僅かに読みやすいかもしれませんね。

方法1: ワイルドカード指定のindexを使用する。

なお、.ftではなく、.tf.jsonを使用

main.tf.json
{
  "locals": {
    "array_01": [
      { "name": "n1", "attr": "attr1" },
      { "name": "n2", "attr": "attr2" },
      { "name": "n3", "attr": "attr3" }
    ]
  },
  "output": {
    "array_01_name": {
      "value": "${ local.array_01.*.name }"
    },
    "n2_attr": {
      "value": "${ local.array_01[ index( local.array_01.*.name, \"n2\" ) ].attr }"
    }
  }
}

内容を見やすくする為にyqユーティリティを使ってyamlフォーマット化したものも載せておく

$ yq -y . main.tf.json
locals:
  array_01:
    - name: n1
      attr: attr1
    - name: n2
      attr: attr2
    - name: n3
      attr: attr3
output:
  array_01_name:
    value: ${ local.array_01.*.name }
  n2_attr:
    value: ${ local.array_01[ index( local.array_01.*.name, "n2" ) ].attr }

ここで、local.array_01.*.nameは、local.array_01の要素でキーがname:の値のアレイ(リスト)となり、index( local.array_01.*.name, "n2" ) は、nameがn2である要素番号(0始まり)の1となる。local.array_01[*].nameでも可。

$ terraform apply --auto-approve 

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

array_01_name = [
  "n1",
  "n2",
  "n3",
]
n2_attr = attr2

なお、localとoutputのみだからか、terraform initも不要であったし、terraform initを行っても.terraformディレクトリーは作成されなかった。

追記

なお、リソースからワイルドカードによる取得を行った際、要素のタイプが揃わず?indexがエラーとなるケースがあった。terraformかproviderのバグ?
indexに、for文にて作成したリストを与える事で回避した。

indexにfor文で作成したリストを渡して回避した例

main.tf.json
{
  "locals": {
    "array_01": [
      {
        "name": "n1",
        "attr": "attr1"
      },
      {
        "name": "n2",
        "attr": "attr2"
      },
      {
        "name": "n3",
        "attr": "attr3"
      }
    ]
  },
  "output": {
    "array_01_name": {
      "value": "${ local.array_01.*.name }"
    },
    "n2_attr": {
      "value": "${ local.array_01[ index( [ for s in local.array_01 : s.name ], \"n2\") ].attr }"
    }
  }
}
$ terraform apply --auto-approve

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

array_01_name = [
  "n1",
  "n2",
  "n3",
]
n2_attr = attr2

Ansibleの例

selectattr.yml
- hosts: all
  gather_facts: false
  vars:
    array_01:
      - name: n1
        attr: attr1
      - name: n2
        attr: attr2
      - name: n3
        attr: attr3
  tasks:
    - debug: msg={{ ( array_01 | selectattr("name", "equalto", "n2") | list )[0].attr }}

    - debug: msg={{ ( array_01 | selectattr("name", "==", "n2") | list )[0].attr }}

    - debug: msg={{ ( array_01 | selectattr("name", "==", "n2") | list | first ).attr }}

    - debug: msg={{ ( array_01 | json_query("[?name=='n2'].attr"))[0] }}
  • どこかのバージョンから | list は不要。(ansible 7.0.0, ansible-core 2.14.0にて確認)

  • json_query には sudo pip install jmespath などが必要

$ ansible-playbook -i localhost, -c local selectattr.yml
PLAY [all] *******************************************************************************************************

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "msg": "attr2"
}

以下同様

Chef(というかRuby)の例

select.rb

require 'yaml'

array_01 = YAML.load(<<~EOS)
  - name: n1
    attr: attr1
  - name: n2
    attr: attr2
  - name: n3
    attr: attr3
EOS

p array_01.select { |e| e['name'] == 'n2' }[0]['attr']
$ ruby select.rb 
"attr2"

参考: terraform

ワイルドカードに少し触れている。
https://www.terraform.io/docs/configuration-0-11/resources.html

公式のindexの項にはワイルドカードの説明は見つけられなかった。
https://www.terraform.io/docs/configuration/functions/index.html

参考: ansible

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?