Constructing tuple list string with templated variables gets converted to a list of lists

Constructing tuple list string with templated variables gets converted to a list of lists

Versions:

ansible-playbook [core 2.17.6]
python version = 3.13.11
jinja version = 3.1.4

I’m trying to automate the configuration of language input sources on a Linux desktop running GNOME. This property is set through gsettings/dconf and the value looks like the following when English and Japanese are configured:

$ gsettings get org.gnome.desktop.input-sources sources
[('xkb', 'gb+mac'), ('ibus', 'mozc-jp')]

I have tried to construct this list of tuples by looping over a dictionary resembling:

languages:
  english:
    packages: []
    dconf_source: "('xkb', 'gb+mac')"
  japanese:
    packages: ["ibus-mozc", "mozc-utils-gui"]
    dconf_source:  "('ibus', 'mozc-jp')" 

and task:

#### DIDNT WORK
- name: Construct GNOME input sources string
  ansible.builtin.set_fact:
    gnome_input_sources: >-
      [{% for lang in languages.keys() -%}
      {{ languages[lang].dconf_source }}{{ '' if loop.last else ', ' }}
      {%- endfor %}]

- name: Configure GNOME keyboard input sources
  community.general.dconf:
    key: "/org/gnome/desktop/input-sources/sources"
    value: "{{ gnome_input_sources | string }}"
    state: present

When this list gets passed over via the dconf module the following is shown when checking dconf and how gsettings interprets the value

$ dconf read /org/gnome/desktop/input-sources/sources
[['xkb', 'gb+mac'], ['ibus', 'mozc-jp']]
$ gsettings get org.gnome.desktop.input-sources sources
@a(ss) []

I am able to use the dconf module when hardcoding the string such as:

- name: Configure keyboard input source
  community.general.dconf:
    key: "/org/gnome/desktop/input-sources/sources"
    value: "[('xkb', 'gb+mac'), ('ibus', 'mozc-jp')]"
    state: present

But I want to be able to have this configurable so that I can add additional input sources in the future.

Any ideas on how to ensure a Ansible doesn’t convert the list of tuples into a list of lists?

ansible-core < 2.19 is notoriously bad at keeping types, it often tries to parse things that look like Python data structures when evaluating templates. If you try this with ansible-core 2.19+, you should get what you expect.

I managed to get this working with 2.17 by adding a dash (or something else that makes it an invalid Python data structure) at the end of gnome_input_sources, and removing it when passing it on, like this:

    - name: Construct GNOME input sources string
      ansible.builtin.set_fact:
        gnome_input_sources: >-
          [{% for lang in languages.keys() -%}
          {{ languages[lang].dconf_source | string }}{{ '' if loop.last else ', ' }}
          {%- endfor %}]-

    - debug:
        msg: "{{ gnome_input_sources[:-1] | string }}"
4 Likes

Ah perfect, upgrading to ansible-core 2.20 got it working as you mentioned! Also good to know of the workaround for older versions. Thanks for the help :slight_smile: