29

I found this blockinfile issue, where a user suggested adding a number after the "|" in the "block: |" line, but gives a syntax error. Basically, I want to use blockinfile module to add a block of lines in a file, but I want the block to be indented 6 spaces in the file. Here's the task

- name: Added a block of lines in the file
  blockinfile:
  dest: /path/some_file.yml
  insertafter: 'authc:'
  block: |
    line0
      line1
      line2
      line3
        line4

I expect

  authc:
    line0
      line1
      line2
      line3
        line4

but get

  authc:
line0
  line1
  line2
  line3
    line4

Adding spaces in the beginning of the lines does not do it. How can I accomplish this?

techraf
  • 64,883
  • 27
  • 193
  • 198
Chris F
  • 14,337
  • 30
  • 94
  • 192

5 Answers5

64

You can use a YAML feature called "Block Indentation Indicator":

- name: Added a block of lines in the file
  blockinfile:
  dest: /path/some_file.yml
  insertafter: 'authc:'
  block: |2
      line0
        line1
        line2
        line3
          line4

It's all about the 2 after the |

References:

Update:

As Dave correctly pointed out, this does not work anymore in the current version 2.14.2 of ansible :( I'd suggest using the comment workaround from the next answer

antex
  • 794
  • 7
  • 8
  • 3
    [**Currently broken**](https://groups.google.com/forum/#!topic/ansible-project/mmXvhTh6Omo) since Ansible version `2.1` and at least up to `2.3.1.0` – Serge Stroobandt Jun 15 '17 at 11:48
  • 14
    A couple things, first this should be the correct answer! Second, this is [**not broken**](https://github.com/ansible/ansible/issues/23777) but rather the interpretation of the block starts at the "Block Indentation Indicator" as the answer correctly demonstrates. Notice that the first line in the code in the answer has four spaces underneath the `block: |2` line. That is interpreted to mean the following block to insert starts after 2 spaces (on each line), which will result in the file having 2 spaces before the first line when inserted. – ddrake12 Nov 28 '17 at 18:05
  • The vertical bar is the virtual left margin for the block. The integer specifies the number of spaces to indent relative to the left margin. Simply align content under the bar, plus one space. The result will be indented by 2 or 4 or whatever value provided for the integer. – Rick O'Shea Mar 07 '22 at 23:30
  • 2
    Nope, this does not work on current versions of ansible. Seems to only indent up to 2 spaces. After that will only do 2 spaces no matter what. – Dave Jan 25 '23 at 14:34
7

The number after the | describes how many lines the block is indented. For example:

  block: |2
    insert some stuff
  ^^ 2 spaces here.

  block: |4
      insert some stuff
  ^^^^ 4 spaces here.

If you like to indent your line in the destination file you can use this workaround:

  block: |
    # this is a comment
      insert some stuff

In this example, the line # this is a comment will not be indented and the line insert some stuff will have 2 leading spaces.

Eddie Parker
  • 4,770
  • 3
  • 35
  • 43
Nortol
  • 399
  • 3
  • 9
  • This example fails. The VERTICAL BAR acts as the left margin for your content. Nothing to do with "block:" or anything else. If you want to indent N spaces, align content under the bar, one space to the right. Put the indentation value N to the right of the vertical bar. – Rick O'Shea Mar 07 '22 at 23:33
2

I was trying to use YAML feature called "Block Indentation Indicator" from the other answer, but it did not work for me (ansible 2.9.10.post0). Ugly, but working solution is:

- name: docker-compose.yml - service has links to another container
  lineinfile:
    path: "/path/to/docker-compose.yml"
    insertafter: "service:"
    line: "    links:\n      - apache2:proxy.example.com\n      - apache2:proxy2.example.com"

You basically need to put as many spaces as necessary before elements. And use \n for newlines.

Ivan Ermilov
  • 1,769
  • 1
  • 11
  • 10
  • 1
    This solution, while it works the first time, is not idempotent and will continuously add the same lines each time the playbook is run. – Tony May 05 '23 at 11:08
1

You can use the Jinja2 indent filter to add your desired indentation:

- name: Added a block of lines in the file
  blockinfile:
  dest: /path/some_file.yml
  insertafter: 'authc:'
  block: |
    {% filter indent(width=4, first=true) %}
    line0
      line1
      line2
      line3
        line4
    {% endfilter %}

Result:

  authc:
    line0
      line1
      line2
      line3
        line4
stackprotector
  • 10,498
  • 4
  • 35
  • 64
0

If you want to insert multiple blocks in the same file by using blockinfile and also want to keep the leading spaces before each line you are going to add, you could do something like this with each block having a different marker:

- name: Name 1
  blockinfile:
    path: /folder/file.yaml
    insertafter: 'insert after this text'
    block: |
      # Adding parameters:
          line 1
          line 2
    marker: "# BLOCK 1"

- name: Name 2
  blockinfile:
    path: /folder/file.yaml
    insertbefore: "insert before this text"
    block: |
      # Adding parameters:
          line 3
            line 4
            line 5
    marker: "# BLOCK 2"

- name: Name 3
  blockinfile:
    path: /folder/file.yaml
    insertbefore: "insert before this text"
    block: |
      # Adding parameters:
        line 6
            line 7
            line 8
          line 9
    marker: "# BLOCK 3"