2

I wrote an Ansible playbook to grab information from some YAML files and store it in a MariaDB database.

It uses this Jinja SQL template:

REPLACE INTO mytable(hostname,fqdn,owner, ...) VALUES 
{% for h in ansible_play_hosts_all %}
(
    '{{ h }}',
    '{{ hostvars[h]['myvars'][0]['fqdn'] | default('FQDN unknown') }}',
    '{{ hostvars[h]['myvars'][0]['server_owner'] | default('No owner') }}',
(...)

and this task:

- name: Upload to database
  community.mysql.mysql_query:
    login_host: "{{ db_host }}"
    login_port: "{{ db_port }}"
    login_user: "{{ db_user }}"
    login_password: "{{ db_password }}"
    login_db: "{{ db_name }}"
    query: "{{ lookup('template', 'template.sql.j2') }}"
  delegate_to: "ansibletowerhost.example.com"

It works well, but fails whenever fields contain apostrophes (e.g. server_owner: "John O'Hara"):

fatal: [myhost42 -> ansibletowerhost.example.com]: FAILED! => {"changed": false,
"msg": "Cannot execute SQL 'REPLACE INTO mytable(hostname,fqdn,owner, ...) VALUES
\\n(\\n \\n    'myhost42',\\n    'myhost42.example.com',\\n    'John O'Hara',
\\n ... \\n);' args [None]: (1064, \\"You have an error in your SQL syntax;
check the manual that corresponds to your MariaDB server version for the right 
 syntax to use near 'Hara',\\\\n ...

How can I have Ansible correctly handle apostrophes, knowing that the original YAML files cannot be altered to fit SQL format (i.e. specifying server_owner: "John O''Hara" is not an option)?

I have tried this syntax but it fails with the same error:

'{{ hostvars[h]['myvars'][0]['server_owner'] | default('No owner') | replace("'", "''") }}',
3
  • What happens if you swap the two filters? Commented Aug 18 at 16:55
  • I'm not sure this will help but try using the replace filter to to create a modified variable to use in the command. The new var would have the single quoate replace by two single quotes ansible.builtin.set_fact: server_owner_new: "{{ server_owner | replace(\"'\", \"''\") }}" Commented Aug 18 at 21:16
  • Does "ninja sql" support SQL placeholders? If so, use them. If not, then this is an object lesson in why you should only ever use sql libraries/tools that do support them. Commented Aug 19 at 3:56

1 Answer 1

2

You can try enclosing your values in double quotes instead of single ones. Of course, this still means they will break if the value can contain double quotes, but it should at least get you through the current problem:

REPLACE INTO mytable(hostname,fqdn,owner, ...) VALUES 
{% for h in ansible_play_hosts_all %}
(
    "{{ h }}",
    "{{ hostvars[h]['myvars'][0]['fqdn'] | default('FQDN unknown') }}",
    "{{ hostvars[h]['myvars'][0]['server_owner'] | default('No owner') }}",
(...)

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.