Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I copy a multi-line string to a file with literal newlines?

So I know I can do something like this:

copy:
  dest: /etc/issue
  content: |
    Hello
    World

But this doesn't work:

vars:
  login_banner_text: !!str |-
    "Hello\nWorld"
tasks:
  - name: Set TTY login banner
    copy:
      dest: /etc/issue
      content: "{{ login_banner_text }}"

The newline character is printed straight to the file, without parsing, i.e. it's a single line populated with \n strings. I'd like to do this without copying a file into place, because I need to copy this text to two files.

For one file, the \n strings need to remain unparsed, so it's written to file as a single line. For the other, I want the \n to be interpreted, so that the text is expanded into multiple lines.

The first file is being modified using the ini_file module. This task works as expected using the explicit \n in the variable declaration.

- name: "Set message"
  ini_file:
    dest: /etc/dconf/db/gdm.d/00-security-settings
    section: org/gnome/login-screen
    option: banner-message-text
    value: string '{{ login_banner_text }}'
    create: yes
    tags:
      - always

However, other modules behave this way as well.

If I copy a file into place, the rather long text (not "Hello World") has to be maintained in two places.

Update

I found, what I think is, a better way of doing this, based on this post. It stores the banner in a separate file, and then uses that to modify both configuration files. So the value is only stored in one place. However, the answer given by @larsks does answer the question as it was originally posed.

- hosts: 127.0.0.1
  connection: local
  vars:
    login_banner_text: "{{ lookup('file', 'login_banner.txt') }}"
  tasks:
    - name: "Set the GNOME3 Login Warning Banner Text"
      ini_file:
        dest: /etc/dconf/db/gdm.d/00-security-settings
        section: org/gnome/login-screen
        option: banner-message-text
        value: '{{ login_banner_text | to_json }}'
        create: yes
      tags:
        - always
    - name: "Set the TTY Login Warning Banner Text"
      copy:
        dest: '/etc/issue'
        content: "{{ '\n' + login_banner_text + '\n' }}"
      tags:
        - always
like image 692
orodbhen Avatar asked Apr 05 '19 17:04

orodbhen


1 Answers

You already know how to specify a value with literal newlines; you're doing it when setting the content key in your first example. You can set the value of a variable the same way:

---
- hosts: localhost
  gather_facts: false
  vars:
    mytext: |
      Hello
      World
  tasks:
    - copy:
        dest: ./output.txt
        content: "{{ mytext }}"

This would create output.txt with the content:

Hello
World

If instead your goal is to have content like this...

[org/gnome/login-screen]

banner-message-text = "Hello\nWorld"

...then you don't want literal newlines, you want a literal \n, in which case this would work:

---
- hosts: localhost
  gather_facts: false
  vars:
    mytext: "Hello\\nWorld"

  tasks:
    - ini_file:
        dest: ./example.ini
        section: org/gnome/login-screen
        option: banner-message-text
        value: "{{ mytext }}"
        create: true

Which would result in:

[org/gnome/login-screen]
banner-message-text = Hello\nWorld

If you wanted the value in the config file quoted, then:

    - ini_file:
        dest: ./example.ini
        section: org/gnome/login-screen
        option: banner-message-text
        value: '"{{ mytext }}"'
        create: true

Which gets you:

[org/gnome/login-screen]
banner-message-text = "Hello\nWorld"

You could also do it like this:

---
- hosts: localhost
  gather_facts: false
  vars:
    mytext: |-
      Hello
      World

  tasks:
    - ini_file:
        dest: ./example.ini
        section: org/gnome/login-screen
        option: banner-message-text
        value: '{{ mytext|to_json }}'
        create: true

This gets you the same output as the previous example.

like image 149
larsks Avatar answered Oct 30 '22 12:10

larsks