Hi,
I’m trying to override a base strategy in Ansible 6+.
So far, my code works perfectly fine on Ansible 5 and less, but as soon as I try it on a more recent version, it fails.
To illustrate my problem, I made a small reproducer.
A dumb playbook (which targets the default strategy, linear):
---
- hosts: localhost
gather_facts: no
tasks:
- ansible.builtin.debug:
msg: "Hello"
The overriding strategy (located in /usr/share/ansible/plugins/strategy/linear.py) :
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import sys
from ansible.plugins.strategy.linear import StrategyModule
class StrategyModule(StrategyModule):
def __init__(self, tqm):
super(StrategyModule, self).__init__(tqm)
def run(self, iterator, play_context):
print("Customizing the linear strategy")
return super(StrategyModule, self).run(iterator, play_context)
(the code is very similar to what we can find in the debug strategy)
Executing this code in a Ansible 5 Venv :
(ansible5) [root@max-rhel8 ~]# ansible-playbook main.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ************************************************************************************************************************************
Customizing the linear strategy
TASK [debug] ****************************************************************************************************************************************
ok: [localhost] => {
"msg": "Hello"
}
PLAY RECAP ******************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Executing the very same code in a Ansible 6 Venv :
(ansible6) [root@max-rhel8 ~]# ansible-playbook main.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ************************************************************************************************************************************
ERROR! Unexpected Exception, this is probably a bug: cannot import name 'StrategyModule' from 'ansible.plugins.strategy.linear' (/usr/share/ansible/plugins/strategy/linear.py)
to see the full traceback, use -vvv
I read in a Mitogen issue stating that calling the ansible.plugins.strategy package is generally a bad idea :
Regardless it's probably common across versions - "ansible.plugins.strategy.*" is a magic namespace managed by Ansible's PluginLoader. The solution is probably to avoid direct import, but asking PluginLoader to do it for us.
I then try to read about the PluginLoader and especially the strategy_loader, but I don’t think it’s the same usage and on top of that I don’t know how to use it.
I’ve found very few usecases and that kind of code doesn’t help me much.
from ansible.plugins.loader import strategy_loader
from ansible.plugins.strategy import StrategyBase
[ ... ]
strategy = strategy_loader.get(new_play.strategy, self)
If anyone has some insight on that one, I would be grateful.
Thanks.