lineinfile quoting

58 views
Skip to first unread message

Dimitri Yioulos

unread,
Nov 10, 2023, 8:33:19 AM11/10/23
to Ansible Project
Good day, all.

I want to add the following line to a file:

_some-name                                 TXT     "aZJACEhonRJiOCL1ZtkKMKnx7U4m5jbSswyClGb6wGk"

I would think I'd use the following:

lineinfile: dest=/somedir/somefile insertafter=EOF line="_acme-challenge                                 TXT     "aZJACEhonRJiOCL1ZtkKMKnx7U4m5jbSswyClGb6wGk"

However, the quoted string at the end is screwing my up. How do I make this work? Would ansible.builtin.blockinfile be better? If so, how would I set that up?

Todd Lewis

unread,
Nov 10, 2023, 11:25:48 AM11/10/23
to ansible...@googlegroups.com, uto...@gmail.com
Single-quoted strings can contain double-quotes. So instead of
line="something ending with a "double-quoted string""
do this:
line='something ending with a "double-quoted string"'
--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/8cb39f61-4616-4be4-861d-60d726e74a96n%40googlegroups.com.

-- 
Todd

Dimitri Yioulos

unread,
Nov 10, 2023, 12:18:23 PM11/10/23
to Ansible Project
Thanks, Todd. I already tried that, and it fails:

[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see
details
[WARNING]: Found both group and host with same name: uoj
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  mapping values are not allowed in this context

The error appears to be in '/etc/ansible/playbooks/updatedns.yml': line 8, column 16, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

- name: Add to file
     lineinfile: dest=/somedir/somefile insertafter=EOF line='_some-name                                 TXT     "aZJACEhonRJiOCL1ZtkKMKnx7U 4m5j  bSswyClGb6wGk"'
               ^ here

Todd Lewis

unread,
Nov 10, 2023, 1:11:46 PM11/10/23
to ansible...@googlegroups.com, uto...@gmail.com
"lineinfile" should line up with "name" above. The "lineinfile:" is the mapping that it's complaining cannot be indented more than "name:". Such indentation creates a new context. Thus the message, "mapping values are not allowed in this context".

Is there a reason to use the "key=value" format instead of:
    - name: Add to file
      ansible.builtin.lineinfile:
        dest: /somedir/somefile
        insertafter: EOF
        line: '_some-name                                 TXT     "aZJACEhonRJiOCL1ZtkKMKnx7U 4m5j  bSswyClGb6wGk"'
It isn't wrong. It just looks weird when you're used to the other style.

Cheers,
--
Todd

Dimitri Yioulos

unread,
Nov 13, 2023, 10:49:06 AM11/13/23
to Ansible Project
Thanks, Todd! with your hints, I was able to get the results I want.

Hopefully, I'm staying on-topic (and not being a pita) when I ask for further assistance with this playbook, and lineinfile. Here's the playbook, thus far:

---
- hosts: myhost
  gather_facts: False
  become: yes
  become_method: sudo

  vars_files:
    - zones.yml

  vars:
    serial: "{{ lookup('pipe', 'date +%Y%m%d') }}01"
    year: "{{ lookup('pipe', 'date +%Y) }}"

  tasks:

  - name: Add TXT entry to zone file
    lineinfile:
      dest: "{{ item }}"
      insertafter: EOF
      line: '_some-name                                 TXT     "aZBBBBhonRJiOCL1ZtkKMKnx7U2k3wbSswyClGb6wGk"'
    with_items: '{{ zone_files }}'

   - name: Update serial number
     lineinfile:
       dest: "{{ item }}"
       regexp: "{{ item.year }}"
       replace: "{{ item.serial }}"
     with_items: '{{ zone_files }}


I created a vars directory, and added a zones.yml file, with the destination files I want to edit. The first task in the playbook above works fine, but the second one fails. What I'm trying to accomplish with the second task is to change the serial number in this line with the var "serial" at the point where var "year" is in the line:

                                                2023101002      ; Serial Number YYYYMMDDXX where XX is incrimented by 1 if zone modified on same day.

Note the spacing where the serial begins.

I really appreciate the help.

Dimitri Yioulos

unread,
Nov 13, 2023, 4:23:57 PM11/13/23
to Ansible Project
Ah, silly me. As is my wont, I overthought this. This works to do what I want:

---
- hosts: myhost
  gather_facts: False
  become: yes
  become_method: sudo

  vars_files:
    - zones.yml

  vars:
    old_serial: "2023010301"
    next_serial: "{{ lookup('pipe', 'date +%Y%m%d') }}01"

    year: "{{ lookup('pipe', 'date +%Y) }}"

  tasks:

  - name: Add TXT entry to zone file
    lineinfile:
      dest: "{{ item }}"
      insertafter: EOF
      line: '_some-name                                 TXT     "aZBBBBhonRJiOCL1ZtkKMKnx7U2k3wbSswyClGb6wGk"'
    with_items: "{{ zone_files }}"

  - name: Update serial number
    replace:
      dest: "{{ item }}"
      regexp: '{{ old_serial }}'
      replace: '{{ next_serial }}
    with_items: "{{ zone_files }}"

But, to make this even more automated, it would be good to auto-increment the serial number's last two digits (e.g. 2023111301 to 2023111302 on every run of the playbook. Is that possible?

Todd Lewis

unread,
Nov 13, 2023, 9:25:42 PM11/13/23
to ansible...@googlegroups.com, uto...@gmail.com
This will update the serial number like you want on the zone files that get changed. It's not pretty, but it works.

In fact, it's particularly ugly, using a Perl script to loop over your zone_files and print json to stdout that gets read back in.

I've got to admit it: it was fun to play with Perl again. So, thanks for that!
    - name: Add TXT entry to zone file
      lineinfile:
        dest: "{{ item }}"
        insertafter: EOF
        line: '_some-name                                 TXT     "aZBBBBhonRJiOCL1ZtkKMKnx7U2k3wbSswyClGb6wGk"'
      with_items: "{{ zone_files }}"
      register: add_txt
 
    - name: Show add_txt
      ansible.builtin.debug:
        var: add_txt

    - name: Generate updated serial numbers for zone_files
      ansible.builtin.command: >-
        perl -n -e 'BEGIN {print "{";$sep="";}
                    if (m/\b(\d{8})(\d{2}).*serial/i) {
                      if ($1 eq "{{ today }}") {
                        printf("%s\"%s\": \"%s%02d\"", $sep, $ARGV, "{{ today }}", $2+1);
                      } else {
                        printf("%s\"%s\": \"%s%02d\"", $sep, $ARGV, "{{ today }}", "01");
                      }
                      $sep=",\n";
                    }
                    END{print"}"}' {{ zone_files | map('quote') | join(' ') }}
      vars:
        today: "{{ lookup('pipe', 'date +%Y%m%d') }}"
      register: new_serial

    - name: Make new_serial easily accessible
      ansible.builtin.set_fact:
        new_serials : "{{ new_serial.stdout | from_json() }}"
        
    - name: Update serial number
      lineinfile:
        backrefs: true
        dest: "{{ item }}"
        regexp: '^(\s+)(\d{8})(\d{2})(\s+; Serial Number.*)'
        line: '\g<1>{{ new_serials[item] }}\g<4>'
      loop: "{{ add_txt.results | selectattr('changed', 'true') | map(attribute='item') }}"

Dimitri Yioulos

unread,
Nov 14, 2023, 4:34:14 PM11/14/23
to Ansible Project
Todd, the above works great; thanks!
Reply all
Reply to author
Forward
0 new messages