Derek Mahar
Derek Mahar

Reputation: 28386

How do I eliminate extra whitespace between macro calls in Ansible Jinja2 templates?

Given Ansible Jinja2 template:

{% macro directive(name, value) %}
{% if value is defined %}
{{ name }}={{ value }}
{% endif %}
{% endmacro -%}

# {{ ansible_managed }}

[Unit]
{{ directive('Description', service.description) }}
{{ directive('Documentation', service.documentation) }}
{{ directive('Requires', service.requires) }}

with service variable definition:

service:
  description: Test Template
  requires: multi-user.target

how can I change the template to eliminate extra newlines in resulting output:

# Ansible managed

[Unit]
Description=Test Template


Requires=multi-user.target

so that it instead looks like:

# Ansible managed

[Unit]
Description=Test Template
Requires=multi-user.target

?

Upvotes: 1

Views: 1714

Answers (1)

techraf
techraf

Reputation: 68589

Consider the following:

{% macro directive(name, value) %}
{% if value is defined %}
{{ name }}={{ value }} # a newline hardcoded in macro follows
{% endif %}
{% endmacro -%}

# {{ ansible_managed }}

[Unit 1]
{{ directive('Description', service.description) }}# 1st hardcoded newline follows
{{ directive('Documentation', service.documentation) }}# 2nd hardcoded newline follows
{{ directive('Requires', service.requires) }}# 3rd hardcoded newline follows

It produces:

# Ansible managed

[Unit 1]
Description=Test Template # a newline hardcoded in macro follows
# 1st hardcoded newline follows
# 2nd hardcoded newline follows
Requires=multi-user.target # a newline hardcoded in macro follows
# 3rd hardcoded newline follows

Even though documentation on whitespace control states "a single trailing newline is stripped if present", it does not apply to variable substitution, so even though the result of the macro contains a newline character at the end, this particular newline will not be stripped.

Just like it's not stripped if you define:

variable_with_newline: "value\n"

and run a template:

start-{{ variable_with_newline }}-end

it produces:

start-value
-end

To fix to the template either remove the hardcoded newlines:

[Unit]
{{ directive('Description', service.description) }}{{ directive('Documentation', service.documentation) }}{{ directive('Requires', service.requires) }}

or add explicit whitespace stripping:

[Unit]
{{ directive('Description', service.description) }}
{{- directive('Documentation', service.documentation) }}
{{- directive('Requires', service.requires) }}

or

[Unit]
{{ directive('Description', service.description) -}}
{{ directive('Documentation', service.documentation) -}}
{{ directive('Requires', service.requires) }}

Upvotes: 1

Related Questions