Skip to content

Commit

Permalink
ansible-config dedupe ini plugin entries (#82498)
Browse files Browse the repository at this point in the history
 added test for ini file integrity, also ensuring no dupes

(cherry picked from commit 6c2895f)
  • Loading branch information
bcoca authored and mattclay committed Jan 19, 2024
1 parent 9252584 commit 46d9d4b
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 14 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/dedupe_config_init.yml
@@ -0,0 +1,2 @@
bugfixes:
- ansible-config init will now dedupe ini entries from plugins.
36 changes: 22 additions & 14 deletions lib/ansible/cli/config.py
Expand Up @@ -314,7 +314,7 @@ def _get_settings_vars(self, settings, subkey):

return data

def _get_settings_ini(self, settings):
def _get_settings_ini(self, settings, seen):

sections = {}
for o in sorted(settings.keys()):
Expand All @@ -327,7 +327,7 @@ def _get_settings_ini(self, settings):

if not opt.get('description'):
# its a plugin
new_sections = self._get_settings_ini(opt)
new_sections = self._get_settings_ini(opt, seen)
for s in new_sections:
if s in sections:
sections[s].extend(new_sections[s])
Expand All @@ -343,37 +343,45 @@ def _get_settings_ini(self, settings):

if 'ini' in opt and opt['ini']:
entry = opt['ini'][-1]
if entry['section'] not in seen:
seen[entry['section']] = []
if entry['section'] not in sections:
sections[entry['section']] = []

default = opt.get('default', '')
if opt.get('type', '') == 'list' and not isinstance(default, string_types):
# python lists are not valid ini ones
default = ', '.join(default)
elif default is None:
default = ''
# avoid dupes
if entry['key'] not in seen[entry['section']]:
seen[entry['section']].append(entry['key'])

default = opt.get('default', '')
if opt.get('type', '') == 'list' and not isinstance(default, string_types):
# python lists are not valid ini ones
default = ', '.join(default)
elif default is None:
default = ''

if context.CLIARGS['commented']:
entry['key'] = ';%s' % entry['key']

if context.CLIARGS['commented']:
entry['key'] = ';%s' % entry['key']
key = desc + '\n%s=%s' % (entry['key'], default)

key = desc + '\n%s=%s' % (entry['key'], default)
sections[entry['section']].append(key)
sections[entry['section']].append(key)

return sections

def execute_init(self):
"""Create initial configuration"""

seen = {}
data = []
config_entries = self._list_entries_from_args()
plugin_types = config_entries.pop('PLUGINS', None)

if context.CLIARGS['format'] == 'ini':
sections = self._get_settings_ini(config_entries)
sections = self._get_settings_ini(config_entries, seen)

if plugin_types:
for ptype in plugin_types:
plugin_sections = self._get_settings_ini(plugin_types[ptype])
plugin_sections = self._get_settings_ini(plugin_types[ptype], seen)
for s in plugin_sections:
if s in sections:
sections[s].extend(plugin_sections[s])
Expand Down
2 changes: 2 additions & 0 deletions test/integration/targets/ansible-config/aliases
@@ -0,0 +1,2 @@
shippable/posix/group5
context/controller
12 changes: 12 additions & 0 deletions test/integration/targets/ansible-config/files/ini_dupes.py
@@ -0,0 +1,12 @@
#!/usr/bin/env python
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import annotations

import configparser
import sys


ini_file = sys.argv[1]
c = configparser.ConfigParser(strict=True, inline_comment_prefixes=(';',))
c.read_file(open(ini_file))
14 changes: 14 additions & 0 deletions test/integration/targets/ansible-config/tasks/main.yml
@@ -0,0 +1,14 @@
- name: test ansible-config for valid output and no dupes
block:
- name: Create temporary file
tempfile:
path: '{{output_dir}}'
state: file
suffix: temp.ini
register: ini_tempfile

- name: run config full dump
shell: ansible-config init -t all > {{ini_tempfile.path}}

- name: run ini tester, for correctness and dupes
shell: "{{ansible_playbook_python}} '{{role_path}}/files/ini_dupes.py' '{{ini_tempfile.path}}'"

0 comments on commit 46d9d4b

Please sign in to comment.