Closed sebix closed 7 months ago
@sebix , do you have this option set to None
in your ansible configuration? https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-managed-str
According to the Ansible docs, it should be defaulted to "Ansible managed".
grep -ri DEFAULT_MANAGED_STR
gives no results
And grep -ri ansible_managed
only yields roles/ahuffman.sudoers/templates/sudoers.j2:{{ ansible_managed | comment }}
And some occurrences in the ansible community collection:
$ grep -ri ansible_managed ~/.ansible/
~/.ansible/collections/ansible_collections/community/zabbix/roles/zabbix_agent/templates/zabbix_agent2.conf.j2:{{ ansible_managed | comment }}
~/.ansible/collections/ansible_collections/community/zabbix/roles/zabbix_agent/templates/zabbix_agentd.conf.j2:{{ ansible_managed | comment }}
~/.ansible/collections/ansible_collections/community/zabbix/roles/zabbix_javagateway/templates/zabbix_java_gateway.conf.j2:{{ ansible_managed | comment }}
~/.ansible/collections/ansible_collections/community/zabbix/roles/zabbix_proxy/templates/zabbix_proxy.conf.j2:{{ ansible_managed | comment }}
~/.ansible/collections/ansible_collections/community/zabbix/roles/zabbix_server/templates/zabbix_server.conf.j2:{{ ansible_managed | comment }}
~/.ansible/collections/ansible_collections/community/general/tests/integration/targets/consul/templates/consul_config.hcl.j2:# {{ ansible_managed }}
~/.ansible/collections/ansible_collections/ansible/windows/plugins/modules/win_template.py:- C(ansible_managed) (configurable via the C(defaults) section of C(ansible.cfg)) contains a string which can be used to
@sebix try now with the lastest release 2.0.4: 81ce24a43ed4ca9fb9ed4b11631ad01bbf89ffde.
Thank you for the support:
$ ansible-galaxy install -f ahuffman.sudoers
Starting galaxy role install process
- changing role ahuffman.sudoers from 2.0.3 to unspecified
- downloading role 'sudoers', owned by ahuffman
- downloading role from https://github.com/ahuffman/ansible-sudoers/archive/2.0.4.tar.gz
- extracting ahuffman.sudoers to ./roles/ahuffman.sudoers
- ahuffman.sudoers (2.0.4) was installed successfully
Same result:
TASK [ahuffman.sudoers : Ensure sudoers include files are configured] ***********************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ): 'NoneType' object is not iterable. 'NoneType' object is not iterable
failed: [sendai.fizeau.net] (item=/etc/sudoers.d/02_nagios) => changed=false
ansible_loop_var: item
item:
path: /etc/sudoers.d/02_nagios
user_specifications:
commands: /usr/sbin/checkrestart
hosts: ALL
tags: NOPASSWD
users: nagios
msg: |-
AnsibleError: Unexpected templating type error occurred on ({{ ansible_managed | default('Ansible managed') | comment }}
{% if item.defaults is defined %}
# Default specifications
{% for default in item.defaults %}
{% if default is mapping %}
{% for name, values in default.items() %}
{% if name == 'secure_path' %}
Defaults {{ name }} = {% for item in values %}{% if not loop.last %}{{ item }}:{% else %}{{ item }}{% endif %}{% endfor %}
{% else %}
{% for items in values | list | slice(6) %}
{% if items %}
Defaults {{ name }} {% if not loop.first %}+{% endif %}= "{{ items | list | join(' ') }}"
{% endif -%}
{% endfor %}
{% endif %}
{% endfor %}
{% elif default | first == ':' %}
Defaults{{ default }}
{% else %}
Defaults {{ default }}
{% endif %}
{% endfor %}
{% endif %}
{% if item.aliases is defined %}
# Alias specifications
{% if item.aliases.cmnd_alias is defined %}
## Command Aliases
{% for ca in item.aliases.cmnd_alias %}
Cmnd_Alias {{ ca.name }} = {% for cmnd in ca.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %}
{% endfor %}
{% endif %}
{% if item.aliases.host_alias is defined %}
## Host Aliases
{% for ha in item.aliases.host_alias %}
Host_Alias {{ ha.name }} = {% for host in ha.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %}
{% endfor %}
{% endif %}
{% if item.aliases.runas_alias is defined %}
## Runas Aliases
{% for ra in item.aliases.runas_alias %}
Runas_Alias {{ ra.name }} = {% for user in ra.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %}
{% endfor %}
{% endif %}
{% if item.aliases.user_alias is defined %}
## User Aliases
{% for ua in item.aliases.user_alias %}
User_Alias {{ ua.name }} = {% for user in ua.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %}
{% endfor %}
{% endif %}
{% endif %}
{% if item.user_specifications is defined %}
{% if item.user_specifications | json_query('[?!type]') | flatten | length > 0 %}
# User specifications
{% for spec in item.user_specifications %}
{% if spec.type is undefined %}
{% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %} {% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %}={% if spec.operators is defined %}({% for op in spec.operators %}{% if not loop.last%}{{ op }}, {% else %}{{ op }}{% endif %}{% endfor %}){% endif %} {% if spec.selinux_type is defined %}TYPE={% for type in spec.selinux_type %}{% if not loop.last %}{{ type }}, {% else %}{{ type }} {% endif %}{% endfor %}{% endif %}{% if spec.selinux_role is defined %}ROLE={% for role in spec.selinux_role %}{% if not loop.last %}{{ role }}, {% else %}{{ role }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_privs is defined %}PRIVS={% for priv in spec.solaris_privs %}{% if not loop.last %}{{ priv }}, {% else %}{{ priv }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_limitprivs is defined %}LIMITPRIVS={% for lpriv in spec.solaris_limitprivs %}{% if not loop.last %}{{ lpriv }}, {% else %}{{ lpriv }} {% endif %}{% endfor %}{% endif %}{% if spec.tags is defined %}{% for tag in spec.tags %}{{ tag }}:{% endfor %} {% endif %}{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% if item.user_specifications | json_query('[*].defaults') | flatten | length > 0 %}
# Default override specifications
{% for spec in item.user_specifications %}
{% if spec.type is defined %}
{% if spec.type == 'user'%}
Defaults:{% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
{% elif spec.type == 'runas' %}
Defaults>{% for op in spec.operators %}{% if not loop.last %}{{ op }}, {% else %}{{ op }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
{% elif spec.type == 'host' %}
Defaults@{% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
{% elif spec.type == 'command' %}
Defaults!{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if item.include_files is defined or item.include_directories is defined %}
# Includes
{% if item.include_files is defined and item.include_files | length > 0 %}
## Include files
{% for file in item.include_files %}
#include {{ file }}
{% endfor %}
{% endif %}
{% if item.include_directories is defined and item.include_directories | length > 0 %}
## Include directories
{% for dir in item.include_directories %}
#includedir {{ dir }}
{% endfor %}
{% endif %}
{% endif %}
): 'NoneType' object is not iterable. 'NoneType' object is not iterable
Wit -vvv
there is more output:
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 1010, in do_template
res = myenv.concat(rf)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/native_helpers.py", line 83, in ansible_concat
return ''.join([to_text(v) for v in nodes])
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/native_helpers.py", line 83, in <listcomp>
return ''.join([to_text(v) for v in nodes])
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<template>", line 254, in root
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 295, in wrapper
ret = func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/plugins/filter/core.py", line 483, in flatten
for element in mylist:
TypeError: 'NoneType' object is not iterable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/ansible/plugins/action/template.py", line 152, in run
resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, overrides=overrides)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 1021, in do_template
raise AnsibleError("Unexpected templating type error occurred on (%s): %s" % (to_native(data), to_native(te)), orig_exc=te)
ansible.errors.AnsibleError: Unexpected templating type error occurred on ({{ ansible_managed | default('Ansible managed') | comment }}
{% if item.defaults is defined %}
# Default specifications
Can you please post the data you're running the role with or the entire playbook?
Sure, this is the playbook task:
- name: sudoers
hosts:
- hostname
roles:
- ahuffman.sudoers
tags:
- sudoers
vars:
sudoers_files:
- path: /etc/sudoers.d/02_nagios
user_specifications:
# nagios ALL=NOPASSWD:/usr/sbin/checkrestart
users: nagios
hosts: ALL
tags: NOPASSWD
commands: /usr/sbin/checkrestart
sudoers_backup: false
And I execute ansible with -t sudoers
to execute only this task and none else, preventing any influence from other roles.
Can you please run export DEFAULT_MANAGED_STR="Ansible managed" && ansible-playbook <rest of your normal command here>
. I'm trying to see whether you're still getting this with the ansible config option set (which according to ansible docs should be defaulted and not sure why you get a setting of None
for it.
Also, can you post your ansible.cfg file?
When defining DEFAULT_MANAGED_STR="Ansible managed"
nothing changes.
The ansible.cfg
is:
[defaults]
inventory = ./inventories/development.yml
# https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-roles-path
roles_path = ./roles:../org-ansible/roles:../org-ansible/galaxy-roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
retry_files_enabled = False
stdout_callback = yaml
The error message is still the same, when I remove {{ ansible_managed | default('Ansible managed') | comment }}
from templates/sudoers.j2
:
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 1010, in do_template
res = myenv.concat(rf)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/native_helpers.py", line 83, in ansible_concat
return ''.join([to_text(v) for v in nodes])
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/native_helpers.py", line 83, in <listcomp>
return ''.join([to_text(v) for v in nodes])
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<template>", line 245, in root
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 295, in wrapper
ret = func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/plugins/filter/core.py", line 483, in flatten
for element in mylist:
TypeError: 'NoneType' object is not iterable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/ansible/plugins/action/template.py", line 152, in run
resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, overrides=overrides)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/ansible/template/__init__.py", line 1021, in do_template
raise AnsibleError("Unexpected templating type error occurred on (%s): %s" % (to_native(data), to_native(te)), orig_exc=te)
ansible.errors.AnsibleError: Unexpected templating type error occurred on ({% if item.defaults is defined %}
...
By removing piece by piece from sudoers.j2
I found that the error comes from the block
{% if item.user_specifications | json_query('[*].defaults') | flatten | length > 0 %}
So I printed item.user_specifications
alone, which gives {'users': 'nagios', 'hosts': 'ALL', 'tags': 'NOPASSWD', 'commands': '/usr/sbin/checkrestart'}
. And that's now embarrassing: It should be a list. Turns out, it all was just a user error.
I really must apologize at this point.
Awesome! And, no worries, it's been years since I worked on this role code and remember that the template is a quite complicated one due to the many permutations that the sudoers file has per implementation on particular OSes. For some reason the ansible_managed var was throwing me for a loop on the output errors.
Anyways, good luck and hope this role helps you out with your automation project!
It appears a parameter is missing a default value:
Rest of traceback
``` {% if item.defaults is defined %} # Default specifications {% for default in item.defaults %} {% if default is mapping %} {% for name, values in default.items() %} {% if name == 'secure_path' %} Defaults {{ name }} = {% for item in values %}{% if not loop.last %}{{ item }}:{% else %}{{ item }}{% endif %}{% endfor %} {% else %} {% for items in values | list | slice(6) %} {% if items %} Defaults {{ name }} {% if not loop.first %}+{% endif %}= "{{ items | list | join(' ') }}" {% endif -%} {% endfor %} {% endif %} {% endfor %} {% elif default | first == ':' %} Defaults{{ default }} {% else %} Defaults {{ default }} {% endif %} {% endfor %} {% endif %} {% if item.aliases is defined %} # Alias specifications {% if item.aliases.cmnd_alias is defined %} ## Command Aliases {% for ca in item.aliases.cmnd_alias %} Cmnd_Alias {{ ca.name }} = {% for cmnd in ca.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %} {% endfor %} {% endif %} {% if item.aliases.host_alias is defined %} ## Host Aliases {% for ha in item.aliases.host_alias %} Host_Alias {{ ha.name }} = {% for host in ha.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %} {% endfor %} {% endif %} {% if item.aliases.runas_alias is defined %} ## Runas Aliases {% for ra in item.aliases.runas_alias %} Runas_Alias {{ ra.name }} = {% for user in ra.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %} {% endfor %} {% endif %} {% if item.aliases.user_alias is defined %} ## User Aliases {% for ua in item.aliases.user_alias %} User_Alias {{ ua.name }} = {% for user in ua.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %} {% endfor %} {% endif %} {% endif %} {% if item.user_specifications is defined %} {% if item.user_specifications | json_query('[?!type]') | flatten | length > 0 %} # User specifications {% for spec in item.user_specifications %} {% if spec.type is undefined %} {% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %} {% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %}={% if spec.operators is defined %}({% for op in spec.operators %}{% if not loop.last%}{{ op }}, {% else %}{{ op }}{% endif %}{% endfor %}){% endif %} {% if spec.selinux_type is defined %}TYPE={% for type in spec.selinux_type %}{% if not loop.last %}{{ type }}, {% else %}{{ type }} {% endif %}{% endfor %}{% endif %}{% if spec.selinux_role is defined %}ROLE={% for role in spec.selinux_role %}{% if not loop.last %}{{ role }}, {% else %}{{ role }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_privs is defined %}PRIVS={% for priv in spec.solaris_privs %}{% if not loop.last %}{{ priv }}, {% else %}{{ priv }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_limitprivs is defined %}LIMITPRIVS={% for lpriv in spec.solaris_limitprivs %}{% if not loop.last %}{{ lpriv }}, {% else %}{{ lpriv }} {% endif %}{% endfor %}{% endif %}{% if spec.tags is defined %}{% for tag in spec.tags %}{{ tag }}:{% endfor %} {% endif %}{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %} {% endif %} {% endfor %} {% endif %} {% endif %} {% if item.user_specifications | json_query('[*].defaults') | flatten | length > 0 %} # Default override specifications {% for spec in item.user_specifications %} {% if spec.type is defined %} {% if spec.type == 'user'%} Defaults:{% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %} {% elif spec.type == 'runas' %} Defaults>{% for op in spec.operators %}{% if not loop.last %}{{ op }}, {% else %}{{ op }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %} {% elif spec.type == 'host' %} Defaults@{% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %} {% elif spec.type == 'command' %} Defaults!{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %} {% endif %} {% endif %} {% endfor %} {% endif %} {% if item.include_files is defined or item.include_directories is defined %} # Includes {% if item.include_files is defined and item.include_files | length > 0 %} ## Include files {% for file in item.include_files %} #include {{ file }} {% endfor %} {% endif %} {% if item.include_directories is defined and item.include_directories | length > 0 %} ## Include directories {% for dir in item.include_directories %} #includedir {{ dir }} {% endfor %} {% endif %} {% endif %} ): 'NoneType' object is not iterable. 'NoneType' object is not iterable ```The role parameters are very minimal:
I ran ansible in check mode, but I assume that makes no difference.