mirror of
https://github.com/ansible/ansible.git
synced 2026-07-30 16:14:40 +02:00
Add toggle to fix module_defaults with module-as-redirected-action on a per-module basis (#77265)
* If there is a platform specific handler, prefer the resolved module over the resolved action when loading module_defaults Add a toggle for action plugins to prefer the resolved module when loading module_defaults Allow moving away from modules intercepted as actions pattern Fixes #77059
This commit is contained in:
+46
@@ -1,3 +1,49 @@
|
||||
plugin_routing:
|
||||
action:
|
||||
# Backwards compat for modules-redirected-as-actions:
|
||||
# By default, each module_defaults entry is resolved as an action plugin,
|
||||
# and if it does not exist, it is resolved a a module.
|
||||
# All modules that redirect to the same action will resolve to the same action.
|
||||
module_uses_action_defaults:
|
||||
redirect: testns.testcoll.eos
|
||||
|
||||
# module-redirected-as-action overridden by action_plugin
|
||||
iosfacts:
|
||||
redirect: testns.testcoll.nope
|
||||
ios_facts:
|
||||
redirect: testns.testcoll.nope
|
||||
|
||||
redirected_action:
|
||||
redirect: testns.testcoll.ios
|
||||
modules:
|
||||
# Any module_defaults for testns.testcoll.module will not apply to a module_uses_action_defaults task:
|
||||
#
|
||||
# module_defaults:
|
||||
# testns.testcoll.module:
|
||||
# option: value
|
||||
#
|
||||
# But defaults for testns.testcoll.module_uses_action_defaults or testns.testcoll.eos will:
|
||||
#
|
||||
# module_defaults:
|
||||
# testns.testcoll.module_uses_action_defaults:
|
||||
# option: value
|
||||
# testns.testcoll.eos:
|
||||
# option: defined_last_i_win
|
||||
module_uses_action_defaults:
|
||||
redirect: testns.testcoll.module
|
||||
|
||||
# Not "eos_facts" to ensure TE is not finding handler via prefix
|
||||
# eosfacts tasks should not get eos module_defaults (or defaults for other modules that use eos action plugin)
|
||||
eosfacts:
|
||||
action_plugin: testns.testcoll.eos
|
||||
|
||||
# Test that `action_plugin` has higher precedence than module-redirected-as-action - reverse this?
|
||||
# Current behavior is iosfacts/ios_facts do not get ios defaults.
|
||||
iosfacts:
|
||||
redirect: testns.testcoll.ios_facts
|
||||
ios_facts:
|
||||
action_plugin: testns.testcoll.redirected_action
|
||||
|
||||
action_groups:
|
||||
testgroup:
|
||||
# Test metadata 'extend_group' feature does not get stuck in a recursive loop
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.plugins.action.normal import ActionModule as ActionBase
|
||||
from ansible.utils.vars import merge_hash
|
||||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
result['action_plugin'] = 'eos'
|
||||
|
||||
return result
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.plugins.action.normal import ActionModule as ActionBase
|
||||
from ansible.utils.vars import merge_hash
|
||||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
result['action_plugin'] = 'ios'
|
||||
|
||||
return result
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.plugins.action.normal import ActionModule as ActionBase
|
||||
from ansible.utils.vars import merge_hash
|
||||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
result['action_plugin'] = 'vyos'
|
||||
|
||||
return result
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: eosfacts
|
||||
short_description: module to test module_defaults
|
||||
description: module to test module_defaults
|
||||
version_added: '2.13'
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
eosfacts=dict(type=bool),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
module.exit_json(eosfacts=module.params['eosfacts'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: ios_facts
|
||||
short_description: module to test module_defaults
|
||||
description: module to test module_defaults
|
||||
version_added: '2.13'
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
ios_facts=dict(type=bool),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
module.exit_json(ios_facts=module.params['ios_facts'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: module
|
||||
short_description: module to test module_defaults
|
||||
description: module to test module_defaults
|
||||
version_added: '2.13'
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
action_option=dict(type=bool),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
module.exit_json(action_option=module.params['action_option'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: vyosfacts
|
||||
short_description: module to test module_defaults
|
||||
description: module to test module_defaults
|
||||
version_added: '2.13'
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
vyosfacts=dict(type=bool),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
module.exit_json(vyosfacts=module.params['vyosfacts'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
set -eux
|
||||
|
||||
# Symlink is test for backwards-compat (only workaround for https://github.com/ansible/ansible/issues/77059)
|
||||
sudo ln -s "${PWD}/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py" ./collections/ansible_collections/testns/testcoll/plugins/action/vyosfacts.py
|
||||
|
||||
ansible-playbook test_defaults.yml "$@"
|
||||
|
||||
sudo rm ./collections/ansible_collections/testns/testcoll/plugins/action/vyosfacts.py
|
||||
|
||||
ansible-playbook test_action_groups.yml "$@"
|
||||
|
||||
ansible-playbook test_action_group_metadata.yml "$@"
|
||||
|
||||
@@ -110,3 +110,140 @@
|
||||
- "builtin_legacy_defaults_2.msg == 'legacy default'"
|
||||
|
||||
- include_tasks: tasks/main.yml
|
||||
|
||||
- name: test preferring module name defaults for platform-specific actions
|
||||
hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: ensure eosfacts does not use action plugin default
|
||||
testns.testcoll.eosfacts:
|
||||
module_defaults:
|
||||
testns.testcoll.eos:
|
||||
fail: true
|
||||
|
||||
- name: eosfacts does use module name defaults
|
||||
testns.testcoll.eosfacts:
|
||||
module_defaults:
|
||||
testns.testcoll.eosfacts:
|
||||
eosfacts: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.eosfacts
|
||||
- result.action_plugin == 'eos'
|
||||
|
||||
- name: ensure vyosfacts does not use action plugin default
|
||||
testns.testcoll.vyosfacts:
|
||||
module_defaults:
|
||||
testns.testcoll.vyos:
|
||||
fail: true
|
||||
|
||||
- name: vyosfacts does use vyosfacts defaults
|
||||
testns.testcoll.vyosfacts:
|
||||
module_defaults:
|
||||
testns.testcoll.vyosfacts:
|
||||
vyosfacts: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.vyosfacts
|
||||
- result.action_plugin == 'vyos'
|
||||
|
||||
- name: iosfacts/ios_facts does not use action plugin default (module action_plugin field has precedence over module-as-action-redirect)
|
||||
collections:
|
||||
- testns.testcoll
|
||||
module_defaults:
|
||||
testns.testcoll.ios:
|
||||
fail: true
|
||||
block:
|
||||
- ios_facts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- iosfacts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- name: ensure iosfacts/ios_facts uses ios_facts defaults
|
||||
collections:
|
||||
- testns.testcoll
|
||||
module_defaults:
|
||||
testns.testcoll.ios_facts:
|
||||
ios_facts: true
|
||||
block:
|
||||
- ios_facts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.ios_facts
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- iosfacts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.ios_facts
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- name: ensure iosfacts/ios_facts uses iosfacts defaults
|
||||
collections:
|
||||
- testns.testcoll
|
||||
module_defaults:
|
||||
testns.testcoll.iosfacts:
|
||||
ios_facts: true
|
||||
block:
|
||||
- ios_facts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.ios_facts
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- iosfacts:
|
||||
register: result
|
||||
- assert:
|
||||
that:
|
||||
- result.ios_facts
|
||||
- result.action_plugin == 'ios'
|
||||
|
||||
- name: ensure redirected action gets redirected action defaults
|
||||
testns.testcoll.module_uses_action_defaults:
|
||||
module_defaults:
|
||||
testns.testcoll.module_uses_action_defaults:
|
||||
action_option: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.action_option
|
||||
- result.action_plugin == 'eos'
|
||||
|
||||
- name: ensure redirected action gets resolved action defaults
|
||||
testns.testcoll.module_uses_action_defaults:
|
||||
module_defaults:
|
||||
testns.testcoll.eos:
|
||||
action_option: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.action_option
|
||||
- result.action_plugin == 'eos'
|
||||
|
||||
- name: ensure redirected action does not use module-specific defaults
|
||||
testns.testcoll.module_uses_action_defaults:
|
||||
module_defaults:
|
||||
testns.testcoll.module:
|
||||
fail: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not result.action_option
|
||||
- result.action_plugin == 'eos'
|
||||
|
||||
Reference in New Issue
Block a user