Ansible - File System operation

About

File system operations in Ansible

Management

Get file name

  • When looping through files, you can get the basename with the template filter basename
{{ item|basename }}
  • Filename without extension (splits the extension only after the last dot)
{{ item | basename | splitext | first }}

More managing-file-names-and-path-names

Create a directory

http://docs.ansible.com/file_module.html

# create a directory if it doesn't exist
- file:
    path: /etc/some_directory
    state: directory
    mode: 0755

Create a file

- name: Touch a file, using symbolic modes to set the permissions (equivalent to 0644)
  file:
    path: /etc/foo.conf
    state: touch
    mode: u=rw,g=r,o=r

Ownership

Ownership recursively

- file:
    path: /etc/some_directory
    state: directory
    group: 'foo'
    owner: 'bar'
    recurse: yes

Move

from local to host

  • with copy: The copy module has a recursive parameter. See Ansible - Copy Module (Remote File System operation)
- name: Copy ansible inventory file to client (command on  multi-line - break + indent any continuation lines)
  copy: 
    src: hosts 
    dest: /etc/ansible/hosts
    owner: root 
    group: root 
    mode: 0644
    backup: yes

where the relative search path for src is

  • for a play, playdir/{files|vars|templates}/, playdir/.
  • for a role, rolename/{files|vars|templates}/, rolename/tasks/.

The synchronize-module is more efficient than copy for a large number of files. The synchronize module wraps rsync.

from same host

- name: Move file
  become: yes
  become_user: "{{ prometheus_user_name }}"
  shell:
    cmd: "/bin/cp {{ prometheus_install_dir }}/{{ prometheus_node_exporter_name }}/* {{ prometheus_home }}"

from Host to host

You use normally 'rsync' for this purpose (with the synchronize module or at the command line)

Example:

  • without the rsync daemon passing the ssh password via sshpass at the command line,
- name: 'Copy the keystore from the master'
  delegate_to: "{{ hostvars[ groups['gateway'][0] ].inventory_hostname }}"
  shell: |
    sshpass -p "{{ ansible_password }}" rsync \
      -v \
      {{ src_path_file }} \
      {{ ansible_user }}@{{ ansible_host }}:{{ dst_path_file }}
  register: keystore_copy
  changed_when: keystore_copy.rc != 0
  • or with the synchronize module <note important>If the rsync daemon is not running, you may got a permission denied</note>
- hosts: all
  tasks:    
   - name: Copy Remote-To-Remote (from serverA to serverB)
     synchronize: src=/copy/from_serverA dest=/copy/to_serverB
     delegate_to: serverA
     when: inventory_hostname = serverB

Loop

One directory

- name: display content of all .txt files in dir
  debug: msg={{lookup('fileglob', '/my/path/*.txt')}}

- name: "Connection templates that add the environment as prefix {{ env_name}}"
    become: yes
    become_user: '{{ bdm_install_user }}'
    template:
      src: '{{ item }}'
      dest: '{{ connection_dst }}/{{ item|basename }}_{{ env_name|upper }}'
      owner: '{{ bdm_install_user }}'
      group: '{{ bdm_install_group }}'
      mode: 0770
    with_fileglob: 'template/connections/*'

The tree (recursive)

- name: "Creating connection file properties from template for the environment {{ env_name }}"
    become: yes
    become_user: '{{ bdm_install_user }}'
    template:
      src: '{{ item.src }}'
      dest: '{{ bdm_connection_dst }}/{{ item.path }}_{{ env_name|upper }}'
      owner: '{{ bdm_install_user }}'
      group: '{{ bdm_install_group }}'
      mode: 0770
    with_filetree: 'template/connection/{{ env_name|lower }}'
    when: item.state == 'file'

Conditional task

based on file presence

- name: Stat the {{ infa_domain_file }} 
  stat:
    path: '{{infa_domain_file}}'
  register: infa_domain_file

- name: Install if the domain file does not exist
  become: yes
  become_user: '{{ bdm_install_user }}'
  import_tasks: user_install.yml
  when: not infa_domain_file.stat.exists

You can also just fail

- name: Check if Gogs is already installed.
  stat:
    path: "{{ gogs_bin_file }}"
  register: gogs_bin

- name: Download
  when: gogs_bin.stat.islnk is not defined
  block:
  ...

Creation of file with content

You create a file with you own content (ie string) with the copy module

Example with a private key that was encrypted with encrypt string

- name: Private Key
  copy:
    content: "{{ private_key }}"
    dest: "/path/to/my/key"
    owner: 'root'
    group: 'root'
    mode: "0600"

Presence of text in file

Block In File

blockinfile:
    path: /etc/hosts
    block: |
      {{ item.ip }} {{ item.name }}
    marker: "# {mark} ANSIBLE MANAGED BLOCK Hostname"
  with_items:
    - { name: "{{ hostname }}  {{ hostname.split('.', 1)[0] }}", ip: 127.0.0.1 }

Lineinfile

Example:

- name: 'Configure the Java memory requirement'
  lineinfile:
    dest: "{{nexus_application_directory}}/bin/nexus.vmoptions"
    state: present
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  with_items:
    - regexp: '^-Xms(\\d+)m$'
      line: '-Xms{{nexus_java_memory}}m'
    - regexp: '^-Xmx(\\d+)m$'
      line: '-Xmx{{nexus_java_memory}}m'
    - regexp: '^-XX:MaxDirectMemorySize=(\\d+)m$'
      line: '-XX:MaxDirectMemorySize={{nexus_java_memory}}m'
  notify:
    - nexus reload

Powered by ComboStrap