lineinfile quoting

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?

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"'

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

“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,

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:

Ah, silly me. As is my wont, I overthought this. This works to do what I want:

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') }}"

Todd, the above works great; thanks!