Bookmark this page

Guided Exercise: Modifying and Copying Files to Hosts

In this exercise, you use standard Ansible modules to create, install, edit, and remove files on managed hosts and manage the permissions, ownership, and SELinux contexts of those files.

Outcomes

  • Retrieve files from managed hosts, by host name, and store them locally.

  • Create playbooks that use common file management modules from the ansible.builtin Ansible Content Collection such as copy, file, lineinfile, and blockinfile.

As the student user on the workstation machine, use the lab command to prepare your system for this exercise.

This command prepares your environment and ensures that all required resources are available.

[student@workstation ~]$ lab start file-manage

Procedure 5.1. Instructions

  1. As the student user on workstation, change to the /home/student/file-manage working directory. Create a playbook called secure_log_backups.yml in the current working directory. Configure the playbook to use the ansible.builtin.fetch module to retrieve the /var/log/secure log file from each of the managed hosts and store them on the control node. The playbook should create the secure-backups directory with subdirectories named after the host name of each managed host. Store the backup files in their respective subdirectories.

    1. Navigate to the /home/student/file-manage working directory.

      [student@workstation ~]$ cd ~/file-manage
      [student@workstation file-manage]$
    2. Create the secure_log_backups.yml playbook. It should contain a play to fetch the log files from all managed hosts in the inventory, and the play should connect as the remote root user:

      ---
      - name: Use the fetch module to retrieve secure log files
        hosts: all
        remote_user: root
    3. Add a task to the play in the secure_log_backups.yml playbook. That task must retrieve the /var/log/secure log file from the managed hosts and store it in the ~/file-manage/secure-backups directory. The ansible.builtin.fetch module creates the ~/file-manage/secure-backups directory if it does not exist. Use the flat: no parameter to ensure the default behavior of appending the host name, path, and file name to the destination.

        tasks:
          - name: Fetch the /var/log/secure log file from managed hosts
            ansible.builtin.fetch:
              src: /var/log/secure
              dest: secure-backups
              flat: no
    4. Before running the playbook, use the ansible-navigator run --syntax-check command to verify its syntax. Correct any errors before moving to the next step.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout secure_log_backups.yml --syntax-check
      playbook: /home/student/file-manage/secure_log_backups.yml
    5. Use the ansible-navigator run command to execute the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout secure_log_backups.yml
      
      PLAY [Use the fetch module to retrieve secure log files] ******************
      
      TASK [Gathering Facts] ****************************************************
      ok: [servera.lab.example.com]
      ok: [serverb.lab.example.com]
      
      TASK [Fetch the /var/log/secure file from managed hosts] ******************
      changed: [serverb.lab.example.com]
      changed: [servera.lab.example.com]
      
      PLAY RECAP ****************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    6. Confirm that the playbook retrieved the /var/log/secure files from the managed hosts.

      [student@workstation file-manage]$ tree -F secure-backups
      secure-backups
      ├── servera.lab.example.com/
      │   └── var/
      │       └── log/
      │           └── secure
      └── serverb.lab.example.com/
          └── var/
              └── log/
                  └── secure
  2. Create the copy_file.yml playbook in the current working directory. Configure a play in the playbook that connects as the root user and copies the /home/student/file-manage/files/users.txt file to all managed hosts.

    1. Edit the copy_file.yml playbook so that it contains one play that starts with the following initial content:

      ---
      - name: Using the copy module
        hosts: all
        remote_user: root
    2. Add a task to the play that uses the ansible.builtin.copy module to copy the /home/student/file-manage/files/users.txt file to all managed hosts. It must set the following parameters for the users.txt file:

      ParameterValues
      src files/users.txt
      dest /home/devops/users.txt
      owner devops
      group devops
      mode u+rw,g-wx,o-rwx
      setype samba_share_t
        tasks:
          - name: Copy a file to managed hosts and set attributes
            ansible.builtin.copy:
              src: files/users.txt
              dest: /home/devops/users.txt
              owner: devops
              group: devops
              mode: u+rw,g-wx,o-rwx
              setype: samba_share_t
    3. Use the ansible-navigator run --syntax-check command to verify the syntax of the copy_file.yml playbook.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout copy_file.yml --syntax-check
      playbook: /home/student/file-manage/copy_file.yml
    4. Run the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout copy_file.yml
      
      PLAY [Using the copy module] *******************************************
      
      TASK [Gathering Facts] *************************************************
      ok: [serverb.lab.example.com]
      ok: [servera.lab.example.com]
      
      TASK [Copy a file to managed hosts and set attributes] *****************
      changed: [servera.lab.example.com]
      changed: [serverb.lab.example.com]
      
      PLAY RECAP *************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    5. Use the ls -Z command as user devops on the servera machine to verify the attributes of the users.txt file on the managed hosts.

      [student@workstation file-manage]$ ssh devops@servera 'ls -Z'
      unconfined_u:object_r:samba_share_t:s0 users.txt
  3. In a preceding step, you set the samba_share_t SELinux type field for the users.txt file. However, you have decided that you want to change the SELinux context on that file to the default context from the SELinux policy of each system.

    Create a playbook called selinux_defaults.yml in the current working directory. Configure a play in the playbook that uses the ansible.builtin.file module to set the default SELinux context on the file /home/devops/users.txt for user, role, type, and level fields.

    Note

    To avoid unnecessary changes to the file context by your plays, normally you would also edit the play in copy_file.yml to remove the setype keyword from the ansible.builtin.copy task in its play.

    For simplicity, this exercise skips this step.

    1. Create the selinux_defaults.yml playbook. It should contain the following play that uses the ansible.builtin.file module to set the default context on the file.

      ---
      - name: Using the file module to ensure SELinux file context
        hosts: all
        remote_user: root
        tasks:
          - name:  SELinux file context is set to defaults
            ansible.builtin.file:
              path: /home/devops/users.txt
              seuser: _default
              serole: _default
              setype: _default
              selevel: _default
    2. Use the ansible-navigator run --syntax-check command to verify the syntax of the selinux_defaults.yml playbook.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout selinux_defaults.yml --syntax-check
      playbook: /home/student/file-manage/selinux_defaults.yml
    3. Run the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout selinux_defaults.yml
      
      PLAY [Using the file module to ensure SELinux file context] ************
      
      TASK [Gathering Facts] *************************************************
      ok: [serverb.lab.example.com]
      ok: [servera.lab.example.com]
      
      TASK [SELinux file context is set to defaults] *************************
      changed: [serverb.lab.example.com]
      changed: [servera.lab.example.com]
      
      PLAY RECAP *************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    4. Use the ls -Z command as user devops on the servera machine to verify the default file attributes of unconfined_u:object_r:user_home_t:s0.

      [student@workstation file-manage]$ ssh devops@servera 'ls -Z'
      unconfined_u:object_r:user_home_t:s0 users.txt
  4. Create a playbook called add_line.yml in the current working directory. Configure a play in the playbook to use the ansible.builtin.lineinfile module to append the line This line was added by the lineinfile module. to the /home/devops/users.txt file on all managed hosts.

    1. Create the add_line.yml playbook. It should contain the following play:

      ---
      - name: Add text to an existing file
        hosts: all
        remote_user: devops
        tasks:
          - name: Add a single line of text to a file
            ansible.builtin.lineinfile:
              path: /home/devops/users.txt
              line: This line was added by the lineinfile module.
              state: present
    2. Use ansible-navigator run --syntax-check command to verify the syntax of the add_line.yml playbook.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout add_line.yml --syntax-check
      playbook: /home/student/file-manage/add_line.yml
    3. Run the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout add_line.yml
      
      PLAY [Add text to an existing file] ************************************
      
      TASK [Gathering Facts] *************************************************
      ok: [serverb.lab.example.com]
      ok: [servera.lab.example.com]
      
      TASK [Add a single line of text to a file] *****************************
      changed: [servera.lab.example.com]
      changed: [serverb.lab.example.com]
      
      PLAY RECAP *************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    4. Use the cat command as the devops user on the servera machine to verify the content of the users.txt file on the managed hosts.

      [student@workstation file-manage]$ ssh devops@servera 'cat users.txt'
      This line was added by the lineinfile module.
  5. Create a playbook called add_block.yml in the current working directory. Configure a play in the playbook to use the ansible.builtin.blockinfile module to append the following block of text to the /home/devops/users.txt file on all managed hosts.

    This block of text consists of two lines.
    They have been added by the blockinfile module.
    1. Create the add_block.yml playbook. Edit it to contain the following play:

      ---
      - name: Add block of text to a file
        hosts: all
        remote_user: devops
        tasks:
          - name: Add a block of text to an existing file
            ansible.builtin.blockinfile:
              path: /home/devops/users.txt
              block: |
                This block of text consists of two lines.
                They have been added by the blockinfile module.
              state: present
    2. Use the ansible-navigator run --syntax-check command to verify the syntax of the add_block.yml playbook.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout add_block.yml --syntax-check
      playbook: /home/student/file-manage/add_block.yml
    3. Run the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout add_block.yml
      
      PLAY [Add block of text to a file] ****************************************
      
      TASK [Gathering Facts] ****************************************************
      ok: [serverb.lab.example.com]
      ok: [servera.lab.example.com]
      
      TASK [Add a block of text to an existing file] ****************************
      changed: [servera.lab.example.com]
      changed: [serverb.lab.example.com]
      
      PLAY RECAP ****************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    4. Use the cat command as the devops user on the servera machine to verify the correct content of the /home/devops/users.txt file on the managed host.

      [student@workstation file-manage]$ ssh devops@servera 'cat users.txt'
      This line was added by the lineinfile module.
      # BEGIN ANSIBLE MANAGED BLOCK
      This block of text consists of two lines.
      They have been added by the blockinfile module.
      # END ANSIBLE MANAGED BLOCK
  6. Create a playbook called remove_file.yml in the current working directory. Configure a play in the playbook to use the ansible.builtin.file module to remove the /home/devops/users.txt file from all managed hosts.

    1. Create the remove_file.yml playbook. Edit it to contain the following play:

      ---
      - name: Use the file module to remove a file
        hosts: all
        remote_user: devops
        tasks:
          - name: Remove a file from managed hosts
            ansible.builtin.file:
              path: /home/devops/users.txt
              state: absent
    2. Use the ansible-navigator run --syntax-check command to verify the syntax of the remove_file.yml playbook.

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout remove_file.yml --syntax-check
      playbook: /home/student/file-manage/remove_file.yml
    3. Run the playbook:

      [student@workstation file-manage]$ ansible-navigator run \
      > -m stdout remove_file.yml
      
      PLAY [Use the file module to remove a file] *******************************
      
      TASK [Gathering Facts] ****************************************************
      ok: [serverb.lab.example.com]
      ok: [servera.lab.example.com]
      
      TASK [Remove a file from managed hosts] ***********************************
      changed: [serverb.lab.example.com]
      changed: [servera.lab.example.com]
      
      PLAY RECAP ****************************************************************
      servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
      serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    4. Use the ls -l command as the devops user on the servera machine to confirm that the users.txt file no longer exists on the managed hosts.

      [student@workstation file-manage]$ ssh devops@servera 'ls -l'
      total 0

Finish

On the workstation machine, change to the student user home directory and use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish file-manage

This concludes the section.

Revision: rh294-9.0-c95c7de