Managing File Operations With Ansible

Managing File Operations With Ansible

In this article I will demonstrate how we can perform different file operations with Ansible.

Ansible copy module - copying files over remote machines

In one single playbook I will include all possible use cases for copying files over remote nodes.

---
- hosts: worker1
  become: yes
  gather_facts: false

  tasks:
  - name: Task1 - copy file from local machine to remote server
    copy:
      src: /home/ansible_user/ansible/file_ops/file-normal.txt
      dest: /home/ansible_user

  - name: Task2 - copy file from local machine to remote server along with ownership and permissions
    copy:
      src: /home/ansible_user/ansible/file_ops/file-owner-perms.txt
      dest: /home/ansible_user/
      owner: ansible_user
      group: ansible_user
      mode: '0777'

  - name: Task3 - copy directory from local machine to remote server
    copy:
      src: /home/ansible_user/ansible/file_ops/dir1
      dest: /home/ansible_user
      owner: ansible_user
      group: ansible_user
      mode: '0755'

  - name: Task4 - copy multiple files from local machine to remote server
    copy:
      src: /home/ansible_user/ansible/file_ops/dir2
      dest: /home/ansible_user
      owner: ansible_user
      group: ansible_user
      mode: '0755'
    with_items:
      - file-multi1.txt
      - file-multi2.txt

  - name: Task5 - copy file from local machine to remote server along with backup option
    copy:
      src: /home/ansible_user/ansible/file_ops/file-backup.txt
      dest: /home/ansible_user/
      owner: ansible_user
      group: ansible_user
      mode: '0755'
      backup: yes

  - name: Task6 - copy file from local machine to remote server along with content option
    copy:
      content: "Welcome to LearnCodeOnline"
      dest: /home/ansible_user/file-content.txt
      owner: ansible_user
      group: ansible_user
      mode: '0755'

  - name: Task7 - copy file from local machine to remote server along with force option
    copy:
      src: /home/ansible_user/ansible/file_ops/file-force.txt
      dest: /home/ansible_user/file-force.txt
      owner: ansible_user
      group: ansible_user
      mode: '0755'
      force: no

Let us understand all the tasks one by one.

  • Task1 will simply copy file-normal.txt from local machine to worker1
  • Task2 will copy file-owner-perms.txt with the ownership and permissions I've mentioned in the play i.e. ownership - ansible_user and permissions as 0777
  • Task3 will copy dir1 directory from local machine to worker1

For copying directories, you have two options. If you put a / after the directory name in src, then it will copy anything inside that directory to the destination folder. If you don’t put the / in src, then it will first create the directory at the destination and then copy everything inside.

  • Task4 is used when we don't want to copy the entire directory to remote machine, instead just to copy few files.
  • Task5 will create a backup file including the timestamp information when someone changes the source file. (You can try changing content of file-backup.txt file run the playbook again.)
  • Task6 is used when you want to copy a file from local machine to remote server along with the customized content in it.
  • Task7 will be used when we don't want to overwrite the file. The default is yes, which will replace the remote file when contents are different than the source. If no, the file will only be transferred if the destination does not exist.

Here is the list of files/directories on our local machine which we wants to copy over.

file_ops $ tree
.
├── copy.yml
├── dir1
│   ├── abc
│   └── test
├── dir2
│   ├── file-multi1.txt
│   └── file-multi2.txt
├── dir_copy.yml
├── file-backup.txt
├── file-content.txt
├── file-force.txt
├── file-normal.txt
├── file-owner-perms.txt
└── myinventory

2 directories, 12 files

Let us execute the playbook.

Copy-1.png

Now verify the results on the remote system one by one task.

Copy-results.png

As I have mentioned above to test the backup option you need to change the content of file-backup.txt file and run the playbook again. You will see a backup file created on the remote system with old content.

Copy-backup.png

For more details on copy module follow official docs .

Ansible lineinfile module – Manage lines in text files

We use this module when we want to insert a line in file or replace an existing line using a back-referenced regular expression.

Not recommended if you want to change multiple lines or block.

lineinfile example 1 - Modifying a line

Here is our playbook which will go and change a setting in a file.

---
- hosts: worker1
  become: yes
  gather_facts: false
  tasks:

  - name: Ensure SELinux is set to enforcing mode
    lineinfile:
      path: /etc/selinux/config
      regexp: '^SELINUX='
      line: SELINUX=enforcing

Let us run the playbook.

file_ops $ ansible-playbook -i myinventory lineinfile.yml

lineinfile.png

Verify the changes on worker1 node.

file_ops $ ansible -i myinventory worker1 -m shell -a "cat /etc/selinux/config | grep enforcing"
worker1 | CHANGED | rc=0 >>
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
SELINUX=enforcing

lineinfile example 2 - Checking existence of a string in a file and add the line after it

---
- name: Testing lineinfile module
  hosts: worker1
  become: yes
  tasks:
    - name: "Check existence of a String in a file and add the line after it"
      lineinfile:
        path: /home/ansible_user/lineinfile_test_file1.txt
        insertafter: "ExampleName"
        line: "lineinfile_insert_test"
        firstmatch: yes
        state: present
        create: yes
        backup: yes

Here we are adding a line containing string ‘lineinfile_insert_test’ after the line that matches ‘ExampleName’. Similarly the option ‘insertbefore’ can be used to add the line before the specific line if the match is found. create option will create the file if doesn't exists already.

Let's run the playbook.

lineinfile-2.png

Verify the outcome:

file_ops $ ansible -i myinventory worker1 -m shell -a "cat /home/ansible_user/lineinfile_test_file1.txt"
worker1 | CHANGED | rc=0 >>
ExampleName
lineinfile_insert_test

Please go through the official docs to get more idea about other options.

Ansible replace module – Replace all instances of a particular string

This module is used when we want to replace all instances of a pattern within a file.

Lets understand this by our example playbook.

---
- name: Testing lineinfile module
  hosts: worker1
  become: yes
  tasks:
    - name: check the content of file before replace operation
      shell: 'cat /home/ansible_user/replace_example.txt'
      register: var_output_1

    - name: check the content of file before replace operation
      debug:
        var: var_output_1.stdout_lines

    - name: "Check existence of a String in a file and add the line after it"
      replace:
        path: /home/ansible_user/replace_example.txt
        regexp: "Hello Learners"
        replace: "Hello LearnCodeOnline"
        backup: yes

    - name: check the content of file after replace operation
      shell: 'cat /home/ansible_user/replace_example.txt'
      register: var_output_2

    - name: check the content of file after replace operation
      debug:
        var: var_output_2.stdout_lines

In this example we are replacing every occurrence of Hello Learners in /home/ansible_user/replace_example.txt file on worker1 node and displaying the content of that file before and after the replace operation.

Let us execute the playbook.

file_ops $ ansible-playbook -i myinventory  replace.yml

replace-module-1.png

That's all for this article.

I have covered here the most important and frequently used File Operations modules but yes there are many others available which you can go through one by one and try implementing them.

Ref: docs.ansible.com/ansible/2.9/modules/list_o..

Hope you like the article. Stay Tuned for more.

Thank you. Happy learning!

Did you find this article valuable?

Support Learn Code Online by becoming a sponsor. Any amount is appreciated!