Ansible: ฉันสามารถใช้ vars_files ได้หรือไม่เมื่อมีบางไฟล์


17

นั่นคือส่วนที่:

vars_files:
  - vars/vars.default.yml
  - vars/vars.yml

หากไฟล์vars/vars.ymlไม่มีอยู่ - นี่เป็นข้อผิดพลาด

ERROR: file could not read: /.../vars/vars.yml

ฉันจะโหลดตัวแปรเพิ่มเติมจากไฟล์นี้เฉพาะเมื่อมีอยู่ได้อย่างไร (ไม่มีข้อผิดพลาด)

คำตอบ:


27

มันค่อนข้างง่ายจริงๆ คุณสามารถบีบรายการ vars_files ที่แตกต่างกันของคุณลงใน tuple เดียวและ Ansible จะผ่านแต่ละรายการโดยอัตโนมัติจนกว่าจะพบไฟล์ที่มีอยู่และโหลด Ex:

vars_files:
  - [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]

4
ตามนักพัฒนา Ansibleโซลูชันนี้จะโหลดไฟล์ทั้งหมดไม่ใช่แค่ไฟล์แรกที่พบ
tjanez

10

ตามที่นักพัฒนาเบิ้ลที่เหมาะสมวิธีที่จะแก้ปัญหานี้คือการใช้สิ่งที่ชอบ:

vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]

- include_vars: "{{ item }}"
  with_first_found: vars_files_locs

นอกจากนี้พวกเขาพูดว่า :

ด้านบนจะโหลดไฟล์แรกที่พบได้อย่างถูกต้องและมีความยืดหยุ่นมากกว่าการพยายามทำผ่านvars_filesคำหลักภาษา


"พบเฉพาะไฟล์แรก" - ความคิดคือการกำหนดตัวแปรบางตัวไม่ใช่ทั้งหมด
Sergey

@ Sergey อ่านคำถามของคุณอีกครั้งฉันเห็นว่าสิ่งที่คุณต้องการแตกต่างกันเล็กน้อย ขอบคุณที่ชี้นำสิ่งนี้ ฉันจะทิ้งคำตอบเช่นเดียวกับถ้าคนอื่นเห็นว่ามีประโยชน์
tjanez

1
ยกเว้นว่าinclude_varsในงานจะให้ความสำคัญสูงของตัวแปรเมื่อเทียบกับบทบาทdefaultsหรือvars
Alex F

2

ฉันพบปัญหานี้ในการตั้งค่าที่ฉันต้องการในการสร้างสภาพแวดล้อมการปรับใช้ที่หลากหลาย (สด, สาธิต, แซนด์บ็อกซ์) ไปยังเซิร์ฟเวอร์ทางกายภาพเดียวกัน (ไม่อนุญาตเครื่องเสมือนที่นี่) จากนั้นสคริปต์เพื่อปรับใช้ repos svn เอง

สิ่งนี้ต้องการแผนผังไดเรกทอรีของไฟล์ (ไฟล์เสริม) variable.yml ที่จะรวมเข้าด้วยกันและไม่ส่งข้อยกเว้นหากมีที่หายไป

เริ่มต้นด้วยการเปิดใช้งานการรวมตัวแปรใน ansible - โปรดทราบว่านี่เป็นการรวมแฮชแบบตื้น (ความลึก 1 ระดับ) และไม่ผสานการวนซ้ำแบบวนซ้ำอย่างสมบูรณ์

ansible.cfg

[defaults]
hash_behaviour=merge ;; merge rather than replace dictionaries http://docs.ansible.com/ansible/intro_configuration.html###hash-behaviour

เค้าโครงไดเรกทอรีที่ไม่สามารถเข้าถึงได้

/group_vars
└── all.yml

/playbooks
├── boostrap.yml
├── demo.yml
├── live.yml
└── sandbox.yml

/roles/deploy/
├── files
├── tasks
│   ├── includes.yml
│   ├── main.yml
└── vars
    ├── main.yml
    ├── project_1.yml
    ├── project_2.yml
    ├── demo
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    ├── live
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    └── sandbox
        ├── project_1.yml
        ├── project_2.yml   
        └── main.yml

บทบาท / ปรับ / งาน / includes.yml

นี่คือตรรกะหลักสำหรับแผนผังไดเรกทอรีของไฟล์ตัวแปรเสริม

;; imports in this order:
;; - /roles/deploy/vars/main.yml
;; - /roles/deploy/vars/{{ project_name }}.yml
;; - /roles/deploy/vars/{{ project_name }}/main.yml
;; - /roles/deploy/vars/{{ project_name }}/{{ project_env }}.yml
- include_vars:
    dir: 'vars'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

- include_vars:
    dir: 'vars/{{ env_name }}'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

group_vars / all.yml

กำหนดค่าตัวแปรเริ่มต้นสำหรับโครงการและผู้ใช้และสภาพแวดล้อมที่หลากหลาย

project_users:
    bootstrap:
        env:   bootstrap
        user:  ansible
        group: ansible
        mode:  755
        root:  /cs/ansible/
        home:  /cs/ansible/home/ansible/
        directories:
            - /cs/ansible/
            - /cs/ansible/home/

    live:
        env:   live
        user:  ansible-live
        group: ansible
        mode:  755
        root:  /cs/ansible/live/
        home:  /cs/ansible/home/ansible-live/

    demo:
        env:   demo
        user:  ansible-demo
        group: ansible
        mode:  755
        root:  /cs/ansible/demo/
        home:  /cs/ansible/home/ansible-demo/

    sandbox:
        env:   sandbox
        user:  ansible-sandbox
        group: ansible
        mode:  755
        root:  /cs/ansible/sandbox/
        home:  /cs/ansible/home/ansible-sandbox/    

project_env:  bootstrap
project_user: "{{ ansible_users[project_env] }}" ;; this will be retroactively updated if project_env is redefined later

บทบาท / ปรับ / vars / main.yml

ค่าเริ่มต้นของโครงการ

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

บทบาท / ปรับ / vars / project_1.yml

ค่าเริ่มต้นสำหรับ project_1

ansible_project:
  node_port:  4201
  nginx_port: 4401

บทบาท / ปรับ / vars / / main.yml สด

ค่าเริ่มต้นสำหรับสภาพแวดล้อมสดแทนที่ค่าเริ่มต้นของโครงการ

ansible_project:
  node_env: production

บทบาท / ปรับ / vars / สด / project_1.yml

แทนที่สุดท้ายสำหรับ project_1 ในสภาพแวดล้อมสด

ansible_project:
  nginx_port: 80

playbooks / demo.yml

กำหนดค่า playbooks แยกสำหรับแต่ละสภาพแวดล้อม

- hosts: shared_server
  remote_user: ansible-demo
  vars:
    project_env: demo
  pre_tasks:
    - debug: "msg='{{ facter_gid }}@{{ facter_fqdn }} ({{ server_pseudonym }})'"
    - debug: var=project_ssh_user
  roles:
    - { role: deploy, project_name: project_1 }

คำเตือน: เนื่องจากสภาพแวดล้อมทั้งหมดอาศัยอยู่ในโฮสต์เดียว playbooks ทั้งหมดจะต้องทำงานแยกกันมิฉะนั้น Ansible จะพยายามเรียกใช้สคริปต์ทั้งหมดในฐานะผู้ใช้เข้าสู่ระบบ ssh แรกและใช้ตัวแปรสำหรับผู้ใช้คนแรกเท่านั้น หากคุณต้องการเรียกใช้สคริปต์ทั้งหมดตามลำดับให้ใช้ xargs เพื่อรันสคริปต์แต่ละรายการเป็นคำสั่งแยกกัน

find ./playbooks/*.yml | xargs -L1 time ansible-playbook

1
- hosts: all
  vars_files: vars/vars.default.yml
  vars:
    optional_vars_file: "{{ lookup('first_found', 'vars/vars.yml', errors='ignore') }}"
  tasks:
  - when: optional_vars_file is file
    include_vars: "{{ optional_vars_file }}"

หมายเหตุ: การทดสอบพา ธ (คือไฟล์มีอยู่, ... ) ทำงานเฉพาะกับพา ธ สัมบูรณ์หรือพา ธ ที่สัมพันธ์กับไดเร็กทอรีการทำงานปัจจุบันเมื่อรันคำสั่ง ansible-playbook นี่คือเหตุผลที่เราใช้การค้นหา การค้นหายอมรับเส้นทางที่สัมพันธ์กับไดเรกทอรี playbook และส่งคืนเส้นทางสัมบูรณ์เมื่อมีไฟล์อยู่


0

หรือในทาง yaml เพิ่มเติม:

- hosts: webservers
  vars:
    paths_to_vars_files:
      - vars/{{ ansible_hostname }}.yml
      - vars/default.yml
  tasks:
    - include_vars: "{{ item }}"
      with_first_found: "{{ paths_to_vars_files }}"

นั่นคือแทนที่จะเขียนอาเรย์บนหนึ่งบรรทัดด้วยวงเล็บเหลี่ยมเช่น:

['path/to/file1', 'path/to/file2', ...]

ใช้วิธี yaml ในการเขียนค่าอาร์เรย์ในหลายบรรทัดเช่น:

- path/to/file1
- path/to/file2

ดังที่กล่าวมาแล้วจะมองหาไฟล์ vars ที่มีชื่อ{{ ansible_hostname }}.ymlและหากไม่มีอยู่ให้ใช้default.yml


คำตอบนี้ใช้รหัสเดียวกันกับรหัสนี้ยกเว้นว่าจะใช้ข้อมูลอื่น คือชื่อไฟล์แทน{{ ansible_hostname }}.yml ../path/to/file1ประเด็นคืออะไร? หนึ่งสามารถเพิ่มชื่อไฟล์อินพุตได้ไม่ จำกัด
techraf

@ techraf: โอเคฉันได้เพิ่มการชี้แจง / ขยายความเพิ่มเติมเกี่ยวกับสาเหตุที่ส่งคำตอบใหม่ เป็นเพราะความคิดเห็นของเซิร์ฟเวอร์ผิดพลาดไม่สนับสนุนตัวอย่างโค้ดหลายบรรทัดและฉันเพิ่งทำประเด็นที่อาร์เรย์ yaml นั้นบ่อยครั้ง (ดีกว่า?) เขียนในหลายบรรทัด ฉันก็ไม่เป็นไรถ้าคำตอบก่อนหน้านี้ได้รับการแก้ไขและรูปแบบอาร์เรย์หลายบรรทัดแสดงเช่นที่ฉันเห็นบ่อยขึ้น จากนั้นคำตอบของฉันสามารถลบได้
Donn Lee

ข้อความที่ทั้งสองจะถูกระบุไว้ในเอกสารเบิ้ลในบทYAML ข้อมูลพื้นฐานเกี่ยวกับ ความจริงที่ว่าคุณเห็นหนึ่งบ่อยกว่าอีกไม่ได้ทำให้คำตอบใหม่
techraf

0

ประกอบชิ้นส่วนต่าง ๆ เข้าด้วยกัน ... include_vars ด้วย clause ที่เป็นจริงเมื่อไฟล์มีอยู่ กล่าวคือ

vars:
  file_to_include: /path/to/file
tasks:
  - include_vars: "{{ file_to_include }}"
    when: file_to_include is exists

0

คำตอบใหม่โดยยึดตามเวอร์ชันล่าสุดของ Ansible โดยพื้นฐานแล้วคุณควรใช้with_first_foundพร้อมกับskip: trueข้ามภารกิจหากไม่พบไฟล์

- name: Include vars file if one exists meeting our condition.
  include_vars: "{{ item }}"
  with_first_found:
    - files:
        - vars/{{ variable_here }}.yml
      skip: true

สิ่งนี้ทำให้คุณไม่ต้องมีไฟล์ vars สำรองในรายการนั้น

ดูที่เกี่ยวข้อง: /programming//a/39544405/100134

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