Skip to content

Commit 12840f2

Browse files
committed
refactor: support Ansible 2.19
Ansible 2.19 introduces some big changes https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_core_2.19.html One big change is that data structures are no longer mutable by the use of python methods such as `__setitem__`, `setdefault`, `update`, etc. in Jinja constructs. Instead, items must use filters or other Jinja operations. One common idiom is to mutate each element in a list. Since we cannot do this "in-place" anymore, a common way to do this is: ```yaml - name: Construct a new list from an existing list and mutate each element set_fact: __new_list: "{{ __new_list | d([]) + [mutated_item] }}" loop: "{{ old_list }}" mutated_item: "{{ some value based on item from old list }}" - name: Reset original old list set_fact: old_list: "{{ __new_list }}" ``` Similarly with `dict` items: ```yaml - name: Construct a new dict from an existing dict and mutate each element set_fact: __new_dict: "{{ __new_dict | d({}) | combine(mutated_item) }}" loop: "{{ old_dict | dict2items }}" mutated_item: "{{ {item.key: mutation of item.value} }}" - name: Reset original old dict set_fact: old_dict: "{{ __new_dict }}" ``` Another big change is that a boolean expression in a `when` or similar construct must be converted to a boolean - we cannot rely on the implicit evaluation in a boolean context. For example, if `var` is some iterable, like a `dict`, `list`, or `string`, you used to be able to evaluate an empty value in a boolean context: ```yaml when: var # do this only if var is not empty ``` You now have to explicitly test for empty using `length`: ```yaml when: var | length > 0 # do this only if var is not empty ``` Signed-off-by: Rich Megginson <[email protected]>
1 parent 81105e8 commit 12840f2

File tree

5 files changed

+98
-73
lines changed

5 files changed

+98
-73
lines changed

tasks/main.yml

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -120,63 +120,87 @@
120120
path: "{{ __kernel_settings_profile_filename }}"
121121
register: __kernel_settings_profile_contents
122122

123-
- name: Apply kernel settings
124-
template:
125-
src: "{{ __kernel_settings_profile_src }}.j2"
126-
dest: "{{ __kernel_settings_profile_filename }}"
127-
mode: "0644"
128-
vars:
129-
__sysctl_old: "{{ __kernel_settings_profile_contents.data.get('sysctl', {})
123+
- name: Initialize new sysctl
124+
set_fact:
125+
__kernel_settings_new_sysctl: "{{
126+
__kernel_settings_profile_contents.data.get('sysctl', {})
130127
if not kernel_settings_purge
131128
and kernel_settings_sysctl != __kernel_settings_state_empty
132129
and not __kernel_settings_previous_replaced in kernel_settings_sysctl
133130
else {} }}"
134-
__sysfs_old: "{{ __kernel_settings_profile_contents.data.get('sysfs', {})
131+
132+
- name: Set new sysctl
133+
set_fact:
134+
__kernel_settings_new_sysctl: "{{ __kernel_settings_new_sysctl | combine(__new_item) }}"
135+
loop: "{{ [] if kernel_settings_sysctl == __kernel_settings_state_empty
136+
else kernel_settings_sysctl | rejectattr('previous', 'defined') | list }}"
137+
vars:
138+
__new_item: "{{ {item.name: __new_value} }}"
139+
__new_value: "{{ __kernel_settings_state_absent
140+
if item.state | d('present') == 'absent'
141+
else item.value | d(__kernel_settings_state_absent) }}"
142+
143+
- name: Initialize new sysfs
144+
set_fact:
145+
__kernel_settings_new_sysfs: "{{
146+
__kernel_settings_profile_contents.data.get('sysfs', {})
135147
if not kernel_settings_purge
136148
and kernel_settings_sysfs != __kernel_settings_state_empty
137149
and not __kernel_settings_previous_replaced in kernel_settings_sysfs
138150
else {} }}"
151+
152+
- name: Set new sysfs
153+
set_fact:
154+
__kernel_settings_new_sysfs: "{{ __kernel_settings_new_sysfs | combine(__new_item) }}"
155+
loop: "{{ [] if kernel_settings_sysfs == __kernel_settings_state_empty
156+
else kernel_settings_sysfs | rejectattr('previous', 'defined') | list }}"
157+
vars:
158+
__new_item: "{{ {item.name: __new_value} }}"
159+
__new_value: "{{ __kernel_settings_state_absent
160+
if item.state | d('present') == 'absent'
161+
else item.value | d(__kernel_settings_state_absent) }}"
162+
163+
- name: Apply kernel settings
164+
template:
165+
src: "{{ __kernel_settings_profile_src }}.j2"
166+
dest: "{{ __kernel_settings_profile_filename }}"
167+
mode: "0644"
168+
vars:
169+
# we don't have a way to compare an item to a dict - eq not available in el7
170+
# so assume if the value is a dict, it is the {"state": "absent"} dict
171+
# because "real" values should be scalars like strings, int, bool
172+
__sysctl_has_values: "{{ __kernel_settings_new_sysctl | dict2items | rejectattr('value', 'mapping') | list | length > 0 }}"
173+
__sysfs_has_values: "{{ __kernel_settings_new_sysfs | dict2items | rejectattr('value', 'mapping') | list | length > 0 }}"
139174
__systemd_old: "{{
140-
__kernel_settings_profile_contents.data.get('systemd', {}).get('cpu_affinity')
175+
__kernel_settings_profile_contents.data.get('systemd', {}).get('cpu_affinity', '')
141176
if not kernel_settings_purge
142177
and kernel_settings_systemd_cpu_affinity != __kernel_settings_state_absent
143-
else none }}"
178+
else '' }}"
179+
__systemd_new: "{{ kernel_settings_systemd_cpu_affinity
180+
if kernel_settings_systemd_cpu_affinity is not none and
181+
kernel_settings_systemd_cpu_affinity != __kernel_settings_state_absent and
182+
kernel_settings_systemd_cpu_affinity | length > 0
183+
else __systemd_old }}"
144184
__trans_huge_old: "{{
145-
__kernel_settings_profile_contents.data.get('vm', {}).get('transparent_hugepages')
185+
__kernel_settings_profile_contents.data.get('vm', {}).get('transparent_hugepages', '')
146186
if not kernel_settings_purge
147187
and kernel_settings_transparent_hugepages != __kernel_settings_state_absent
148-
else none }}"
188+
else '' }}"
189+
__trans_huge_new: "{{ kernel_settings_transparent_hugepages
190+
if kernel_settings_transparent_hugepages is not none and
191+
kernel_settings_transparent_hugepages != __kernel_settings_state_absent and
192+
kernel_settings_transparent_hugepages | length > 0
193+
else __trans_huge_old }}"
149194
__trans_defrag_old: "{{
150-
__kernel_settings_profile_contents.data.get('vm', {}).get('transparent_hugepage.defrag')
195+
__kernel_settings_profile_contents.data.get('vm', {}).get('transparent_hugepage.defrag', '')
151196
if not kernel_settings_purge
152197
and kernel_settings_transparent_hugepages_defrag != __kernel_settings_state_absent
153-
else none }}"
154-
__sections:
155-
- name: sysctl
156-
new: "{{ kernel_settings_sysctl | difference([__kernel_settings_previous_replaced]) | list
157-
if kernel_settings_sysctl != __kernel_settings_state_empty
158-
else [] }}"
159-
old: "{{ __sysctl_old }}"
160-
- name: sysfs
161-
new: "{{ kernel_settings_sysfs | difference([__kernel_settings_previous_replaced]) | list
162-
if kernel_settings_sysfs != __kernel_settings_state_empty
163-
else [] }}"
164-
old: "{{ __sysfs_old }}"
165-
- name: systemd
166-
new:
167-
- name: cpu_affinity
168-
value: "{{ kernel_settings_systemd_cpu_affinity }}"
169-
old:
170-
cpu_affinity: "{{ __systemd_old }}"
171-
- name: vm
172-
new:
173-
- name: transparent_hugepages
174-
value: "{{ kernel_settings_transparent_hugepages }}"
175-
- name: transparent_hugepage.defrag
176-
value: "{{ kernel_settings_transparent_hugepages_defrag }}"
177-
old:
178-
transparent_hugepages: "{{ __trans_huge_old }}"
179-
transparent_hugepage.defrag: "{{ __trans_defrag_old }}"
198+
else '' }}"
199+
__trans_defrag_new: "{{ kernel_settings_transparent_hugepages_defrag
200+
if kernel_settings_transparent_hugepages_defrag is not none and
201+
kernel_settings_transparent_hugepages_defrag != __kernel_settings_state_absent and
202+
kernel_settings_transparent_hugepages_defrag | length > 0
203+
else __trans_defrag_old }}"
180204
register: __kernel_settings_register_apply
181205

182206
# this will also apply the kernel_settings profile, so we

templates/kernel_settings.j2

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
11
{{ ansible_managed | comment }}
22
{{ "system_role:kernel_settings" | comment(prefix="", postfix="") }}
3-
[main]
4-
summary = kernel settings
5-
{% set __settings = {} %}
6-
{% for section in __sections %}
7-
{% set section_name = section["name"] %}
8-
{% for item in section["new"] %}
9-
{% if item.state | d() == "absent" %}
10-
{% set _ = __settings.setdefault(section_name, {}).__setitem__(item.name, __kernel_settings_state_absent) %}
11-
{% elif item.value != none and item.value != "" %}
12-
{% set _ = __settings.setdefault(section_name, {}).__setitem__(item.name, item.value) %}
13-
{% endif %}
14-
{% endfor %}
15-
{% for key, value in section["old"].items() %}
16-
{% if not __settings.get(section_name, {}).__contains__(key) and value != none and value != "" %}
17-
{% set _ = __settings.setdefault(section_name, {}).__setitem__(key, value) %}
18-
{% endif %}
19-
{% endfor %}
20-
{% endfor %}
21-
{% set seen_sections = {} %}
22-
{% for section_name in __settings.keys() | sort %}
23-
{% set section = __settings[section_name] %}
24-
{% for key in section.keys() | sort %}
25-
{% if section[key] != __kernel_settings_state_absent %}
26-
{% if not seen_sections.__contains__(section_name) %}
27-
{% set _ = seen_sections.__setitem__(section_name, true) %}
3+
{% macro write_section(section_name, settings) %}
284
[{{ section_name }}]
29-
{% endif %}
30-
{{ key }} = {{ section[key] }}
5+
{% for key, val in settings.items() %}
6+
{% if val != {"state": "absent"} %}
7+
{{ key }} = {{ val }}
318
{% endif %}
329
{% endfor %}
33-
{% endfor %}
10+
{% endmacro %}
11+
[main]
12+
summary = kernel settings
13+
{% if __sysctl_has_values %}
14+
{{ write_section("sysctl", __kernel_settings_new_sysctl) -}}
15+
{% endif %}
16+
{% if __sysfs_has_values %}
17+
{{ write_section("sysfs", __kernel_settings_new_sysfs) -}}
18+
{% endif %}
19+
{% if __systemd_new | length > 0 %}
20+
[systemd]
21+
cpu_affinity = {{ __systemd_new }}
22+
{% endif %}
23+
{% if __trans_huge_new | length > 0 or __trans_defrag_new | length > 0 %}
24+
[vm]
25+
{% if __trans_huge_new | length > 0 %}
26+
transparent_hugepages = {{ __trans_huge_new }}
27+
{% endif %}
28+
{% if __trans_defrag_new | length > 0 %}
29+
transparent_hugepage.defrag = {{ __trans_defrag_new }}
30+
{% endif %}
31+
{% endif %}

tests/tasks/assert_kernel_settings_conf_files.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,16 @@
8080
ignore_errors: true
8181
register: __kernel_settings_register_verify_bl_cmdline
8282
when:
83-
- __kernel_settings_blcmdline_value | d()
83+
- __kernel_settings_blcmdline_value | d() is not none
84+
- __kernel_settings_blcmdline_value | d("") | length > 0
8485
changed_when: false
8586

8687
- name: Verify bootloader settings value
8788
set_fact:
8889
__kernel_settings_success: false
8990
when:
90-
- __kernel_settings_blcmdline_value | d()
91+
- __kernel_settings_blcmdline_value | d() is not none
92+
- __kernel_settings_blcmdline_value | d("") | length > 0
9193
- __kernel_settings_register_verify_bl_cmdline is defined
9294
- __kernel_settings_register_verify_bl_cmdline.stdout is defined
9395
- __kernel_settings_register_verify_bl_cmdline is failed or

tests/tasks/check_header.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
- name: Check for presence of ansible managed header, fingerprint
1010
assert:
1111
that:
12-
- ansible_managed in content
12+
- __ansible_managed in content
1313
- __fingerprint in content
1414
vars:
1515
content: "{{ (__file_content | d(__content)).content | b64decode }}"
16-
ansible_managed: "{{ lookup('template', 'get_ansible_managed.j2') }}"
16+
__ansible_managed: "{{ lookup('template', 'get_ansible_managed.j2') }}"

tests/vars/vars_simple_settings.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ __kernel_settings_profile_file: |
5353
/sys/kernel/debug/x86/ibrs_enabled = 0
5454
/sys/kernel/debug/x86/pti_enabled = 0
5555
/sys/kernel/debug/x86/retp_enabled = 0
56-
{% if __kernel_settings_blcmdline_value | d() %}
56+
{% if __kernel_settings_blcmdline_value | d() is not none and
57+
__kernel_settings_blcmdline_value | d("") | length > 0 %}
5758
[bootloader]
5859
cmdline = {{ __kernel_settings_blcmdline_value }}
5960
{% endif %}

0 commit comments

Comments
 (0)