[RUBY] Terraform: (und Ansible: und Chef :) Extrahieren Sie einen Hash aus einem Array, in dem ein Schlüssel einen bestimmten Wert hat.

Was willst du tun

** Bei Terraform wird ** Attr mit dem Namen n2 aus dem Array (Liste) von Hashes (Karten) extrahiert, wie unten gezeigt. Der Schlüssel ist einzigartig.


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

Wenn es ansibel ist, kann der selectattr-Filter verwendet werden, und wenn chef | ruby, kann die select-Methode verwendet werden.

Methode: Verwenden Sie einen vom Platzhalter angegebenen Index.

Beispiel

Verwenden Sie .tf.json anstelle von .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 }"
    }
  }
}

Ich habe auch das yaml-Format mit dem yq-Dienstprogramm eingefügt, damit der Inhalt besser sichtbar ist.

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

Hier ist local.array_01. \ *. Name ein Element von local.array_01 und der Schlüssel ist ein Array (eine Liste) von Werten mit dem Namen: und index (local.array_01. \ . Name, "n2") ist name. Ist 1 der Elementnummer (beginnend mit 0), wobei n2 ist. Sie können auch local.array_01 [] .name verwenden.

$ terraform apply --auto-approve 

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

Outputs:

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

Darüber hinaus war Terraform-Init wahrscheinlich nicht erforderlich, da Terraform-Init ausgeführt wurde, da Terraform-Init nicht ausgeführt wurde.

Nachtrag

Außerdem gab es beim Abrufen von einer Ressource mit einem Platzhalter einen Fall, in dem die Elementtypen nicht ausgerichtet waren und? Index zu einem Fehler wurde. Terraform oder Provider Bug? Dies wurde vermieden, indem die von der for-Anweisung erstellte Liste indiziert wurde.

Beispiel für das Vermeiden durch Übergeben der von der for-Anweisung erstellten Liste an den 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

Ansible Beispiel

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   

Beispiel eines Küchenchefs (oder Rubins)

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"

Referenz: Terraform

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

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

Ich berühre die Wild Card ein wenig. https://www.terraform.io/docs/configuration-0-11/resources.html

Im offiziellen Indexbereich wurde keine Beschreibung des Platzhalters gefunden. https://www.terraform.io/docs/configuration/functions/index.html

Referenz: ansible

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

Recommended Posts

Terraform: (und Ansible: und Chef :) Extrahieren Sie einen Hash aus einem Array, in dem ein Schlüssel einen bestimmten Wert hat.
[Ruby] So extrahieren Sie einen bestimmten Wert aus einem Array unter mehreren Bedingungen [select / each]
[Java] Ruft Werte zufällig aus einem Array ab
In Bezug auf die Zuordnung von Hash-Schlüssel und Wert
[Ruby] Ich möchte nur den Wert des Hash und nur den Schlüssel extrahieren