Search code examples
yamlansibleansible-template

Printing a variable value indented in a YAML file using ansible


I'm generating a Behat config file using Ansible. This configuration file is a YAML file. I'm using a Jinja2 template like this:

default:
  paths:
    features: '../all/tests/features'
  filters:
    tags: "~@api&&~@drush"
  extensions:
    Behat\MinkExtension\Extension:
    files_path: '{{ project_docroot }}/sites/all/tests/files'
      files_path: '{{ project_docroot }}'
      goutte: ~
      selenium2: ~
      base_url: '{{ base_url }}'
    Drupal\DrupalExtension\Extension:
      blackbox: ~
      drush_driver: "drush"
      drush:
        root: "{{ project_docroot }}"
      api_driver: "drupal"
      drupal:
        drupal_root: "{{ project_docroot }}"
      region_map:
{{ project_behat_region_map }}
      selectors:
{{ project_behat_selectors }}

And the following defined vars:

project_behat_region_map: |
        content: "#content"
        footer: "#footer"
        header: "#header"
        header bottom: "#header-bottom"
        navigation: "#navigation"
        highlighted: "#highlighted"
        help: "#help"
        bottom: "#bottom"

project_behat_selectors: |
        message_selector: '.messages'
        error_message_selector: '.messages.error'
        success_message_selector: '.messages.status'
        warning_message_selector: '.messages.warning'

As you can see the variable values are indented, but when pasted into the Jinja2 template the lost indentation:

default:
  paths:
    features: '../all/tests/features'
  filters:
    tags: "~@api&&~@drush"
  extensions:
    Behat\MinkExtension\Extension:
    files_path: '/var/www//bacteriemias/docroot/sites/all/tests/files'
      files_path: '/var/www//bacteriemias/docroot'
      goutte: ~
      selenium2: ~
      base_url: 'http://bacteriemias.me'
    Drupal\DrupalExtension\Extension:
      blackbox: ~
      drush_driver: "drush"
      drush:
        root: "/var/www//bacteriemias/docroot"
      api_driver: "drupal"
      drupal:
        drupal_root: "/var/www//bacteriemias/docroot"
      region_map:
content: "#content"
footer: "#footer"
header: "#header"
header bottom: "#header-bottom"
navigation: "#navigation"
highlighted: "#highlighted"
help: "#help"
bottom: "#bottom"


      selectors:
message_selector: '.messages'
error_message_selector: '.messages.error'
success_message_selector: '.messages.status'
warning_message_selector: '.messages.warning'

This is not valid YAML. How can I print a variable with indentation in Jinja2?


Solution

  • It turns out that the problem can be solved using the indent Jinja2 filter.

    indent(s, width=4, first=False)

    Return a copy of the passed string, each line indented by 4 spaces. The first line is not indented. If you want to change the number of spaces or indent the first line too you can pass additional parameters to the filter:

    {{ mytext|indent(2, true) }} indent by two spaces and indent the first line too.

    So, in my case is:

    default:
      paths:
        features: '../all/tests/features'
      filters:
        tags: "~@api&&~@drush"
      extensions:
        Behat\MinkExtension\Extension:
        files_path: '{{ project_docroot }}/sites/all/tests/files'
          files_path: '{{ project_docroot }}'
          goutte: ~
          selenium2: ~
          base_url: '{{ base_url }}'
        Drupal\DrupalExtension\Extension:
          blackbox: ~
          drush_driver: "drush"
          drush:
            root: "{{ project_docroot }}"
          api_driver: "drupal"
          drupal:
            drupal_root: "{{ project_docroot }}"
          region_map:
    {{ project_behat_region_map | indent( width=8, first=True) }}
    
          selectors:
    {{ project_behat_selectors | indent( width=8, first=True) }}
    

    indent(s, width=4, first=False)

    Update May, 2022

    Before Jinja 2.10 the first parameter was called indentfirst.

    I've updated the code to the new name.