Ansible : 일부 파일이 없을 때 vars_files를 사용할 수 있습니까 – vars/vars.yml 파일 vars/vars.yml이 존재하지

그 부분입니다.

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

파일 vars/vars.yml이 존재하지 않는 경우 -여기에 오류가 있습니다.

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

존재하는 경우에만이 파일에서 추가 변수를로드하려면 어떻게해야합니까? (오류 없음)



답변

정말 간단합니다. 다른 vars_files 항목을 단일 튜플로 스쿼시 할 수 있으며 Ansible은 존재하는 파일을 찾아로드 할 때까지 각 튜플을 자동으로 통과합니다. 전의:

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


답변

Ansible 개발자 에 따르면 이를 해결 하는 올바른 방법은 다음과 같은 것을 사용하는 것입니다.

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

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

또한 그들은 말합니다 :

위의 방법은 찾은 첫 번째 파일 만 올바르게로드하며 vars_fileslanguage 키워드 를 통해이 작업을 수행하는 것보다 융통성이 있습니다.


답변

동일한 물리적 서버 (여기서는 가상 머신은 허용되지 않음)에 여러 배치 환경 (라이브, 데모, 샌드 박스)을 작성하고 임의의 svn repos를 배치하는 스크립트를 작성해야하는 설정에서이 문제점이 발생했습니다.

여기에는 (선택적) variable.yml 파일의 디렉토리 트리가 필요합니다.이 트리는 서로 위에 병합되어 누락 된 경우 예외를 발생시키지 않습니다.

가변 병합을 가능하게하여 시작하십시오-이것은 얕은 해시 병합 (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

roles / deploy / tasks / 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

roles / deploy / vars / project_1.yml

project_1의 기본값

ansible_project:
  node_port:  4201
  nginx_port: 4401

역할 / 배치 /vars/live/main.yml

라이브 환경의 기본값, 프로젝트 기본값을 재정의

ansible_project:
  node_env: production

역할 / 배치 /vars/live/project_1.yml

실제 환경에서 project_1에 대한 최종 재정의

ansible_project:
  nginx_port: 80

플레이 북 /demo.yml

각 환경에 대해 별도의 플레이 북 구성

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

경고 : 모든 환경이 단일 호스트에 존재하므로 모든 플레이 북을 개별적으로 실행해야합니다. 그렇지 않으면 Ansible은 모든 스크립트를 첫 번째 ssh 로그인 사용자로 실행하려고 시도하고 첫 번째 사용자의 변수 만 사용합니다. 모든 스크립트를 순차적으로 실행해야하는 경우 xargs를 사용하여 각각 별도의 명령으로 실행하십시오.

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


답변

- 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 명령을 실행할 때 현재 작업 디렉토리에 상대적인 절대 경로 또는 경로에서만 작동합니다. 이것이 우리가 조회를 사용한 이유입니다. 조회는 플레이 북 디렉토리에 상대적인 경로를 허용하고 파일이 존재할 때 절대 경로를 반환합니다.


답변

또는 더 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


답변

파일이 존재할 때 true 인 when 절을 사용하여 다양한 조각을 함께 … include_vars 즉

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


답변

최신 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