ต่อท้ายรายการหรือเพิ่มคีย์ให้กับพจนานุกรมใน Ansible


34

(เกี่ยวข้องกับCallbacks หรือ hooks และชุดงานที่สามารถใช้ซ้ำได้ในบทบาท Ansible ):

มีวิธีใดที่ดีกว่าในการผนวกรายการหรือเพิ่มคีย์ในพจนานุกรมใน Ansible than (ab) โดยใช้เทมเพลต jina2

ฉันรู้ว่าคุณสามารถทำสิ่งที่ชอบ:

- name: this is a hack
  shell: echo "{% originalvar.append('x') %}New value of originalvar is {{originalvar}}"

แต่จริง ๆ แล้วไม่มีเมตาดาต้าหรือตัวช่วยในการทำเช่นนี้?

รู้สึกเปราะบางดูเหมือนว่าจะไม่มีเอกสารและอาศัยสมมติฐานมากมายเกี่ยวกับการทำงานของตัวแปรใน Ansible

กรณีการใช้ของฉันมีหลายบทบาท (ส่วนขยายเซิร์ฟเวอร์ฐานข้อมูล) ที่แต่ละคนต้องจัดหาการกำหนดค่าบางอย่างให้กับบทบาทพื้นฐาน (เซิร์ฟเวอร์ฐานข้อมูล) มันไม่ง่ายเหมือนการต่อบรรทัดเข้ากับไฟล์กำหนดค่าเซิร์ฟเวอร์ db การเปลี่ยนแปลงแต่ละครั้งจะมีผลกับบรรทัดเดียวกันเช่นส่วนขยายbdrและpg_stat_statementsทั้งสองจะต้องปรากฏในบรรทัดเป้าหมาย:

shared_preload_libaries = 'bdr, pg_stat_statements'

วิธี Ansible ในการทำเช่นนี้เพียงแค่ประมวลผลไฟล์กำหนดค่าหลาย ๆ ครั้ง (หนึ่งครั้งต่อส่วนขยาย) ด้วย regexp ที่แยกค่าปัจจุบันแยกวิเคราะห์แล้วเขียนใหม่หรือไม่ ถ้าเป็นเช่นนั้นคุณจะทำให้ idempotent นั้นข้ามหลาย ๆ การวิ่งได้อย่างไร?

จะเกิดอะไรขึ้นถ้าการกำหนดค่านั้นยากกว่านี้ในการแยกวิเคราะห์และมันไม่ง่ายเท่ากับการผนวกค่าที่คั่นด้วยเครื่องหมายจุลภาคอื่น คิดว่าไฟล์กำหนดค่า XML


คุณรู้อะไรไหม ฉันชอบการตัดผลข้างเคียง
ฟัล

คำตอบ:


13

+คุณสามารถผสานสองรายการในตัวแปรที่มี สมมติว่าคุณมีgroup_varsไฟล์ที่มีเนื้อหานี้:

---
# group_vars/all
pgsql_extensions:
  - ext1
  - ext2
  - ext3

และมันถูกใช้ในเทมเพลตpgsql.conf.j2เช่น:

# {{ ansible_managed }}
pgsql_extensions={% for item in pgsql_extensions %}{{ item }}, {% endfor %}

จากนั้นคุณสามารถผนวกส่วนขยายเข้ากับเซิร์ฟเวอร์ฐานข้อมูลทดสอบดังนี้:

---
# group_vars/testing_db
append_exts:
  - ext4
  - ext5
pgsql_extensions: "{{ pgsql_extensions + append_exts }}"

เมื่อมีการเรียกใช้บทบาทในเซิร์ฟเวอร์ทดสอบใด ๆ ส่วนขยาย aditional จะถูกเพิ่ม

ฉันไม่แน่ใจว่าสิ่งนี้ใช้ได้กับพจนานุกรมเช่นกันและควรระวังช่องว่างและปล่อยเครื่องหมายจุลภาคที่ห้อยอยู่ที่ท้ายบรรทัด


คุณสามารถทำได้ แต่คุณต้องทำทั้งหมดgroup_varsให้ครบบทบาทไม่สามารถดูแลรายละเอียดของการตั้งค่าส่วนขยายได้ มันเป็นการเพิ่ม vars จากบทบาทที่ฉันกำลังมองหาเป็นพิเศษดังนั้นหนึ่งบทบาทสามารถต่อท้ายบทบาทที่เปิดเผยโดยบทบาทอื่น
Craig Ringer

บทบาทพื้นฐานของคุณรู้เกี่ยวกับบทบาทส่วนขยายหรือไม่ ฉันมีกรณีที่คล้ายกันที่ฉันสามารถปล่อยให้เรียงต่อกันได้ถึงwith_itemsประโยค
GnP

ไม่และนั่นเป็นปัญหาจริงๆ ในการปรับใช้ครั้งเดียวบทบาทพื้นฐานอาจเป็น al
Craig Ringer

4
ดูเหมือนว่าถ้าคุณพยายามทำเช่นนี้เพื่อเชื่อมสองรายการเข้าด้วยกันคุณคิดว่ามันเป็นเทมเพลตแบบเรียกซ้ำไม่สิ้นสุดเนื่องจากด้านซ้ายมืออยู่ทางด้านขวาด้วยเช่นกัน ฉันเข้าใจผิดว่าจะใช้สิ่งนี้ได้อย่างไร
อิบราฮิม

2
@spectras อย่างน้อยในฐานะของ Ansible 2.7 มันไม่ทำงาน ตามที่แนะนำ Ibrahim สิ่งนี้ทำให้เกิดข้อผิดพลาด: "ตรวจพบลูปซ้ำในสตริงแม่แบบ"
rluba

35

ตั้งแต่ Ansible v2.x คุณสามารถทำได้:

# use case I: appending to LIST variable:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_myvar + new_items_list}}'

# use case II: appending to LIST variable one by one:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_var + [item]}}'
        with_items: '{{my_new_items|list}}'

# use case III: appending more keys DICT variable in a "batch":

      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine(my_new_keys_in_a_dict)}}'

# use case IV: appending keys DICT variable one by one from tuples
      - name: setup list of tuples (for 2.4.x and up
        set_fact:
          lot: >
            [('key1', 'value1',), ('key2', 'value2',), ..., ('keyN', 'valueN',)],
      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine({item[0]: item[1]})}}'
        with_items: '{{lot}}'
# use case V: appending keys DICT variable one by one from list of dicts (thanks to @ssc)

  - name: add new key / value pairs to dict
    set_fact:
      my_dict_var: "{{ my_dict_var | combine({item.key: item.value}) }}"
    with_items:
    - { key: 'key01', value: 'value 01' }
    - { key: 'key02', value: 'value 03' }
    - { key: 'key03', value: 'value 04' }

ทั้งหมดข้างต้นได้รับการบันทึกไว้ใน: http://docs.ansible.com/ansible/playbooks_filters.html


1
ใช้ case IV เพิ่งผนวกu'(': u\"'\"}"
ssc

1
ขอบคุณ @ssc ฉันสังเกตเห็นว่ามันไม่ทำงานกับ ansible 2.4.x(คงที่)
Max Kovgan

ตาม usecase # 4 ผมได้เพิ่มค่าเริ่มต้นที่จะจัดการกับข้อผิดพลาดที่ไม่ได้กำหนดset_fact: my_dict_var: '{{my_dict_var|default({})|combine({item[0]: item[1]})}}'ในสถานการณ์ของฉัน: ข้อผิดพลาดที่ไม่ได้กำหนดเกิดขึ้นเมื่อมีการใช้การกรองบางอย่างหรือไม่มีการลงทะเบียนผลลัพธ์
SK Venkat

Mr SK Venkat รหัสตัวอย่างที่นี่แสดงให้เห็นถึงสิ่งที่เฉพาะเจาะจงมากเท่านั้น (การเพิ่มรายการพจนานุกรมจากสิ่งอันดับ) หากคุณต้องการทำอย่างอื่นรหัสนี้ไม่ใช่ของคุณคัดลอกวาง
Max Kovgan

3

คุณต้องแบ่งลูปเป็น 2

--- 
- โฮสต์: localhost
  งาน: 
    - include_vars: สแต็ก
    - set_facts: บทบาท = {{stacks.Roles | แยก ('')}}
    - รวมถึง: addhost.yml
      with_items: "{{role}}"

และ addhost.yml

- set_facts: groupname = {{item}}
- set_facts: ips = {{สแต็ก [รายการ] | split ('')}}
- local_action: add_host hostname = {{item}} groupname = {{groupname}}
  with_items: {{ips}}

1

ไม่แน่ใจว่าเมื่อพวกเขาเข้ามานี้ แต่อย่างน้อยสำหรับพจนานุกรม / แฮช (ไม่รายการ / อาร์เรย์) คุณสามารถตั้งค่าตัวแปรhash_behaviourเช่นดังนั้น: ในของคุณhash_behaviour = mergeansible.cfg

เอาฉันไปสองสามชั่วโมงเพื่อบังเอิญเจอกับสภาพแวดล้อมนี้:


สิ่งนี้มีประโยชน์มาก แต่ระวังให้เปิดใช้งาน e2e บน codebase ที่มีอยู่ อาจทำลายไข่บ้าง
Max Kovgan

0

คำตอบเกือบทั้งหมดในที่นี้ต้องการการเปลี่ยนแปลงในงาน แต่ฉันต้องการผสานพจนานุกรมในคำจำกัดความ vars แบบไดนามิกไม่ใช่ในระหว่างการเรียกใช้

เช่นผมต้องการที่จะกำหนด vars ที่ใช้ร่วมกันบางอย่างในall group_varsและแล้วฉันต้องการที่จะขยายพวกเขาในบางอื่น ๆหรือgroup host_varsมีประโยชน์มากเมื่อทำงานกับบทบาท

หากคุณพยายามใช้combineหรือunionกรองการเขียนทับตัวแปรดั้งเดิมในไฟล์ var คุณจะสิ้นสุดในลูปไม่สิ้นสุดระหว่างการสร้างเทมเพลตดังนั้นฉันจึงสร้างวิธีแก้ปัญหานี้ (ไม่ใช่วิธีแก้ปัญหา)

คุณสามารถกำหนดตัวแปรหลายตัวตามรูปแบบชื่อบางส่วนแล้วโหลดโดยอัตโนมัติในบทบาท

group_vars/all.yml

dictionary_of_bla:
  - name: blabla
    value1 : blabla
    value2 : blabla

group_vars/group1.yml

dictionary_of_bla_group1:
  - name: blabla2
    value1 : blabla2
    value2 : blabla2

ข้อมูลโค้ดบทบาท

tasks:
  - name: Run for all dictionary_of_bla.* variations
    include_tasks: do_some_stuff.yml
    with_items: "{{ lookup('varnames','dictionary_of_bla.*').split(',') }}"
    loop_control:
      loop_var: _dictionary_of_bla

do_some_stuff.yml

- name: do magic
  magic:
    trick_name: item.name
    trick_value1: item.value1
    trick_value2: item.value2
  with_items: "{{ vars[_dictionary_of_bla] }}"

มันเป็นเพียงตัวอย่างเล็ก ๆ น้อย ๆ แต่คุณควรเข้าใจว่ามันทำงานอย่างไร หมายเหตุ: การค้นหา ('varnames', '') มีให้ตั้งแต่ ansible 2.8

ฉันเดาว่ามันจะเป็นไปได้ที่จะรวมตัวแปรทั้งหมดdictionary_of_bla.*เข้าเป็นหนึ่งพจนานุกรมระหว่างรันไทม์โดยใช้การค้นหาเดียวกัน

ข้อดีของวิธีนี้คือคุณไม่จำเป็นต้องตั้งค่ารายการชื่อตัวแปรที่แน่นอน แต่มีเพียงรูปแบบและผู้ใช้ที่สามารถตั้งค่าแบบไดนามิกได้


-4

Ansibleเป็นระบบอัตโนมัติและเกี่ยวกับการจัดการไฟล์การกำหนดค่าก็ไม่แตกต่างกันมากaptนัก เหตุผลที่ซอฟต์แวร์มากขึ้นมีคุณสมบัติในการอ่านตัวอย่างการกำหนดค่าจากconf.dไดเรกทอรีคือการทำให้ระบบอัตโนมัติดังกล่าวมีแพ็คเกจ / บทบาทที่แตกต่างกันเพิ่มการกำหนดค่าให้กับซอฟต์แวร์ ฉันเชื่อว่ามันไม่ใช่ปรัชญาของAnsibleการทำสิ่งที่คุณมีในใจ แต่แทนที่จะใช้conf.dเคล็ดลับ หากซอฟต์แวร์ที่มีการกำหนดค่าไม่ได้มีฟังก์ชั่นนี้แสดงว่าคุณกำลังมีปัญหา

เมื่อคุณพูดถึงไฟล์การกำหนดค่า XML ฉันมีโอกาสทำเสียงหอนบ้าง มีเหตุผลสำหรับประเพณี Unix ในการใช้ไฟล์การกำหนดค่าข้อความล้วน ไฟล์การกำหนดค่าไบนารีไม่ได้ให้ยืมตัวเองดีกับระบบอัตโนมัติดังนั้นรูปแบบไบนารีใด ๆ ที่จะทำให้คุณเดือดร้อนและอาจต้องการให้คุณสร้างโปรแกรมเพื่อจัดการกับการกำหนดค่า (ถ้าใครคิดว่า XML เป็นรูปแบบข้อความธรรมดาพวกเขาควรไปตรวจสมอง)

ตอนนี้PostgreSQLปัญหาเฉพาะของคุณ PostgreSQLสนับสนุนconf.dเคล็ดลับ ก่อนอื่นฉันจะตรวจสอบว่าshared_preload_librariesสามารถระบุได้หลายครั้งหรือไม่ ฉันไม่พบคำใบ้ใด ๆ ในเอกสารที่สามารถทำได้ แต่ฉันจะลองทำดู หากไม่สามารถระบุได้หลายครั้งฉันจะอธิบายปัญหาของฉันให้PostgreSQLผู้ชายทราบในกรณีที่พวกเขามีแนวคิด นี่เป็นPostgreSQLปัญหาและไม่ใช่Ansibleปัญหา หากไม่มีวิธีการแก้ปัญหาและฉันไม่สามารถรวมบทบาทที่แตกต่างกันเป็นหนึ่งเดียวฉันจะใช้ระบบเพื่อรวบรวมการกำหนดค่าในโฮสต์ที่มีการจัดการ ในกรณีนี้ผมอาจจะสร้างสคริปต์/usr/local/sbin/update_postgresql_configซึ่งจะรวบรวมเข้า/etc/postgresql/postgresql.conf.jinja /etc/postgresql/9.x/main/postgresql.confสคริปต์จะอ่านไลบรารีที่โหลดล่วงหน้าที่แบ่งใช้จาก/etc/postgresql/shared_preload_libraries.txtหนึ่งไลบรารีต่อบรรทัดและจัดเตรียมให้กับ jinja

ไม่ใช่เรื่องแปลกที่ระบบอัตโนมัติจะทำเช่นนี้ ตัวอย่างคือexim4แพ็คเกจเดเบียน


PostgreSQL สนับสนุนconf.dกลไกการรวมและขอบคุณที่ใช้ไฟล์ธรรมดา อย่างไรก็ตามมีตัวเลือกการกำหนดค่าบางอย่างที่ส่วนขยายหลายรายการอาจมีความคิดเห็นเกี่ยวกับเรื่องนี้ - เช่น "เพิ่ม max_wal_senders เพิ่มขึ้น 10 เท่าจากที่เคยเป็นมาก่อน"
Craig Ringer

4
ดูเหมือนว่าคุณกำลังบอกว่าแอปพลิเคชันควรจะเปลี่ยนไปเพื่อแก้ไขข้อ จำกัด ในระบบการจัดการการกำหนดค่าหรือฉันควรยอมแพ้ที่จะมีบทบาทที่สามารถใช้งานได้อีกครั้ง
Craig Ringer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.