'How can I add new line "\n" character to Ansible variable

How can I add new line "\n" characters to Ansible variable mailbody

I set the below variable to ansible's mail module body attribute.

   - set_fact:
       mailbody: "{{ mailbody | default('') + 'PROFILE_NAME:' +  PROFILE_NAME ~ '\n\nSERVER_NAME:' + SERVER_NAME ~ '\n\nNODE_NAME:' +  NODE_NAME ~ '\n\n\n\n' }}"

But the body of the email has '\n\n' printed instead of new lines.

Can you please suggest what changes are needed?



Solution 1:[1]

Please try something like this :

as stated on the documentation I share in comment "The difference between single quotes and double quotes is that in double quotes you can use escapes : foo: "a \t TAB and a \n NEWLINE"

so

1.first thing to try:

mailbody: "{{ mailbody | default('') + 'PROFILE_NAME:' +  PROFILE_NAME ~}} {{ 'SERVER_NAME:' + SERVER_NAME ~ }}\n\n{{'NODE_NAME:' +  NODE_NAME ~ }}\n\n\n\n"

2.if that doesn help then:

mailbody: >
   "{{ mailbody | default('') + 'PROFILE_NAME:' +  PROFILE_NAME ~}}"
   "{{ 'SERVER_NAME:' + SERVER_NAME ~ }}"
   "{{'NODE_NAME:' +  NODE_NAME ~ }}"

3.if still won't work:

 mailbody: | 
     "{{ mailbody | default('') + 'PROFILE_NAME:' +  PROFILE_NAME ~}}"
     "{{ 'SERVER_NAME:' + SERVER_NAME ~ }}"
     "{{'NODE_NAME:' +  NODE_NAME ~ }}"

4.if this still isn't working try removing double quotes to this last 2 and 3.

Solution 2:[2]

I created an example playbook using the 4th suggestion from MikZuit's answer with the literal block syntax and it works like a charm. It sets the variable with set_fact which I tried to both debug and copy (print to a file). This is it:

- name: variable test
  hosts: 127.0.0.1
  connection: local
  vars:
    mailbody: "I am a mail body."
    PROFILE_NAME: "my profile"
    SERVER_NAME: "myserver.example.org"
    NODE_NAME: "I feel on edge today."
  tasks:
    - name: variable test | set variable
      ansible.builtin.set_fact:
        mailbody: |
          {{ mailbody | default('') }}

          PROFILE_NAME: {{ PROFILE_NAME }}

          SERVER_NAME: {{ SERVER_NAME }}

          NODE_NAME: {{ NODE_NAME }}

    - name: variable test | print variable to stdout
      ansible.builtin.debug:
        var: mailbody
    - name: variable test | print variable to file
      ansible.builtin.copy:
        content: "{{ mailbody }}"
        dest: "/tmp/mailbody.txt"

When I run the playbook the debug output looks like this:

ok: [localhost] => {
    "mailbody": "I am a mail body.\n\nPROFILE_NAME: my profile\n\nSERVER_NAME: myserver.example.org\n\nNODE_NAME: I feel on edge today.\n"
}

Note that the debug module prints the output as JSON and escapes any special characters, unlike the copy module which, in this playbook, prints the following output to /tmp/mailbody.txt:

I am a mail body.

PROFILE_NAME: my profile

SERVER_NAME: myserver.example.org

NODE_NAME: I feel on edge today.

Some general notes:

Since v2.10 or so, Ansible has been strongly modularized. This means that task names should now be fully qualified collection names (e.g. ansible.builtin.copy instead of copy) in order to avoid possible name collisions with other collections. Also it does not accept any plays or tasks without a name anymore.

When using the literal block syntax, it will truncate trailing newlines (like the empty line after NODE_NAME: {{ NODE_NAME }}) down to at most one. Btw, you don't need any quotes inside these blocks except for literals in evaluated expressions, e.g. {{ mailbody | default('') }}.

Quoting in Ansible works very similar to quoting in Linux shells. Double quotes can evaluate expressions and escaped characters while single quotes pass everything "as is".

Concerning the unexpected end of print statement error in Ashar's comment: the error occurs because the concatenation operator (~) expects a second operand but instead finds closed curly braces which mark the end of the expression. Just delete all the tildes shown in your error message and you should be good to go.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MikZuit
Solution 2 Marcel B.