Home > Mobile >  Ansible, junja2 and setting single quotes around a value with ansible.builtin.replace
Ansible, junja2 and setting single quotes around a value with ansible.builtin.replace

Time:07-07

I want to make sure there are single quotes around the relation_regex defined regular expression (configuring datadog postgres module with ansible).

This is what I am aiming at:

conf.yml:

instances:
-   dbname: dbname
    host: localhost
    password: password
    port: 5432
    username: datadog
    relations:
      - relation_regex: '.*'
        relkind:
        - r
        - i
        - S
        - p

This is where I am with the ansible task:


- name: Properly configure any regexp expression in a configuration file
  ansible.builtin.replace:
    path: "/etc/datadog-agent/conf.d/{{ item }}.d/conf.yaml"
    regexp: '(\s relation_regex:)\s (?:['']*([^'']*))'
    replace: '\g<1> ''\g<2>'''
  with_items: "{{ datadog_checks|list }}"
  notify: restart datadog-agent

Yet, this is what is produced:


.. cut ..
-      - relation_regex: .*
       - relation_regex: '.*
.. cut ..

Ansible does not provide the ending single quote ('). Feels like a bug but perhaps there is something wrong with my lookaround regex which has odd consequences?

Versions:

ansible [core 2.11.1] 
  python version = 3.8.10 (default, Mar 15 2022, 12:22:08) [GCC 9.4.0]
  jinja version = 3.0.1
  libyaml = True

CodePudding user response:

You omitted the next line of that "diff" output that would have been a dead giveaway of the problem:

-    - relation_regex: .*
     - relation_regex: '.*
 '

which indicates that your "any character except '" needs to be more specific, saying "any character except ' or EOL characters"

- name: Properly configure any regexp expression in a configuration file
  ansible.builtin.replace:
    path: "/etc/datadog-agent/conf.d/{{ item }}.d/conf.yaml"
    regexp: '(\s relation_regex:)\s (?:['']*([^''\r\n]*))'
    replace: '\g<1> ''\g<2>'''
  with_items: "{{ datadog_checks|list }}"
  notify: restart datadog-agent

Also, while this isn't what you asked, you are making things harder on yourself than necessary with the single-quoted scalar containing single quoted escapes since there's (currently) nothing yaml-sensitive in those scalars that needs quoting:

- name: Properly configure any regexp expression in a configuration file
  ansible.builtin.replace:
    path: "/etc/datadog-agent/conf.d/{{ item }}.d/conf.yaml"
    regexp: (\s relation_regex:)\s (?:'*([^'\r\n]*))
    replace: \g<1> '\g<2>'
  with_items: "{{ datadog_checks|list }}"
  notify: restart datadog-agent

You'll also want to be cautious because as written your replace will fail to harmonize existing single quoted items, causing idempotency failures if you run that task twice

- name: Properly configure any regexp expression in a configuration file
  ansible.builtin.replace:
    path: "/etc/datadog-agent/conf.d/{{ item }}.d/conf.yaml"
    regexp: (\s relation_regex:)\s (?:'*([^'\r\n]*)'*)
    replace: \g<1> '\g<2>'
  with_items: "{{ datadog_checks|list }}"
  notify: restart datadog-agent

CodePudding user response:

Given the file

shell> cat conf.yaml
 relation_regex: .*

the task

    - ansible.builtin.replace:
        path: conf.yaml
        regexp: '(\s relation_regex:)\s ''?(.*)''?'
        replace: '\1 ''\2'''

gives (running --check --diff options)

--- before: conf.yaml
    after: conf.yaml
@@ -1  1 @@
- relation_regex: .*
  relation_regex: '.*'
  • Related