Comment créer un fichier vide avec Ansible?

115

Quelle est la manière la plus simple de créer un fichier vide à l'aide d'Ansible? Je sais que je peux enregistrer un fichier vide dans le filesrépertoire, puis le copier sur l'hôte distant, mais je trouve cela quelque peu insatisfaisant.

Une autre façon consiste à toucher un fichier sur l'hôte distant:

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555

Mais ensuite, le fichier est touché à chaque fois, apparaissant comme une ligne jaune dans le journal, ce qui est également insatisfaisant ...

Y a-t-il une meilleure solution à ce problème simple?

Dokaspar
la source

Réponses:

189

La documentation du module de fichiers dit

Si state=file, le fichier ne sera PAS créé s'il n'existe pas, consultez le module de copie ou de modèle si vous souhaitez ce comportement.

Nous utilisons donc le module de copie, qui permet force=node créer un nouveau fichier vide uniquement lorsque le fichier n'existe pas encore (si le fichier existe, son contenu est conservé).

- name: ensure file exists
  copy:
    content: ""
    dest: /etc/nologin
    force: no
    group: sys
    owner: root
    mode: 0555

C'est une solution déclarative et élégante.

René Pijl
la source
15
@ ÁkosVandra: En fait, ce n'est pas le cas. Voir: force: no.
palacsint
Merci - c'est une solution beaucoup plus agréable que file / touch ou la réponse stat / file acceptée, et c'est facile à faire avec "with_items"
Réaliste
Excellente réponse, vous êtes curieux de savoir comment créer deux fichiers vides en utilisant la même construction que vous avez fournie?
Tasdik Rahman
Existe-t-il un moyen de créer le répertoire parent s'il n'existe pas, ou dois-je le faire séparément?
falsePockets
Vous devez vous assurer que le répertoire parent existe et qu'il est accessible en écriture. Voir stackoverflow.com/questions/22844905/…
René Pijl
37

Quelque chose comme ça (en utilisant d'abord le statmodule pour collecter des données à ce sujet, puis en filtrant à l'aide d'un conditionnel) devrait fonctionner:

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555
  when: p.stat.exists is defined and not p.stat.exists

Vous pourriez également être en mesure de tirer parti de la changed_whenfonctionnalité.

ceejayoz
la source
20
peut-être que ça devrait être: "quand: pas p.stat.exists"
piro
28

Une autre option, en utilisant le module de commande:

- name: Create file
  command: touch /path/to/file
  args:
    creates: /path/to/file

L'argument «crée» garantit que cette action n'est pas effectuée si le fichier existe.

Leynos
la source
5
Vous devez éviter la commande autant que possible car elle n'est pas idempotente. ryaneschinger.com/blog/…
redshark1802
4
@ redshark1802 D'accord. Bien que dans ce cas, la tâche soit idempotente, puisqu'elle ne sera pas exécutée si "/ chemin / vers / fichier" existe déjà. Je pense que la solution de René Pijl est la plus semblable à Ansible des trois principales réponses, et certainement celle que vous devriez utiliser si vous devez définir la propriété, le mode, etc.
Leynos
15

En vous basant sur la réponse acceptée, si vous souhaitez que le fichier soit vérifié pour les autorisations à chaque exécution, et que celles-ci soient modifiées en conséquence si le fichier existe, ou créez simplement le fichier s'il n'existe pas, vous pouvez utiliser ce qui suit:

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin 
        owner=root
        group=sys
        mode=0555
        state={{ "file" if  p.stat.exists else "touch"}}
AllBlackt
la source
3
Cette réponse est géniale en raison de la flexibilité qu'elle vous donne dans la définition des attributs de fichier d'un fichier s'il n'existe pas.
Dejay Clayton
10

file: path=/etc/nologin state=touch

Equivalent complet de touch (nouveau dans 1.4+) - utilisez stat si vous ne voulez pas changer l'horodatage du fichier.

jalmasi
la source
3
Ce n'est pas idempotent, la date du fichier sera modifiée à chaque exécution du playbook ansible.
Jérôme B
3
@ Jérôme B Nouveau dans Ansible 2.7: vous pouvez le rendre idempotent avec file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
GregV
8

Le module de fichiers permet de toucher le fichier sans modifier son heure.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: u+rw,g-wx,o-rwx
    modification_time: preserve
    access_time: preserve

Référence: https://docs.ansible.com/ansible/latest/modules/file_module.html

Ravi Kulkarni
la source
C'est la bonne réponse pour ansible 2.7+, mais il manque des informations importantes.
Honza
3

Il s'avère que je n'ai pas assez de réputation pour mettre cela en commentaire, ce qui serait un endroit plus approprié pour cela:

Ré. Réponse d'AllBlackt, si vous préférez le format multiligne d'Ansible, vous devez ajuster les citations state(j'ai passé quelques minutes à travailler sur cela, alors j'espère que cela accélère quelqu'un d'autre),

- stat:
    path: "/etc/nologin"
  register: p

- name: create fake 'nologin' shell
  file:
    path: "/etc/nologin"
    owner: root
    group: sys
    mode: 0555
    state: '{{ "file" if  p.stat.exists else "touch" }}'
Andrew Richards
la source
0

Pour créer un fichier dans la machine distante avec la commande ad-hoc

ansible client -m file -a"dest=/tmp/file state=touch"

S'il vous plait corrigez moi si je me trompe

vajrala chakradhar reddy
la source
0

Modifié si le fichier n'existe pas. Créez un fichier vide.

- name: create fake 'nologin' shell
  file:
    path: /etc/nologin
    state: touch
  register: p
  changed_when: p.diff.before.state == "absent"
Dmitry Balashov
la source
0

Une combinaison de deux réponses, avec une torsion. Le code sera détecté comme modifié, lorsque le fichier est créé ou l'autorisation mise à jour.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: 0644
    modification_time: preserve
    access_time: preserve
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644"

et une version qui corrige également le propriétaire et le groupe et le détecte comme modifié lorsqu'il corrige ces derniers:

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    state: touch
    mode: 0644
    owner: root
    group: root
    modification_time: preserve
    access_time: preserve
  register: p
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644" or
    p.diff.before.owner|default(0) != 0 or
    p.diff.before.group|default(0) != 0
Roch Bourdon
la source
ansible 2.7+ uniquement - cela devrait être mentionné.
Honza