ProgramingTip

Ansible set_fact를 사용하여 예측 결과에서 사전 생성

bestdevel 2021. 1. 6. 20:54
반응형

Ansible set_fact를 사용하여 예측 결과에서 사전 생성


Ansible에서는 register작업 결과를 변수에 저장하는 데 사용 했습니다 people. 필요하지 않은 항목을 생략하면 다음과 같은 구조가 있습니다.

{
    "results": [
        {
            "item": {
                "name": "Bob"
            },
            "stdout": "male"
        },
        {
            "item": {
                "name": "Thelma"
            },
            "stdout": "female"
        }
    ]
}

다음 set_fact작업 을 사용하여 다음 과 같은 사전으로 새 변수를 생성하고 싶습니다.

{
    "Bob": "male",
    "Thelma": "female"
}

나는 그것이 가능할 것이라고 생각하지만 지금까지 운이없는 둥글게 돌고있다.


나는 결국 거기에 도착했다고 생각합니다.

작업은 다음과 달라집니다.

- name: Populate genders
  set_fact:
    genders: "{{ genders|default({}) | combine( {item.item.name: item.stdout} ) }}"
  with_items: "{{ people.results }}"

그것은 dicts (각 통해 루프 item)에 people.results배열 각 같은 새로운 딕셔너리를 생성 시간 {Bob: "male"}, 및 combine()s를 딕셔너리 그 genders와 같은 끝 배열 :

{
    "Bob": "male",
    "Thelma": "female"
}

키 ( name이 경우)가 고유 한 가정합니다 .


그런 다음 사용하여 반복하는 것이 즉시 보라고 사전 목록이 필요합니다 with_items.

- name: Populate genders
  set_fact:
    genders: "{{ genders|default([]) + [ {'name': item.item.name, 'gender': item.stdout} ] }}"
  with_items: "{{ people.results }}"

기존의 기존 목록을 단일 dict를 포함하는 목록과 계속 결합합니다. 우리는 다음과 같은 genders배열로 끝납니다 .

[
    {'name': 'Bob', 'gender': 'male'},
    {'name': 'Thelma', 'gender': 'female'}
]

솔루션에 대해 Phil에게 감사합니다. 누군가 나와 같은 상황에 처하게 여기에 (더 복잡한) 변형이 있습니다.

---
# this is just to avoid a call to |default on each iteration
- set_fact:
    postconf_d: {}

- name: 'get postfix default configuration'
  command: 'postconf -d'
  register: command

# the answer of the command give a list of lines such as:
# "key = value" or "key =" when the value is null
- name: 'set postfix default configuration as fact'
  set_fact:
    postconf_d: >
      {{
        postconf_d |
        combine(
          dict([ item.partition('=')[::2]|map('trim') ])
        )
  with_items: command.stdout_lines

그러면 다음과 같은 출력이 제공됩니다 (예제에서는 생략 됨).

"postconf_d": {
    "alias_database": "hash:/etc/aliases", 
    "alias_maps": "hash:/etc/aliases, nis:mail.aliases",
    "allow_min_user": "no", 
    "allow_percent_hack": "yes"
}

더 나아가 '값'의 목록을 구문 분석하십시오.

- name: 'set postfix default configuration as fact'
  set_fact:
    postconf_d: >-
      {% set key, val = item.partition('=')[::2]|map('trim') -%}
      {% if ',' in val -%}
        {% set val = val.split(',')|map('trim')|list -%}
      {% endif -%}
      {{ postfix_default_main_cf | combine({key: val}) }}
  with_items: command.stdout_lines
...
"postconf_d": {
    "alias_database": "hash:/etc/aliases", 
    "alias_maps": [
        "hash:/etc/aliases", 
        "nis:mail.aliases"
    ], 
    "allow_min_user": "no", 
    "allow_percent_hack": "yes"
}

주의해야 할 몇 가지 사항 :

  • 그것은 "트림"에 모든 필요가있는 경우 >-사용됩니다 (사용 YAML-%}신사 , 그것이 의미하는 오류를 같이 얻을,) :

    FAILED! => {"failed": true, "msg": "|combine expects dictionaries, got u\"  {u'...
    
  • 분명히 {% if ..방탄과는 거리가 멀다

  • 접미사의 경우 val.split(',')|map('trim')|list로 단순화 할 수 val.split(', ')있었지만 |list그렇지 않으면 다음과 같은 오류가 발생 한다는 사실을 지적하고 싶었습니다 .

    "|combine expects dictionaries, got u\"{u'...': <generator object do_map at ...
    

이것이 도움이되기를 바랍니다.

참조 URL : https://stackoverflow.com/questions/35605603/using-ansible-set-fact-to-create-a-dictionary-from-register-results

반응형