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 항목을 단일 튜플로 스쿼시 할 수 있으며 Ansible은 존재하는 파일을 찾아로드 할 때까지 각 튜플을 자동으로 통과합니다. 전의:

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

4
Ansible 개발자 에 따르면 이 솔루션은 처음 발견 된 파일뿐만 아니라 모든 파일을로드합니다.
tjanez

10

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

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

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

또한 그들은 말합니다 :

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


"첫 번째 파일 만 발견됨"-아이디어는 일부 변수를 재정의하는 것이 아니라 모든 변수를 재정의하는 것이 었습니다.
Sergey

@ Sergey, 귀하의 질문을 다시 읽으면 원하는 것이 약간 다릅니다. 이것을 지적 해 주셔서 감사합니다. 다른 사람이 유용하다고 생각하는 경우 답변을 그대로 두겠습니다.
tjanez '11

1
것을 제외하고 include_vars작업의 역할에 비해 변수의 높은 우선 순위를 줄 것이다 defaults또는vars
알렉스 F

2

동일한 물리적 서버 (여기서는 가상 머신은 허용되지 않음)에 여러 배치 환경 (라이브, 데모, 샌드 박스)을 작성하고 임의의 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

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


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 : 좋아, 나는 새로운 답변이 제출 된 이유에 대한 설명 / 증폭을 추가했습니다. serverfault 주석은 다중 라인 코드 스 니펫을 지원하지 않기 때문에 yaml 배열이 여러 줄에 자주 작성되는 것이 좋습니다 (바람직하게는?). 더 자주 볼 수 있듯이 이전 답변을 편집하고 여러 줄 배열 형식을 표시하면 괜찮습니다. 그런 다음 내 답변을 삭제할 수 있습니다.
Donn Lee

두 표기법 모두 YAML 기본 장의 Ansible 문서에 지정되어 있습니다. 당신이 다른 것보다 더 자주 볼 수 있다는 사실은 아직 새로운 답이되지 않습니다.
techraf

0

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

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.