web-dev-qa-db-fra.com

ANSIBLE: puis-je utiliser vars_files lorsque certains fichiers n'existent pas

C'est la partie:

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

Si un fichier vars/vars.yml n'existe pas - voici une erreur.

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

Comment puis-je charger des variables supplémentaires à partir de ce fichier que s'il existe? (sans erreurs)

17
Sergey

C'est vraiment simple vraiment. Vous pouvez écraser vos différents éléments vars_files dans un seul tuple et une autre manière à parcourir automatiquement chacun d'entre eux jusqu'à ce qu'il trouve un fichier qui existe et chargez-le. Ex.:

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

Selon - Développeurs ansibles , le correct moyen de résoudre ce problème est d'utiliser quelque chose comme:

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

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

En outre, dit-on :

Ce qui précède ne chargera que le premier fichier trouvé et est plus flexible que d'essayer de le faire via le vars_files Mot-clé de langue.

11
tjanez

J'ai rencontré ce problème dans une configuration où je devais créer plusieurs environnements de déploiement (Live, Demo, Sandbox) sur le même serveur physique (pas autorisé les machines virtuelles ici), puis un script pour déployer des repos svn arbitraires

Cela nécessitait une arborescence de répertoires de fichiers variables (facultatif), qui fusionneraient à l'autre et ne jettent pas une exception si elle manque

Commencez par la mise en place de la fusion variable dans une ondulation - Notez que cela fait la fusion de hachage peu profonde (1 niveau de profondeur) et non une fusion profonde entièrement récursive

ansible.cfg

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

Disposition de répertoire ansible

/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

rôles/déploiement/tâches/inclut.yml

Ceci est la principale logique pour un arborescence de répertoires de fichiers variables optionnels.

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

Configurez les variables par défaut pour le projet et divers utilisateurs et environnements

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

rôles/déploiement/vars/main.yml

par défaut du projet

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

rôles/Déploiement/Vars/Project_1.yml

par défaut pour Project_1

ansible_project:
  node_port:  4201
  nginx_port: 4401

rôles/Déploieur/Vars/Live/Main.yml

les valeurs par défaut pour l'environnement en direct, remplacent les valeurs par défaut du projet

ansible_project:
  node_env: production

rôles/Déploieur/Vars/Live/Project_1.yml

nursons finaux pour le projet_1 dans l'environnement en direct

ansible_project:
  nginx_port: 80

playbooks/Demo.yml

Configurez les playbooks séparés pour chaque environnement

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

AVERTISSEMENT: Étant donné que tous les environnements vivent sur un seul hôte, tous les playbooks doivent être exécutés individuellement, sinon une tentative ansite tentent d'exécuter tous les scripts en tant que premier utilisateur de connexion SSH et n'utilisez que les variables pour le premier utilisateur. Si vous devez exécuter tous les scripts séquentiellement, utilisez Xargs pour les exécuter chacun comme des commandes distinctes.

find ./playbooks/*.yml | xargs -L1 time ansible-playbook
2
James McGuigan
- 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 }}"

Remarque: Les tests de cheminement (fichier sont-ils existent, ...) ne fonctionnent qu'avec des chemins ou des chemins absolus par rapport au répertoire de travail actuel lors de l'exécution de la commande Ansible-Playbook. C'est la raison pour laquelle nous avons utilisé la recherche. La recherche accepte les chemins par rapport au répertoire de lecture et renvoie la voie absolue lorsque le fichier existe.

2
Ejez

Assembler diverses pièces ensemble ... Inclure_vars avec une clause WHERE qui est vrai lorsque le fichier existe. c'est à dire.

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

Nouvelle réponse basée sur les dernières versions ansibles - essentiellement, vous devez utiliser with_first_found, de même que skip: true Pour ignorer la tâche si aucun fichier n'est trouvé.

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

Cela le rend afin que vous n'ayez pas besoin d'avoir un fichier varys de Fallback dans cette liste.

Voir Connexes: https://stackoverflow.com/a/395444405/100134

0
geerlingguy