web-dev-qa-db-fra.com

La tâche d'inclusion Ansible uniquement si le fichier existe

J'essaie d'inclure un fichier uniquement s'il existe. Cela permet de personnaliser les "tâches/rôles" entre les "tâches/rôles" existants, si nécessaire par l'utilisateur de mon rôle. J'ai trouvé ça:

- include: ...
  when: condition

Mais la documentation Ansible précise que:

"Toutes les tâches sont évaluées, mais le conditionnel est appliqué à chaque tâche" - http://docs.ansible.com/playbooks_conditionals.html#applying-when-to-roles-and-includes

Alors

- stat: path=/home/user/optional/file.yml
  register: optional_file
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists

Echouera si le fichier en cours d’inclusion n’existe pas. J'imagine qu'il pourrait exister un autre mécanisme permettant à un utilisateur d'ajouter des tâches à une recette existante. Je ne peux pas laisser l'utilisateur ajouter un rôle après le mien, car il n'aurait pas le contrôle de la commande: son rôle sera exécuté après le mien.

28
Leito

Merci à tous pour votre aide! Je réponds à ma propre question après avoir finalement essayé toutes les réponses et le code de ma propre question dans Ansible d'aujourd'hui: ansible 2.0.1.0

Mon code original semble fonctionner maintenant, sauf que le fichier facultatif que je cherchais se trouvait sur mon ordinateur local. Je devais donc exécuter stat via local_action et définir become: no pour cette tâche particulière, afin que personne ne tente pas de réaliser Sudo. dans ma machine locale et erreur avec: "Sudo: un mot de passe est requis\n"

- local_action: stat path=/home/user/optional/file.yml
  register: optional_file
  become: no
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists
10
Leito

Le with_first_found conditionnel peut accomplir cela sans stat ou local_action. Cette conditionnelle parcourra une liste de fichiers locaux et exécutera la tâche avec item défini sur le chemin du premier fichier existant. Inclure skip: true sur les options with_first_found l'empêchera d'échouer si le fichier n'existe pas.

Exemple:

- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - include: "{{ item }}"
      with_first_found:
        - files:
            - /home/user/optional/file.yml
          skip: true
26
Dave Konopka

J'utilise quelque chose de similaire mais pour le module de fichier et ce qui m'a été difficile, c'est de vérifier la définition de la variable, essayez par exemple

when: optional_file.stat.exists is defined and optional_file.stat.exists

la tâche ne sera exécutée que lorsque la variable existe.

5
olluch

En utilisant ansible-2.1.0, je peux utiliser des extraits comme ceci dans mon livre de jeu:

- hosts: all
  gather_facts: false
  tasks:
    - name: Determine if local playbook exists
      local_action: stat path=local.yml
      register: st

- include: local.yml
  when: st.stat.exists

Je n'obtiens aucune erreur/échec lorsque local.yml n'existe pas et que le playbook est exécuté (en tant que playbook, ce qui signifie qu'il commence par la ligne hosts:, etc.)

Vous pouvez faire la même chose au niveau de la tâche à la place avec un code similaire . Utiliser stat semble fonctionner correctement.

2
Kayvan Sylvan

Je pourrais passer du temps ici à critiquer les dispositions de gestion des erreurs d’Anse, mais en bref, vous avez raison et vous ne pouvez pas utiliser le module stat à cette fin pour des raisons données.

La solution la plus simple pour la plupart des problèmes rencontrés est de le faire en dehors de celui-ci. Par exemple.

- Shell: test -f /home/user/optional/file.yml     # or use -r if you're too particular.
  register: optional_file
  failed_when: False
- include: /home/user/optional/file.yml
  when: optional_file.rc == 0
- debug: msg="/home/user/optional/file.yml did not exist and was not included"
  when: optional_file.rc != 0

* failed_whenajouté pour éviter que l'hôte ne soit exclu de tâches ultérieures lorsque le fichier n'existe pas.

2
Kashyap

Il existe également la possibilité d'utiliser un filtre Jinja2 pour cela:

 - set_fact: optional_file="/home/user/optional/file.yml"

 - include: ....
   when: optional_file|exists
1
mbarthelemy

La meilleure option que j'ai proposée jusqu'à présent est la suivante:

- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"

Ce n'est pas exactement un "si-existe", mais cela donne le même résultat aux utilisateurs de votre rôle. Créez quelques variables dans votre rôle et un fichier vide par défaut. Les filtres Jinja "default" et "lookup" se chargent de revenir sur le fichier vide au cas où la variable ne serait pas définie.

Pour plus de commodité, un utilisateur peut utiliser la variable {{ playbook_dir }} pour définir les chemins:

hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml" 
1
Ramon de la Fuente

Si je ne me trompe pas, vous voulez continuer le livret même si la déclaration est fausse?

Si oui, veuillez ajouter cette ligne après when:

ignore_errors: True

Donc, vos tâches ressembleront à ceci:

- stat: path=/home/user/optional/file.yml
  register: optional_file
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists
  ignore_errors: True

Faites-le moi savoir, si je comprends bien votre question, ou peut aider davantage. Merci

1
Arbab Nazar