diff --git a/changelogs/fragments/3074-ini_file-3031-empty-value-inconsistency.yml b/changelogs/fragments/3074-ini_file-3031-empty-value-inconsistency.yml new file mode 100644 index 0000000000..7bfe958a12 --- /dev/null +++ b/changelogs/fragments/3074-ini_file-3031-empty-value-inconsistency.yml @@ -0,0 +1,4 @@ +--- +bugfixes: + - ini_file - fix inconsistency between empty value and no value + (https://github.com/ansible-collections/community.general/issues/3031). diff --git a/plugins/modules/files/ini_file.py b/plugins/modules/files/ini_file.py index 7d6a988e85..a9c2e290b0 100644 --- a/plugins/modules/files/ini_file.py +++ b/plugins/modules/files/ini_file.py @@ -205,11 +205,11 @@ def do_ini(module, filename, section=None, option=None, value=None, for i in range(index, 0, -1): # search backwards for previous non-blank or non-comment line if not non_blank_non_comment_pattern.match(ini_lines[i - 1]): - if option and value: + if option and value is not None: ini_lines.insert(i, assignment_format % (option, value)) msg = 'option added' changed = True - elif option and not value and allow_no_value: + elif option and value is None and allow_no_value: ini_lines.insert(i, '%s\n' % option) msg = 'option added' changed = True @@ -225,7 +225,7 @@ def do_ini(module, filename, section=None, option=None, value=None, if state == 'present': # change the existing option line if match_opt(option, line): - if not value and allow_no_value: + if value is None and allow_no_value: newline = u'%s\n' % option else: newline = assignment_format % (option, value) @@ -324,7 +324,7 @@ def main(): create = module.params['create'] if state == 'present' and not allow_no_value and value is None: - module.fail_json("Parameter 'value' must not be empty if state=present and allow_no_value=False") + module.fail_json("Parameter 'value' must be defined if state=present and allow_no_value=False") (changed, backup_file, diff, msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create, allow_no_value) diff --git a/tests/integration/targets/ini_file/tasks/main.yml b/tests/integration/targets/ini_file/tasks/main.yml index 210dafe2ca..96c6771b9e 100644 --- a/tests/integration/targets/ini_file/tasks/main.yml +++ b/tests/integration/targets/ini_file/tasks/main.yml @@ -215,10 +215,10 @@ path: "{{ output_file }}" section: mysqld option: "{{ item.o }}" - value: "{{ item.v }}" + value: "{{ item.v | d(omit) }}" allow_no_value: yes with_items: - - { o: "skip-name-resolve", v: null } + - { o: "skip-name-resolve" } - { o: "max_connections", v: "500" } - name: read content from output file @@ -459,12 +459,23 @@ option: like value: tea state: absent - - name: Test with empty string + + # See https://github.com/ansible-collections/community.general/issues/3031 + - name: Tests with empty strings ini_file: path: "{{ output_file }}" - section: extensions - option: evolve + section: "{{ item.section | d('extensions') }}" + option: "{{ item.option }}" value: "" + allow_no_value: "{{ item.no_value | d(omit) }}" + loop: + - option: evolve + - option: regress + - section: foobar + option: foo + no_value: true + - option: improve + no_value: true - name: read content from output file slurp: @@ -473,7 +484,7 @@ - name: set expected content and get current ini file content set_fact: - expected15: "\n[extensions]\nevolve = \n" + expected15: "\n[extensions]\nevolve = \nregress = \nimprove = \n[foobar]\nfoo = \n" content15: "{{ output_content.content | b64decode }}" - debug: var=content15 - name: Verify content of ini file is as expected