Ansible: 다른 디렉터리 키와 일치하는 배열 키 값을 업데이트하는 방법

Ansible: 다른 디렉터리 키와 일치하는 배열 키 값을 업데이트하는 방법

나는 다음과 같은 사전을 가지고 있습니다 :

question:
  first_run:
    app:
      - answer: null
        name: first_name
        question: What is your First name?
      - answer: null
        name: last_name
        question: What is your Last name?
    core:
      - question: question1
      - question: question2
answer:
  first_name: John
  last_name: Smith

다음 작업을 사용하여 수동으로 업데이트합니다.답변이하의 가치Question.first_run.app좋은 결과

- name: Update question variable
  set_fact:
    question:
      first_run:
        app:
          - name: first_name
            question: "What is your First name?"
            answer: "{{ answer.first_name }}"
          - name: last_name
            question: "What is your Last name?"
            answer: "{{ answer.last_name }}"

또한 다음 작업을 테스트했습니다(이 경우에는 이것이 바람직한 접근 방식임).

- name: "TEST-1"
  set_fact:
    question: "{{ question | combine({'first_run': {'app': question.first_run.app | map('combine', {'answer': update }) | list }}, recursive=True) }}"
  loop: "{{ question.first_run.app }}"
  vars:
    update: "{{ answer[item.name] if item.name in answer.keys() else item.answer }}"

- name: "TEST-2"
  set_fact:
    question: "{{ question | combine({'first_run': {'app': question.first_run.app | map('combine', {'answer': (answer[item.name])})}}, recursive=True) }}"
  loop: "{{ question.first_run.app }}"
  vars:c
    update: "{{ answer | dict2items | selectattr('key', 'in', [item.name]) | map(attribute='value') | first }}"
#    update: "{{ answer[item.name] }}"    # THis also works

그러나 TEST-1 및 TEST-2의 출력은 항상 다음과 같습니다.

question:
  first_run:
    app:
      - answer: Smith
        name: first_name
        question: What is your First name?
      - answer: Smith
        name: last_name
        question: What is your Last name?
    core:
      - question: question1
      - question: question2

내가 테스트한 마지막 작업은 다음과 같습니다.
작동하지만 원하는 결과가 새 var app_list 아래에 저장됩니다.

- name: "TEST-3"
  set_fact:
    question: "{{ question | combine({'first_run': {'app': app_list}}, recursive=True) }}"
  vars:
    app_list: []
  loop: "{{ question.first_run.app }}"
  set_fact:
    app_list: "{{ app_list + [item | combine({'answer': answer[item.name]})] }}"

질문:

이러한 모든 키를 배열에 수동으로 배치할 필요가 없도록 "문제 변수 업데이트" 작업을 업데이트해야 합니다.Question.first_run.app

루프를 사용하여 일치시키는 방법Question.first_run.app.name그리고답안그러면 출력은 다음과 같을까요? TEST-1, TEST-2 또는 TEST-3을 조정하는 것이 좋습니다.

question:
  first_run:
    app:
      - answer: John
        name: first_name
        question: What is your First name?
      - answer: Smith
        name: last_name
        question: What is your Last name?
    core:
      - question: question1
      - question: question2

답변1

만들다답변

  answers: "{{ question.first_run.app|
               map(attribute='name')|
               map('extract', answer)|
               map('community.general.dict_kv', 'answer') }}"

주어진

  answers:
  - answer: John
  - answer: Smith

사전 업데이트

  app_update: "{{ question.first_run.app|
                  zip(answers)|
                  map('combine') }}"

주어진

  app_update:
  - answer: John
    name: first_name
    question: What is your First name?
  - answer: Smith
    name: last_name
    question: What is your Last name?

고쳐 쓰다첫 번째 실행

    first_run_update: "{{ question.first_run|
                          combine({'app': app_update}) }}"

주어진

  first_run_update:
    app:
    - answer: John
      name: first_name
      question: What is your First name?
    - answer: Smith
      name: last_name
      question: What is your Last name?
    core:
    - question: question1
    - question: question2

마지막 업데이트질문

    - set_fact:
        question: "{{ question|
                      combine({'first_run': first_run_update}) }}"

당신이 원하는 것을 줄

  question:
    first_run:
      app:
      - answer: John
        name: first_name
        question: What is your First name?
      - answer: Smith
        name: last_name
        question: What is your Last name?
      core:
      - question: question1
      - question: question2

테스트를 위한 완전한 플레이북 예시

- name: Substitute attribute *answer* by *name*
  hosts: localhost

  vars:

    question:
      first_run:
        app:
        - answer: null
          name: first_name
          question: What is your First name?
        - answer: null
          name: last_name
          question: What is your Last name?
        core:
        - question: question1
        - question: question2

    answer:
      first_name: John
      last_name: Smith

    answers: "{{ question.first_run.app|
                 map(attribute='name')|
                 map('extract', answer)|
                 map('community.general.dict_kv', 'answer') }}"
    app_update: "{{ question.first_run.app|
                    zip(answers)|
                    map('combine') }}"
    first_run_update: "{{ question.first_run|
                          combine({'app': app_update}) }}"
    

  tasks:

    - debug:
        var: answers
    - debug:
        var: app_update
    - debug:
        var: first_run_update

    - set_fact:
        question: "{{ question|
                      combine({'first_run': first_run_update}) }}"
    - debug:
        var: question

프로덕션에서는 선언을그룹 변수

shell> cat group_vars/all/answers.yml 
answers: "{{ question.first_run.app|
             map(attribute='name')|
             map('extract', answer)|
             map('community.general.dict_kv', 'answer') }}"
app_update: "{{ question.first_run.app|
                zip(answers)|
                map('combine') }}"
question_update:
  first_run: "{{ question.first_run|
                 combine({'app': app_update}) }}"

데이터를 넣다변하기 쉬운. 예를 들어 파일을 생성합니다.

shell> cat qa.yml 
question:
  first_run:
    app:
    - answer: null
      name: first_name
      question: What is your First name?
    - answer: null
      name: last_name
      question: What is your Last name?
    core:
    - question: question1
    - question: question2

answer:
  first_name: John
  last_name: Smith

, 스크립트를 단순화

shell> cat pb.yml 
- hosts: all
  vars_files:
    - qa.yml
  tasks:
    - set_fact:
        question: "{{ question|combine(question_update) }}"
    - debug:
        var: question

스크립트 실행

shell> ansible-playbook -l localhost pb.yml

관련 정보