[RUBY] Terraform: (et Ansible: et Chef :) Extraire un hachage d'un tableau où une clé a une valeur spécifique.

Que veux-tu faire

** Avec terraform, ** Attr avec le nom n2 est extrait du tableau (liste) de hachages (cartes) comme indiqué ci-dessous. La clé est unique.


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

S'il est ansible, le filtre selectattr peut être utilisé, et si chef | ruby, la méthode select peut être utilisée.

Méthode: utilisez un index spécifié par des caractères génériques.

Exemple

Utilisez .tf.json au lieu de .ft

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

J'ai également mis le format yaml en utilisant l'utilitaire yq pour rendre le contenu plus facile à voir.

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

Ici, local.array_01. \ *. Name est un élément de local.array_01 et la clé est un tableau (liste) de valeurs portant le nom:, et l'index (local.array_01. \ . Name, "n2") est le nom. Est 1 du numéro d'élément (commençant par 0) où est n2. Vous pouvez également utiliser 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

De plus, probablement parce qu'il est uniquement local et en sortie, terraform init n'était pas nécessaire, et même si terraform init a été exécuté, le répertoire .terraform n'a pas été créé.

Postscript

De plus, lors de l'extraction à partir d'une ressource avec un caractère générique, il y avait un cas où les types d'éléments n'étaient pas alignés et? Index devenait une erreur. bogue terraform ou fournisseur? Cela a été évité en donnant la liste créée par l'instruction for à indexer.

Exemple d'évitement en passant la liste créée par l'instruction for à index

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( [ 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

Exemple 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 | json_query("[?name=='n2'].attr"))[0] }}
$ ansible-playbook -i localhost, -c local selectattr.yml
PLAY [all] *******************************************************************************************************

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

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

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

PLAY RECAP *******************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Exemple de Chef (ou 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"

Référence: terraform

https://stackoverflow.com/questions/52119400/how-to-get-an-object-from-a-list-of-objects-in-terraform

https://stackoverflow.com/a/59437020/13819312

Je touche un peu le joker. https://www.terraform.io/docs/configuration-0-11/resources.html

Aucune description du caractère générique n'a été trouvée dans la section d'index officielle. https://www.terraform.io/docs/configuration/functions/index.html

Référence: ansible

https://www.it-swarm-ja.tech/ja/jinja2/ansible:リストを属性でフィルタリングする/1053979194/

Recommended Posts

Terraform: (et Ansible: et Chef :) Extraire un hachage d'un tableau où une clé a une valeur spécifique.
[Ruby] Comment extraire une valeur spécifique d'un tableau sous plusieurs conditions [sélectionner / chacun]
[Java] Récupère des valeurs de manière aléatoire dans un tableau
Concernant le mappage de la clé de hachage et de la valeur
[Ruby] Je souhaite extraire uniquement la valeur du hachage et uniquement la clé