fix/ansible-core 2.19: etcd: avoid mutating methods in template (#13474)

2.19 disallow methods with side effects in Jinja. Use a simple loop by
adding all the SANs source in one list.

Also check the sources before hand for failing on CIDR notation.

Link: https://github.com/ansible/ansible/issues/85202
This commit is contained in:
Max Gautier
2026-09-08 09:12:32 +00:00
committed by GitHub
parent 4b7dfaef87
commit c554ee816d
3 changed files with 20 additions and 25 deletions
+18 -25
View File
@@ -1,4 +1,4 @@
{% set counter = {'dns': 2,'ip': 1,} %}{% macro increment(dct, key, inc=1)%}{% if dct.update({key: dct[key] + inc}) %} {% endif %}{% endmacro %}[req]
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
@@ -23,28 +23,21 @@ subjectAltName = @alt_names
authorityKeyIdentifier=keyid:always,issuer
[alt_names]
DNS.1 = localhost
{% for host in groups['etcd'] %}
{% if hostvars[host]['etcd_access_address'] is defined and not (hostvars[host]['etcd_access_address'] | ansible.utils.ipaddr) %}
{# If defined, the address which etcd uses to access its members must be included in the SAN, otherwise etcd will fail with a TLS error upon startup. #}
DNS.{{ counter["dns"] }} = {{ hostvars[host]['etcd_access_address'] }}{{ increment(counter, 'dns') }}
{% endif %}
{# This will always expand to inventory_hostname, which can be a completely arbitrary name, that etcd will not know or care about, hence this line is (probably) redundant. #}
DNS.{{ counter["dns"] }} = {{ host }}{{ increment(counter, 'dns') }}
{#
List all possible ways etcd instances can be contacted
main_{access_,}ips: those variables are explicitly set by network_facts role
and thus don't need a defined check
#}
{% for san in (
groups['etcd'] | map('extract', hostvars, morekeys='etcd_access_address') | select('defined')
+ groups['etcd']
+ etcd_cert_alt_names
+ groups['etcd'] | map('extract', hostvars, morekeys='main_access_ips')
+ groups['etcd'] | map('extract', hostvars, morekeys='main_ips')
+ etcd_cert_alt_ips
+ ['localhost', '127.0.0.1', '::1']
) | flatten | unique
%}
{{ 'IP' if san is ansible.utils.ip_address else 'DNS' }}.{{ loop.index }} = {{ san }}
{% endfor %}
{% for etcd_alt_name in etcd_cert_alt_names %}
DNS.{{ counter["dns"] }} = {{ etcd_alt_name }}{{ increment(counter, 'dns') }}
{% endfor %}
{% for host in groups['etcd'] %}
{% for address in hostvars[host]['main_access_ips'] %}
IP.{{ counter["ip"] }} = {{ address }}{{ increment(counter, 'ip') }}
{% endfor %}
{% for address in hostvars[host]['main_ips'] %}
IP.{{ counter["ip"] }} = {{ address }}{{ increment(counter, 'ip') }}
{% endfor %}
{% endfor %}
{% for cert_alt_ip in etcd_cert_alt_ips %}
IP.{{ counter["ip"] }} = {{ cert_alt_ip }}{{ increment(counter, 'ip') }}
{% endfor %}
IP.{{ counter["ip"] }} = 127.0.0.1{{ increment(counter, 'ip') }}
IP.{{ counter["ip"] }} = ::1
+1
View File
@@ -1,3 +1,4 @@
---
dependencies:
- role: kubespray_defaults
- role: etcd_defaults
+1
View File
@@ -170,6 +170,7 @@
- etcd_deployment_type in ['host', 'docker', 'kubeadm']
- etcd_deployment_type in ['host', 'kubeadm'] or container_manager == 'docker'
- container_manager in ['docker', 'crio', 'containerd']
- etcd_cert_alt_ips | reject('ansible.utils.ip_address') == []
msg: The selected choice is not supported
run_once: true