escaping curly braces in lineinfile module

905 views
Skip to first unread message

Laci

unread,
May 12, 2020, 3:32:12 PM5/12/20
to Ansible Project
I am new in Ansible world. I spent some time solving this but got to the point when I need to ask:
I have a file called jobs.inc and I need to add six lines with Ansible.

Here is an example
% cat jobs.inc
Job {
  Name    = "server1"
  Client  = "server1-fd"
  JobDefs = "DefaultJob"
}
Job {
  Name    = "server2"
  Client  = "server2-fd"
  JobDefs = "DefaultJob"
}


How would I add server3?

The following playbooks are the ones I tried and they didn't work. Thank you!

1)
  - name: add new lines to jobs.inc
    lineinfile:
      path: /conf.d/jobs.inc
      line: "{{ item }}"
    with_items:
      - Job {% raw %}{{% endraw %} 
      -    Name    = "{{ remote_shorthost }}"
      -    Client  = "{{ remote_shorthost }}-fd"
      -    JobDefs = "DefaultJob"
      - {% raw %}}{% endraw %}

2)
  - name: add new lines to jobs.inc
    lineinfile:
      path: /conf.d/jobs.inc
      line: "{{ item }}"
    with_items:
      - Job {
      -    Name    = "{{ remote_shorthost }}"
      -    Client  = "{{ remote_shorthost }}-fd"
      -    JobDefs = "DefaultJob"
      - }

3)
  vars:
   curly1_variable: !unsafe '{'
   curly2_variable: !unsafe '}'
  tasks:
  - name: add new lines to jobs.inc
    lineinfile:
      path: /conf.d/jobs.inc
      line: "{{ item }}"
    with_items:
      - Job !unsafe curly1_variable
      -    Name    = "{{ remote_shorthost }}"
      -    Client  = "{{ remote_shorthost }}-fd"
      -    JobDefs = "DefaultJob"
      -  !unsafe curly2_variable

Vladimir Botka

unread,
May 12, 2020, 3:47:30 PM5/12/20
to Laci, ansible...@googlegroups.com
On Tue, 12 May 2020 12:32:11 -0700 (PDT)
Laci <lac...@gmail.com> wrote:

> % cat jobs.inc
> Job {
> Name = "server1"
> Client = "server1-fd"
> JobDefs = "DefaultJob"
> }
> Job {
> Name = "server2"
> Client = "server2-fd"
> JobDefs = "DefaultJob"
> }
>
> How would I add server3?

The best option in this case would be "template"
https://docs.ansible.com/ansible/latest/modules/template_module.html#template-template-a-file-out-to-a-remote-server

If the editing can't be avoided then "blockinfile" might do the job
https://docs.ansible.com/ansible/latest/modules/blockinfile_module.html

HTH,

-vlado

Laci

unread,
May 12, 2020, 4:42:00 PM5/12/20
to Ansible Project
Thank you vlado, this worked for me:

    blockinfile:
      path: /conf.d/jobs.inc
      marker: " "
      block: |
        Job {
          Name    = "{{ remote_shorthost }}"
          Client  = "{{ remote_shorthost }}-fd"
          JobDefs = "DefaultJob"
         }
      backup: yes

Vladimir Botka

unread,
May 12, 2020, 11:47:02 PM5/12/20
to Laci, ansible...@googlegroups.com
On Tue, 12 May 2020 13:42:00 -0700 (PDT)
Laci <lac...@gmail.com> wrote:

> Thank you vlado, this worked for me:
>
> blockinfile:
> path: /conf.d/jobs.inc
> marker: " "
> block: |
> Job {
> Name = "{{ remote_shorthost }}"
> Client = "{{ remote_shorthost }}-fd"
> JobDefs = "DefaultJob"
> }
> backup: yes

You're welcome, Laci. It's necessary to add that the task is not idempotent.
It will repeatedly add the same block into the file. Quoting from
"blockinfile" parameter "marker":
https://docs.ansible.com/ansible/latest/modules/blockinfile_module.html#parameter-marker

"Using a custom marker without the {mark} variable may result in the block
being repeatedly inserted on subsequent playbook runs."

Best practice is to make the "marker" unique. For example

- blockinfile:
path: jobs.inc
marker: "# {mark} {{ remote_shorthost }}"
block: |
Job {
Name = "{{ remote_shorthost }}"
Client = "{{ remote_shorthost }}-fd"
JobDefs = "DefaultJob"
}
backup: yes

would create (if the variable "remote_shorthost: server3")

shell> cat jobs.inc
Job {
Name = "server1"
Client = "server1-fd"
JobDefs = "DefaultJob"
}
Job {
Name = "server2"
Client = "server2-fd"
JobDefs = "DefaultJob"
}
# BEGIN server3
Job {
Name = "server3"
Client = "server3-fd"
JobDefs = "DefaultJob"
}
# END server3

Such marker makes the task idempotent and also helps to create a loop, if
needed. For example

- blockinfile:
path: jobs.inc
marker: "# {mark} {{ item.remote_shorthost }}"
block: |
Job {
Name = "{{ item.remote_shorthost }}"
Client = "{{ item.remote_shorthost }}-fd"
JobDefs = "{{ item.jobdefs }}"
}
backup: yes
loop: "{{ my_servers }}"
vars:
my_servers:
- remote_shorthost: server3
jobdefs: DefaultJob
- remote_shorthost: server4
jobdefs: DefaultJob

Fit the first character(s) of the marker to the comment syntax of the language
the block shall be included in.

HTH,

-vlado

Laci

unread,
May 14, 2020, 10:31:36 AM5/14/20
to Ansible Project
Actually this is my goal.
We are going to have add new servers every time to this file.

So the following lines will be repeated X times
 Job { 
      Name    = "serverX" 
      Client  = "serverX-fd" 
      JobDefs = "DefaultJob" 

Laci

unread,
May 14, 2020, 11:16:20 AM5/14/20
to Ansible Project
Another task I'm working on is a conditional blockinfile, something like: 
if OS=BSD do this, if Linux do that.

I need this because there is a slightly different configuration for them:

BSD:
 Job { 
      Name    = "serverX" 
      Client  = "serverX-fd" 
      JobDefs = "DefaultJob" 
     }

Linux:
 Job { 
      Name    = "serverX" 
      Client  = "serverX-fd" 
      JobDefs = "DefaultJob" 
      FileSet = "linux"
     }

Stefan Hornburg (Racke)

unread,
May 14, 2020, 11:23:49 AM5/14/20
to ansible...@googlegroups.com
On 5/14/20 5:16 PM, Laci wrote:
> Another task I'm working on is a conditional blockinfile, something like: 
> if OS=BSD do this, if Linux do that.
>
> I need this because there is a slightly different configuration for them:
>
> BSD:
>  Job { 
>       Name    = "serverX" 
>       Client  = "serverX-fd" 
>       JobDefs = "DefaultJob" 
>      }
>
> Linux:
>  Job { 
>       Name    = "serverX" 
>       Client  = "serverX-fd" 
>       JobDefs = "DefaultJob" 
>       FileSet = "linux"
>      }
>
>

Sorry but I would really use a template instead of shoehorn your syntax with blockinfile.

Regards
Racke

>
> On Thursday, May 14, 2020 at 10:31:36 AM UTC-4, Laci wrote:
>
> Actually this is my goal.
> We are going to have add new servers every time to this file.
>
> So the following lines will be repeated X times
>  Job { 
>       Name    = "serverX" 
>       Client  = "serverX-fd" 
>       JobDefs = "DefaultJob" 
>      } 
>
>
>   "Using a custom marker without the {mark} variable may result in the block
>    being repeatedly inserted on subsequent playbook runs."
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to
> ansible-proje...@googlegroups.com <mailto:ansible-proje...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ansible-project/3b17e950-1ea1-4734-9b38-3746c44ac1ee%40googlegroups.com
> <https://groups.google.com/d/msgid/ansible-project/3b17e950-1ea1-4734-9b38-3746c44ac1ee%40googlegroups.com?utm_medium=email&utm_source=footer>.


--
Ecommerce and Linux consulting + Perl and web application programming.
Debian and Sympa administration. Provisioning with Ansible.

signature.asc

Vladimir Botka

unread,
May 14, 2020, 11:44:44 AM5/14/20
to Laci, ansible...@googlegroups.com
On Thu, 14 May 2020 08:16:20 -0700 (PDT)
Laci <lac...@gmail.com> wrote:

> Another task I'm working on is a conditional blockinfile, something like:
> if OS=BSD do this, if Linux do that.
>
> I need this because there is a slightly different configuration for them:
>
> BSD:
> Job {
> Name = "serverX"
> Client = "serverX-fd"
> JobDefs = "DefaultJob"
> }
>
> Linux:
> Job {
> Name = "serverX"
> Client = "serverX-fd"
> JobDefs = "DefaultJob"
> FileSet = "linux"
> }

Include OS-specific variables from the files. For example,

- name: "Vars from {{ playbook_dir}}/vars/defaults"
include_vars: "{{ item }}"
with_first_found:
- files:
- "{{ ansible_distribution }}-{{ ansible_distribution_release }}.yml"
- "{{ ansible_distribution }}.yml"
- "{{ ansible_os_family }}.yml"
- "default.yml"
- "defaults.yml"
paths: "{{ playbook_dir }}/vars/defaults"

FWIW. See
https://github.com/vbotka/ansible-lib/blob/master/tasks/al_include_os_vars_playbook_dir.yml
--
Reply all
Reply to author
Forward
0 new messages