Using Ansible blockinfile Module

Ansible blockinfile module is used to insert/update/remove a block of lines. The block will be surrounded by a marker, like begin and end, to make the task idempotent.

If you want to modify/ insert only a line, use lineinfile module. You can find the documentation in

You can find more details of blockinfile module in Ansible documentation.  This post gives a basic idea and some examples of doing config management with blockinfile module.

Inserting a Block of Lines

To insert a block of lines, at the very least, you need to give the Path of the file and a block of lines.

Here I am trying to insert the block of two lines in the file block_output.txt. The dest parameter sets the path of remote file and block parameter sets the block of lines.

- hosts: blocks
  tasks:
  - name: Ansible Insert multiple lines using blockinfile
    blockinfile:
      dest: /home/mdtutorials2/block_output.txt
      block: |
        These lines are added by blockinfile module
        Check out the marker lines
      backup: yes

Note 1: Use path parameter if you have Ansible version >2.3.

Note 2: If you don’t give the block parameter, then any block with the default markup line will be removed.

Note 3: By default, the block will be inserted at the end of the file.

Note 4: ‘|’ is the literal block character in YAML.

Note 5: Use the backup parameter to create a backup file if something changed. It can help if any failure happened. The backup file includes the timestamp. eg: block_output.txt.8588.2017-03-12@05:44:27

In the block_output.txt below, you can see the inserted lines. Note that, above and below the inserted block is a marker ‘#BEGIN/END ANSIBLE MANAGED BLOCK’. This makes sure that on subsequent runs the block won’t be inserted again. You can have multiple managed blocks using different markup. For instance, you can see in the execution summary below, for the second run, that there is no change.

Inserting a group of lines using blockinfile module

 

Customized marker line

You can customize the marker line. This is helpful when you need to control multiple blocks in the same file. The unique marker lines will make sure each blockinfile operations change only the intended blocks.

Or maybe ‘#’ is not the comment character in the particular file you need to change.

You can customize the marker line like below.

marker: "<!-- {mark} Adding IP address -->"

This will add the marker ‘BEGIN Adding IP address’ and ‘End Adding IP address’ to the block. You can change the ‘{mark}’ also.

Updating a Block of Lines

You can update an inserted block of lines by changing the content of the block parameter. Ansible first the check if a block with the marker is present. Then it will update the remote file with the new block.

- hosts: blocks
  tasks:
  - name: Updating a line using Ansible blockinfile module
    blockinfile:
      dest: /home/mdtutorials2/config_management.txt
      marker: <!-- {mark} Adding IP address -->
      block: |
        These lines were updated by blockinfile module
        Check out the marker lines

The above task will update the block with the given marker line.

Removing a block of lines

You can remove a block by choosing the absent option for the state parameter.

- hosts: blocks
  tasks:
  - name: Removing a line using blockinfile
    blockinfile:
      dest: /home/mdtutorials2/block_output.txt
      marker: <!-- {mark} Adding IP address -->
      state: absent

Adding Block After/Before a Particular Pattern Using Regex

By default, the block will be inserted at the EOF. But we can control where to insert using Regex.You can either insert below a pattern using the insertafter parameter or above a line using the insertbefore parameter.

In the below script I am trying to insert a block, before the pattern “line starting with line no”.

- hosts: blocks
  tasks:
  - name: Ansible blockinfile insertafter and insertbefore
    blockinfile:
      dest: /home/mdtutorials2/block_output.txt
      block: |
        Line inserted using Regex
        Ansible blockinfile module
      insertbefore: "^line no"

blockinfile using regex

Here there are multiple lines with the regex “^line no”. So the block was inserted just before the last occurrence of the pattern, “line no 3”.

Note 1: If the same pattern occurs multiple times, then the last match will be taken.

Note 2: You can insert at the beginning of the file using insertbefore: BOF

Giving variables in the block

You can add variables in the blocks by just enclosing the variable within {{ }}. The following example will replace the variable ‘var1’ with the value before modifying the remote file.

- hosts: blocks
  vars:
    var1: 'world'
  tasks:
    - name: Ansible blockinfile variable example
      blockinfile:
        dest: /home/mdtutorials2/block_output.txt
        marker: <!-- {mark} variable replace -->
        block: |
          hello {{ var1 }}

Adding Multiple blocks using with_items

We can add multiple blocks in a file using blockinfile and with_items. But one of the common mistakes people make is not using a unique marker. If you use a marker like below, then the content will be overwritten multiple times.

marker: <!-- {mark} blockinfile with items -->

To solve this, you can use a unique marker like below.

- hosts: blocks
  tasks:
  - name: Using Ansible blockinfile with_items
    blockinfile:
      dest: /home/mdtutorials2/block_output.txt
      block: |
        {{ item.name }} -- {{ item.line }}
      marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.name }}"
    with_items:
      - { name: line1, line: hello1 }
      - { name: line2, line: hello2 }
      - { name: line3, line: hello3 }

Ansible blockinfile with_items

Note 1: With_items should be written at the level of the module name. And not at the level of its parameters. If you get an error “the field ‘args’ has an invalid value, which appears to include a variable that is undefined.”, this might be the reason.

Inserting contents from an external file

You can also use the contents from an external file using the lookup plugin. The file should be available in your Ansible control machine.

block: "{{ lookup('file', '/home/user/localfile.txt') }}"

 

ISSUE:

If you get the following error,

blockinfile unsupported parameter for module: path

check your ansible version. If the version is below 2.3, use dest instead. It was renamed to ‘path‘ only in version 2.3]

For more details on how to change file contents, you can check the details of all the parameters in Ansible documentation.

Check out the Ansible user module  to see how to mange the user accounts in Linux.