From 5149f7c64079d95a968dbdfd4fa8c3aeee394532 Mon Sep 17 00:00:00 2001 From: Apoorv Darshan Date: Sat, 18 Jul 2026 00:04:17 +0530 Subject: [PATCH] ansible-config: default to checking all plugin configs (#87212) * ansible-config: default validate to checking all plugin configs ansible-config validate defaulted to -t base, so any configuration file using a section owned by a plugin (e.g. [ssh_connection]) was reported as an unknown section, and keys inside such sections were never validated at all - a stock, perfectly valid ansible.cfg failed validation out of the box. Default the validate action to -t all so installed plugin configuration is taken into account. An explicit -t still narrows validation, and the other ansible-config actions keep their base default (the -t default is now resolved per action in post_process_args, since the shared parent parser action object cannot carry per-subcommand defaults). Fixes #86398 Signed-off-by: Apoorv Darshan * Move -t to per-default shared parsers built by a factory Per review: instead of a None sentinel resolved in post_process_args, provide two small shared parent parsers for -t (one with default 'base', one with default 'all', built by a factory) so each subcommand's --help states its actual default. Signed-off-by: Apoorv Darshan * Address review: parametrize ansible-config type tests Deduplicate the three near-identical tests into a single @pytest.mark.parametrize with descriptive IDs, return the resolved type directly from the helper, add return-type annotations, and turn the helper's leading comment into a docstring. * Default ansible-config type to all for every action Broaden the new default as requested in review, while keeping -t base as the compatibility override for users who need the previous behavior. Cover every action and both explicit override paths in the parser tests. Assisted-by: OpenAI Codex Signed-off-by: Apoorv Darshan * Move ansible-config default coverage to integration tests Exercise the public CLI across every action and run existing init, validate, and dump scenarios without an explicit type. Remove the parser-only unit test and use translation-friendly changelog wording. Assisted-by: OpenAI Codex Signed-off-by: Apoorv Darshan * Document ansible-config default as breaking Move the entry into the generated porting-guide section and document the -t base compatibility override. Assisted-by: OpenAI Codex Signed-off-by: Apoorv Darshan --------- Signed-off-by: Apoorv Darshan --- ...98-ansible-config-validate-default-all.yml | 6 ++++ lib/ansible/cli/config.py | 7 +++-- .../targets/ansible-config/tasks/main.yml | 31 ++++++++++++++----- 3 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 changelogs/fragments/86398-ansible-config-validate-default-all.yml diff --git a/changelogs/fragments/86398-ansible-config-validate-default-all.yml b/changelogs/fragments/86398-ansible-config-validate-default-all.yml new file mode 100644 index 00000000000..418fe24614a --- /dev/null +++ b/changelogs/fragments/86398-ansible-config-validate-default-all.yml @@ -0,0 +1,6 @@ +breaking_changes: + - >- + ansible-config - all actions now default to ``-t all``, so configuration files using sections + owned by plugins (for example, ``[ssh_connection]``) are no longer reported as unknown sections, + and keys within those sections are actually validated. Use ``-t base`` to retain the previous + behavior (https://github.com/ansible/ansible/issues/86398). diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py index 8d21e78a238..c7bfe6d1ac1 100755 --- a/lib/ansible/cli/config.py +++ b/lib/ansible/cli/config.py @@ -103,8 +103,9 @@ class ConfigCLI(CLI): opt_help.add_verbosity_options(common) common.add_argument('-c', '--config', dest='config_file', help="path to configuration file, defaults to first file found in precedence.") - common.add_argument("-t", "--type", action="store", default='base', dest='type', choices=['all', 'base'] + list(C.CONFIGURABLE_PLUGINS), - help="Filter down to a specific plugin type.") + common.add_argument("-t", "--type", action="store", default='all', dest='type', + choices=['all', 'base'] + list(C.CONFIGURABLE_PLUGINS), + help="Filter down to a specific plugin type. Defaults to 'all'; use 'base' for the previous behavior.") common.add_argument('args', help='Specific plugin to target, requires type of plugin to be set', nargs='*') subparsers = self.parser.add_subparsers(dest='action') @@ -134,7 +135,7 @@ class ConfigCLI(CLI): validate_parser = subparsers.add_parser('validate', help='Validate the configuration file and environment variables. ' - 'By default it only checks the base settings without accounting for plugins (see -t).', + 'By default it checks the base settings and all installed plugins (use -t to narrow down).', parents=[common]) validate_parser.set_defaults(func=self.execute_validate) validate_parser.add_argument('--format', '-f', dest='format', action='store', choices=['ini', 'env'] , default='ini', diff --git a/test/integration/targets/ansible-config/tasks/main.yml b/test/integration/targets/ansible-config/tasks/main.yml index c3b46fa4daf..91d94ce331a 100644 --- a/test/integration/targets/ansible-config/tasks/main.yml +++ b/test/integration/targets/ansible-config/tasks/main.yml @@ -1,3 +1,21 @@ +- name: check the default type in help for every action + ansible.builtin.command: ansible-config {{ item }} --help + loop: + - list + - dump + - view + - init + - validate + register: config_help + changed_when: false + +- name: ensure every action documents all as the default type + ansible.builtin.assert: + that: + - >- + item.stdout is regex("Defaults to\\s*'all'") + loop: '{{ config_help.results }}' + - name: test ansible-config init for valid output and no dupes block: - name: Create temporary file @@ -7,17 +25,16 @@ suffix: temp.ini register: ini_tempfile - - name: run config full dump - shell: ansible-config init -t all > {{ini_tempfile.path}} + - name: run config full dump using the default type + shell: ansible-config init > {{ini_tempfile.path}} - name: run ini tester, for correctness and dupes shell: "{{ansible_playbook_python}} '{{role_path}}/files/ini_dupes.py' '{{ini_tempfile.path}}'" - name: test ansible-config validate block: - # not testing w/o -t all as ansible-test uses it's own plugins and would give false positives - - name: validate config files - shell: ansible-config validate -t all -v + - name: validate config files using the default type + shell: ansible-config validate -v register: valid_cfg loop: - empty.cfg @@ -142,8 +159,8 @@ vars: config_keys: "{{ config_dump['stdout'] | from_json | selectattr('name', 'defined') }}" block: - - name: run config full dump - shell: ansible-config dump -t all -f json + - name: run config full dump using the default type + shell: ansible-config dump -f json register: config_dump - name: validate we get 'internal' but not hidden (_Z_)