Ansible: Posso usar vars_files quando alguns arquivos não existem

16

Essa é a parte:

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

Se um arquivo vars/vars.yml não existir - aqui está um erro.

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

Como posso carregar variáveis adicionais deste arquivo somente se ele existir? (sem erros)

    
por Sergey 17.04.2014 / 16:18

6 respostas

25

É bem simples na verdade. Você pode esmagar seus diferentes itens vars_files em uma única tupla e Ansible passará automaticamente por cada um até encontrar um arquivo existente e carregá-lo. E.x .:

vars_files:
  - [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]
    
por 05.06.2014 / 08:17
10

De acordo com desenvolvedores Ansible , a maneira correta de resolver isto é para usar algo como:

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

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

Além disso, eles dizem :

The above will properly load only the first file found, and is more flexible than trying to do this via the vars_files language keyword.

    
por 24.11.2014 / 13:07
2

Encontrei esse problema em uma configuração em que precisei criar vários ambientes de implementação (ao vivo, demo, sandbox) para o mesmo servidor físico (não permitidas máquinas virtuais aqui) e um script para implantar repositórios svn arbitrários

Isso exigia uma árvore de diretórios de arquivos (opcionais) variable.yml, que se fundiriam ontop uns dos outros e não lançariam uma exceção se algum deles faltasse

Comece ativando a mesclagem de variáveis em ansible - note que isso faz mesclagem superficial de hash (1 nível de profundidade) e não mesclagem profunda totalmente recursiva

ansible.cfg

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

Layout de diretório anível

/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

Esta é a principal lógica para uma árvore de diretórios de arquivos variáveis opcionais.

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

Configure variáveis padrão para o projeto e vários usuários e ambientes

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

roles / deploy / vars / main.yml

padrões de projeto

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

roles / deploy / vars / project_1.yml

padrões para project_1

ansible_project:
  node_port:  4201
  nginx_port: 4401

roles / deploy / vars / live / main.yml

padrões para o ambiente ao vivo, sobrescreve os padrões do projeto

ansible_project:
  node_env: production

roles / deploy / vars / live / project_1.yml

substituições finais para project_1 no ambiente ao vivo

ansible_project:
  nginx_port: 80

playbooks / demo.yml

Configurar livros de exercícios separados para cada ambiente

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

AVISO: Como todos os ambientes residem em um único host, todos os playbooks devem ser executados individualmente, caso contrário, o Ansible tentará executar todos os scripts como o primeiro usuário ssh e usar as variáveis apenas para o primeiro usuário. Se você precisar executar todos os scripts sequencialmente, use xargs para executá-los como comandos separados.

find ./playbooks/*.yml | xargs -L1 time ansible-playbook
    
por 03.01.2017 / 18:51
0

Ou de uma maneira mais 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 }}"

Ou seja, em vez de escrever um array em uma linha com colchetes, como:

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

Use a maneira yaml de escrever valores de matriz em várias linhas, como:

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

Como mencionado, ele procura por um arquivo vars chamado {{ ansible_hostname }}.yml e, se ele não existir, usa default.yml

    
por 22.12.2016 / 02:40
0

Reunindo várias partes juntas ... include_vars com uma cláusula when que é verdadeira quando o arquivo existe. ou seja,

vars:
  file_to_include: /path/to/file
tasks:
  - include_vars: "{{ file_to_include }}"
    when: file_to_include is exists
    
por 18.09.2018 / 00:10
0

Nova resposta com base nas versões mais recentes do Ansible - basicamente, você deve usar with_first_found , juntamente com skip: true , para ignorar a tarefa se nenhum arquivo for encontrado.

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

Isso faz com que você não precise ter um arquivo de fallback vars nessa lista.

Veja a relação: link

    
por 05.10.2018 / 20:40

Tags