Does current Ansible support templates macro?

Hello,

I’m working on a role for system SSSD daemon. I found this piece of code online:
https://github.com/picotrading/ansible-sssd/blob/master/templates/sssd.conf.j2

I have defined my own sssd_config variable in my role’s defaults directory, so I’d like to use that piece of code. That code is neat. However, I don’t understand what it is doing in line:
{% from “templates/encoder/macros/ini_encode_macro.j2” import ini_encode with context -%}

Also does current Ansible support templates macro like above?

If it doesn’t, then sssd_config variable is a large dictionary map, with INI-style different sections. What really needs to happen is based on that variable, change it to use = symbol as delimiter for each INI section. For example:

sssd_config:
sssd:
debug_level: 1

config_file_version: 2

Then the produced sssd.conf file would look like below:

[sssd]
debug_level=1
config_file_version=2

Thank you,

Xinhuan Zheng

This link to the Jinja doc will help you
https://jinja.palletsprojects.com/en/2.10.x/templates/#import

  -vlado

I still cannot figure out how to loop through my variable:

sssd_config:
sssd:
debug_level: 1
nss:
reconnection_retries: 3
pam:
**debug_level: 5**

Here is my template code:

{% for item in sssd_config %}
[{{ item }}]
{% set list = sssd_config[item] %}
{% for i in list %}
{{ i }} =
{% endfor %}
{% endfor %}

I cannot figure out what to put after {{ i }}. Please HELP!

Thank you,

- Xinhuan Zheng

Variable 'sssd_config' is dictionary. It's not possible to iterate
dictionary. Try for example

  {% for item in sssd_config.items() %}
  {{ item }}
  {% endfor %}

see the 'items' in the created file and fit the template to your needs.

HTH,

  -vlado

Tried what you said. Here is what {{ item }} look like:

[(u’sssd’, {u’debug_level’: 5, u’reconnection_retries’: 3, u’config_file_version’: 2, u’sbus_timeout’: 30})]

[(u’services’, [u’nss’, u’pam’, u’ssh’])]

What should I do next?

Thanks again,

  • Xinhuan

Fit the template to your needs. For example the template

    {% for item in sssd_config.items() %}
    [{{ item.0 }}]
    {{ item.1.keys().0 }}={{ item.1.values().0 }}
    {% endfor %}

gives

    [nss]
    reconnection_retries=3
    [pam]
    debug_level=5
    [sssd]
    debug_level=1

HTH,

  -vlado

There might be more items in the configuration sections. The template
below gives the same result and would include other parameters if present

    {% for item in sssd_config.items() %}
    [{{ item.0 }}]
    {% for iitem in item.1.items() %}
    {{ iitem.0 }}={{ iitem.1 }}
    {% endfor %}
    {% endfor %}

I tested the solution, it doesn’t work. item.1 becomes:
{u’id_provider’: u’local’, u’auth_provider’: u’local’, u’enumerate’: True}

So I get error there is no keys on {{ item.1.keys().0 }}

  • Xinhuan

Got this error:

"AnsibleUndefinedVariable: ‘list object’ has no attribute ‘items’ for item.1.items()

  • Xinhuan

Both versions works for me. Double-check the code. The playbook

- hosts: localhost
  vars:
    sssd_config:
      sssd:
        debug_level: 1
      nss:
        reconnection_retries: 3
      pam:
        debug_level: 5
  tasks:
    - template:
        src: template.j2
        dest: config.ini

with the template

% for item in sssd_config.items() %}
[{{ item.0 }}]
{{ item.1.keys().0 }}={{ item.1.values().0 }}
{% endfor %}
# ------------------------------------------
{% for item in sssd_config.items() %}
[{{ item.0 }}]
{% for iitem in item.1.items() %}
{{ iitem.0 }}={{ iitem.1 }}
{% endfor %}
{% endfor %}

gives

[nss]
reconnection_retries=3
[pam]
debug_level=5
[sssd]
debug_level=1
# ------------------------------------------
[nss]
reconnection_retries=3
[pam]
debug_level=5
[sssd]
debug_level=1

Hello,

Your testing looks fine in the test data model. However, the sssd_config real data model is like below:

sssd_config:
sssd:
debug_level: 1

additional_key: additional_value
another_addtional_key: another_additional_value

nss:
reconnection_retries: 3

additional_key: additional_value
another_addtional_key: another_additional_value
pam:
debug_level: 5

additional_key: additional_value
another_addtional_key: another_additional_value

The addtional_key and another_additional_key isn’t same per section (pam,nss,sssd), and number of additional_key per section isn’t identical either. So nss section may have 5 key/value pairs, pam may have 6 key/value pairs, and sssd may have only 3 key/value pairs. Each additional_key is pretty much unique to that section.

Because this is so difficult to manipulate in template (I spend most yesterday to figure it out), I think it is probably better just put INI-style content into template file, then fill in the values from variables that varies for that key/value pair. It makes the work more simpler.

Thank you for providing the test case. I’ll remember this lesson.

  • Xinhuan

It also possible to use module 'ini_file'
https://docs.ansible.com/ansible/latest/modules/ini_file_module.html

With the configuration data transformed to this list

      sssd_config:
        - params:
            - additional_key: additional_value
            - reconnection_retries: 3
            - another_addtional_key: another_additional_value
          section: nss
        - params:
            - debug_level: 5
            - another_addtional_key: another_additional_value
            - additional_key: additional_value
          section: pam
        - params:
            - debug_level: 1
            - another_addtional_key: another_additional_value
            - additional_key: additional_value
          section: sssd

the task below

    - ini_file:
        path: /scratch/tmp/config.ini
        section: "{{ item.0.section }}"
        option: "{{ item.1.keys()|list|first }}"
        value: "{{ item.1.values()|list|first }}"
      with_subelements:
        - "{{ sssd_config }}"
        - params

gives

$ cat /scratch/tmp/config.ini
[nss]
additional_key = additional_value
reconnection_retries = 3
another_addtional_key = another_additional_value
[pam]
debug_level = 5
another_addtional_key = another_additional_value
additional_key = additional_value
[sssd]
debug_level = 1
another_addtional_key = another_additional_value
additional_key = additional_value

Hello Mr. Botka,

This is exactly what I am looking for. It looks so neat with ini_file module instead of template. I’ll play with it in my tasks.

Thank you very much! :slight_smile:

  • Xinhuan