Skip to content

Commit e9d4c6a

Browse files
committed
Support setting whole section when option is unset
Docs sound like you can set a section by not setting option, but it didn't work previously, this fixes that.
1 parent d4f2b2f commit e9d4c6a

File tree

3 files changed

+247
-77
lines changed

3 files changed

+247
-77
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bugfixes:
2+
- "ini_file - fixes adding or replacing a whole section (https://github.com/ansible-collections/community.general/pull/10288)."

plugins/modules/ini_file.py

Lines changed: 98 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,13 @@
167167
value: lemonade
168168
mode: '0600'
169169
backup: true
170-
171170
- name: Ensure "temperature=cold is in section "[drinks]" in specified file
172171
community.general.ini_file:
173172
path: /etc/anotherconf
174173
section: drinks
175174
option: temperature
176175
value: cold
177176
backup: true
178-
179177
- name: Add "beverage=lemon juice" is in section "[drinks]" in specified file
180178
community.general.ini_file:
181179
path: /etc/conf
@@ -185,7 +183,6 @@
185183
mode: '0600'
186184
state: present
187185
exclusive: false
188-
189186
- name: Ensure multiple values "beverage=coke" and "beverage=pepsi" are in section "[drinks]" in specified file
190187
community.general.ini_file:
191188
path: /etc/conf
@@ -196,14 +193,12 @@
196193
- pepsi
197194
mode: '0600'
198195
state: present
199-
200196
- name: Add "beverage=lemon juice" outside a section in specified file
201197
community.general.ini_file:
202198
path: /etc/conf
203199
option: beverage
204200
value: lemon juice
205201
state: present
206-
207202
- name: Remove the peer configuration for 10.128.0.11/32
208203
community.general.ini_file:
209204
path: /etc/wireguard/wg0.conf
@@ -213,14 +208,12 @@
213208
value: 10.128.0.11/32
214209
mode: '0600'
215210
state: absent
216-
217211
- name: Add "beverage=lemon juice" outside a section in specified file
218212
community.general.ini_file:
219213
path: /etc/conf
220214
option: beverage
221215
value: lemon juice
222216
state: present
223-
224217
- name: Update the public key for peer 10.128.0.12/32
225218
community.general.ini_file:
226219
path: /etc/wireguard/wg0.conf
@@ -232,7 +225,6 @@
232225
value: xxxxxxxxxxxxxxxxxxxx
233226
mode: '0600'
234227
state: present
235-
236228
- name: Remove the peer configuration for 10.128.0.11/32
237229
community.general.ini_file:
238230
path: /etc/wireguard/wg0.conf
@@ -242,7 +234,6 @@
242234
value: 10.4.0.11/32
243235
mode: '0600'
244236
state: absent
245-
246237
- name: Update the public key for peer 10.128.0.12/32
247238
community.general.ini_file:
248239
path: /etc/wireguard/wg0.conf
@@ -254,6 +245,15 @@
254245
value: xxxxxxxxxxxxxxxxxxxx
255246
mode: '0600'
256247
state: present
248+
- name: Add or replace whole section
249+
community.general.ini_file:
250+
path: /etc/wireguard/wg0.conf
251+
section: Peer
252+
value: |
253+
AllowedIps = 10.4.0.11/32
254+
PublicKey = xxxxxxxxxxxxxxxxxxxx
255+
mode: '0600'
256+
state: present
257257
"""
258258

259259
import io
@@ -427,74 +427,86 @@ def do_ini(module, filename, section=None, section_has_values=None, option=None,
427427
# 2. edit all the remaining lines where we have a matching option
428428
# 3. delete remaining lines where we have a matching option
429429
# 4. insert missing option line(s) at the end of the section
430-
431-
if state == 'present' and option:
432-
for index, line in enumerate(section_lines):
433-
if match_function(option, line):
434-
match = match_function(option, line)
435-
if values and match.group(8) in values:
436-
matched_value = match.group(8)
437-
if not matched_value and allow_no_value:
430+
if state == 'present':
431+
if option:
432+
for index, line in enumerate(section_lines):
433+
if match_function(option, line):
434+
match = match_function(option, line)
435+
if values and match.group(8) in values:
436+
matched_value = match.group(8)
437+
if not matched_value and allow_no_value:
438+
# replace existing option with no value line(s)
439+
newline = u'%s\n' % option
440+
option_no_value_present = True
441+
else:
442+
# replace existing option=value line(s)
443+
newline = assignment_format % (option, matched_value)
444+
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
445+
values.remove(matched_value)
446+
elif not values and allow_no_value:
438447
# replace existing option with no value line(s)
439448
newline = u'%s\n' % option
449+
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
440450
option_no_value_present = True
441-
else:
442-
# replace existing option=value line(s)
443-
newline = assignment_format % (option, matched_value)
444-
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
445-
values.remove(matched_value)
446-
elif not values and allow_no_value:
447-
# replace existing option with no value line(s)
448-
newline = u'%s\n' % option
449-
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
450-
option_no_value_present = True
451-
break
452-
453-
if state == 'present' and exclusive and not allow_no_value:
454-
# override option with no value to option with value if not allow_no_value
455-
if len(values) > 0:
456-
for index, line in enumerate(section_lines):
457-
if not changed_lines[index] and match_function(option, line):
458-
newline = assignment_format % (option, values.pop(0))
459-
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
460-
if len(values) == 0:
461451
break
462-
# remove all remaining option occurrences from the rest of the section
463-
for index in range(len(section_lines) - 1, 0, -1):
464-
if not changed_lines[index] and match_function(option, section_lines[index]):
465-
del section_lines[index]
466-
del changed_lines[index]
467-
changed = True
468-
msg = 'option changed'
469452

470-
if state == 'present':
471-
# insert missing option line(s) at the end of the section
472-
for index in range(len(section_lines), 0, -1):
473-
# search backwards for previous non-blank or non-comment line
474-
if not non_blank_non_comment_pattern.match(section_lines[index - 1]):
475-
if option and values:
476-
# insert option line(s)
477-
for element in values[::-1]:
478-
# items are added backwards, so traverse the list backwards to not confuse the user
479-
# otherwise some of their options might appear in reverse order for whatever fancy reason ¯\_(ツ)_/¯
480-
if element is not None:
481-
# insert option=value line
482-
section_lines.insert(index, assignment_format % (option, element))
483-
msg = 'option added'
484-
changed = True
485-
elif element is None and allow_no_value:
486-
# insert option with no value line
487-
section_lines.insert(index, u'%s\n' % option)
488-
msg = 'option added'
489-
changed = True
490-
elif option and not values and allow_no_value and not option_no_value_present:
491-
# insert option with no value line(s)
492-
section_lines.insert(index, u'%s\n' % option)
493-
msg = 'option added'
494-
changed = True
495-
break
453+
if exclusive and not allow_no_value:
454+
# override option with no value to option with value if not allow_no_value
455+
if len(values) > 0:
456+
for index, line in enumerate(section_lines):
457+
if not changed_lines[index] and match_function(option, line):
458+
newline = assignment_format % (option, values.pop(0))
459+
(changed, msg) = update_section_line(option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg)
460+
if len(values) == 0:
461+
break
462+
# remove all remaining option occurrences from the rest of the section
463+
for index in range(len(section_lines) - 1, 0, -1):
464+
if not changed_lines[index] and match_function(
465+
option, section_lines[index]
466+
):
467+
del section_lines[index]
468+
del changed_lines[index]
469+
changed = True
470+
msg = 'option changed'
471+
472+
# insert missing option line(s) at the end of the section
473+
for index in range(len(section_lines), 0, -1):
474+
# search backwards for previous non-blank or non-comment line
475+
if not non_blank_non_comment_pattern.match(section_lines[index - 1]):
476+
if values:
477+
# insert option line(s)
478+
for element in values[::-1]:
479+
# items are added backwards, so traverse the list backwards to not confuse the user
480+
# otherwise some of their options might appear in reverse order for whatever fancy reason ¯\_(ツ)_/¯
481+
if element is not None:
482+
# insert option=value line
483+
section_lines.insert(
484+
index, assignment_format % (option, element)
485+
)
486+
msg = 'option added'
487+
changed = True
488+
elif element is None and allow_no_value:
489+
# insert option with no value line
490+
section_lines.insert(index, u'%s\n' % option)
491+
msg = 'option added'
492+
changed = True
493+
elif allow_no_value and not option_no_value_present :
494+
# insert option with no value line(s)
495+
section_lines.insert(index, u'%s\n' % option)
496+
msg = 'option added'
497+
changed = True
498+
break
499+
elif within_section and len(section_lines) > 0 and len(values) > 0:
500+
original = ''.join(section_lines[1:])
501+
replacement = ''.join(values)
502+
if not replacement.endswith('\n'):
503+
replacement += '\n'
504+
if original != replacement:
505+
section_lines = [section_lines[0], replacement]
506+
msg = 'section replaced'
507+
changed = True
496508

497-
if state == 'absent':
509+
if state == 'absent':
498510
if option:
499511
if exclusive:
500512
# delete all option line(s) with given option and ignore value
@@ -539,11 +551,20 @@ def do_ini(module, filename, section=None, section_has_values=None, option=None,
539551
for value in condition['values']:
540552
if value not in values:
541553
values.append(value)
542-
if option and values:
543-
for value in values:
544-
ini_lines.append(assignment_format % (option, value))
545-
elif option and not values and allow_no_value:
546-
ini_lines.append(u'%s\n' % option)
554+
if option:
555+
if values:
556+
for value in values:
557+
ini_lines.append(assignment_format % (option, value))
558+
elif not values and allow_no_value:
559+
ini_lines.append('%s\n' % option)
560+
else:
561+
msg = 'only section added'
562+
elif len(values) > 0:
563+
replacement = ''.join(values)
564+
if not replacement.endswith('\n'):
565+
replacement += '\n'
566+
ini_lines.append(replacement)
567+
msg = 'section added'
547568
else:
548569
msg = 'only section added'
549570
changed = True
@@ -659,4 +680,4 @@ def main():
659680

660681

661682
if __name__ == '__main__':
662-
main()
683+
main()

0 commit comments

Comments
 (0)