# How to use module\_utils in Event Driven Ansible (eda) plugins

**URL:** <https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274>\
**Category:** Get Help\
**Tags:** eda-server\
**Created:** [August 11, 2025, 5:55pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274 "2025-08-11T17:55:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [August 11, 2025, 5:55pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/1 "2025-08-11T17:55:35Z")

</div>

I am trying to write an Event Driven Ansible plugin that uses module\_utils from the same collection. I cannot get the imports working properly, so I was wondering if anyone had any idea on how to do this or what to try.

Here is my current work in progress: [check in changes by mikemorency · Pull Request #494 · ansible-collections/servicenow.itsm · GitHub](https://github.com/ansible-collections/servicenow.itsm/pull/494)

I’ve tried the following imports:

```auto
ansible_collections.servicenow.itsm.plugins.module_utils...
plugins.module_utils....
.......plugins.module_utils....

```

But they dont seem to work, even if I try to run the plugin using `ansible-rulebook`

---

<div class="post-metadata">

**Author:** ![Alex-Izquierdo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex-izquierdo/32/679_2.png) [@Alex-Izquierdo](https://forum.ansible.com/u/Alex-Izquierdo)\
**Post date:** [August 12, 2025, 10:40am UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/2 "2025-08-12T10:40:35Z")

</div>

You are trying an absolute import, but you want to load a local module, you can try a relative import, as it are already doing the modules, for example: [servicenow.itsm/plugins/modules/api.py at main · ansible-collections/servicenow.itsm · GitHub](https://github.com/ansible-collections/servicenow.itsm/blob/main/plugins/modules/api.py#L286)

> <https://github.com/ansible-collections/servicenow.itsm/blob/main/plugins/modules/api.py#L286>

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [August 12, 2025, 12:59pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/3 "2025-08-12T12:59:18Z")

</div>

Hi,

I changed my imports to this:

```auto
from .....plugins.module_utils.instance_config import get_combined_instance_config
from .....plugins.module_utils import client, table

```

And then ansible rulebook throws this error:

```auto
> ansible-galaxy collection install . --force; ansible-rulebook -E SN_HOST,SN_USERNAME,SN_PASSWORD -v -r test.yml

....
2025-08-12 08:57:14,129 - ansible_rulebook.app - ERROR - ImportError: attempted relative import with no known parent package
2025-08-12 08:57:14,129 - ansible_rulebook.app - ERROR - /home/mimorenc/.ansible/collections/ansible_collections/servicenow/itsm/extensions/eda/plugins/event_source/records.py:67 <module>
2025-08-12 08:57:14,130 - ansible_rulebook.app - ERROR - <frozen runpy>:88 _run_code
2025-08-12 08:57:14,130 - ansible_rulebook.app - ERROR - <frozen runpy>:98 _run_module_code
2025-08-12 08:57:14,130 - ansible_rulebook.app - ERROR - <frozen runpy>:291 run_path
2025-08-12 08:57:14,130 - ansible_rulebook.app - ERROR - /home/mimorenc/miniconda3/envs/test/lib/python3.11/site-packages/ansible_rulebook/engine.py:120 start_source
2025-08-12 08:57:14,130 - ansible_rulebook.app - INFO - Main complete
2025-08-12 08:57:14,130 - ansible_rulebook.cli - ERROR - Terminating: One of the source plugins failed

```

---

<div class="post-metadata">

**Author:** ![Alex-Izquierdo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex-izquierdo/32/679_2.png) [@Alex-Izquierdo](https://forum.ansible.com/u/Alex-Izquierdo)\
**Post date:** [August 12, 2025, 1:29pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/4 "2025-08-12T13:29:54Z")

</div>

This looks like a very nested relative import which might not be a good idea in terms of readability.  
The error “ImportError: attempted relative import with no known parent package”  
means the parent package is not actually a package, probably it is lacking ` __init__.py` files. ANy package needs this file to be recognized as package by python.

To avoid relative imports, you should be able to access the package by its full absolute package. You mentioned that `ansible_collections.servicenow.itsm.plugins.module_utils` didn’t work, but ansible-collections does not seem to be a package, just a github namespace.  
I think `from servicenow.itsm.plugins.module_utils.instance_config import get_combined_instance_config` should work.  
The problem that I see is that `servicenow.itsm` is interpreted as [pyproject]/itsm.  
I think the dot in the package name is problematic, if it does not work, you will might need to load the module explicitly with [importlib](https://docs.python.org/3/library/importlib.html#module-importlib.util)

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [August 12, 2025, 1:43pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/5 "2025-08-12T13:43:37Z")

</div>

I tried these without luck:

```auto
# from .....plugins.module_utils.instance_config import get_combined_instance_config
# from .....plugins.module_utils import client, table

# from servicenow.itsm.plugins.module_utils.instance_config import get_combined_instance_config
# from servicenow.itsm.plugins.module_utils import client, table

# from ansible_collections.servicenow.itsm.plugins.module_utils.instance_config import get_combined_instance_config
# from ansible_collections.servicenow.itsm.plugins.module_utils import client, table

```

Ill give the importlib approach a try and report back

---

<div class="post-metadata">

**Author:** ![Alex-Izquierdo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex-izquierdo/32/679_2.png) [@Alex-Izquierdo](https://forum.ansible.com/u/Alex-Izquierdo)\
**Post date:** [August 12, 2025, 2:05pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/6 "2025-08-12T14:05:21Z")

</div>

Another thing that I see is that you are placing a new instance\_config module in plugins/module\_utils that is out of the scope of extensions/eda/plugins.  
/plugins/module\_utils is intended for ansible-core while /extensions/eda/plugins is intended for ansible-rulebook.

Since this module is to be used by the source plugin, I suggest to locate in extensions/eda/plugins/utils, then you can use a relative import like `..utils` and that should work and probably would be a more readable code. (don’t forget to add an empty ` __init__.py` file so python can recognize it as package)

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [August 12, 2025, 2:53pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/7 "2025-08-12T14:53:07Z")

</div>

Unfortunately that creates a lot of duplicated code in our repository. The intent of using stuff from module\_utils is to use code that already exists for the modules or other plugins. The `instance_config` module specifically is code that is already in the inventory plugin but can be used by the EDA plugins. So I am moving it to a shared location, and then will update the inventory plugin to use that instead of local methods

---

<div class="post-metadata">

**Author:** ![Alex-Izquierdo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex-izquierdo/32/679_2.png) [@Alex-Izquierdo](https://forum.ansible.com/u/Alex-Izquierdo)\
**Post date:** [August 12, 2025, 3:59pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/8 "2025-08-12T15:59:03Z")

</div>

Ok, I just saw a new `instance_config` module in the PR and I thought that would be just for the eda plugin. For more reusability as you mention, my last comment is not a good idea, the explicit import with importlib to use on demand whatever you want for the rest of the collection seems to make more sense.

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [August 14, 2025, 1:20pm UTC](https://forum.ansible.com/t/how-to-use-module-utils-in-event-driven-ansible-eda-plugins/44274/9 "2025-08-14T13:20:44Z")

</div>

I tried using importlib without success. However, their docs suggest using sys.path instead, which is what I tried as a hack/stopgap so I will likely go with that.

For import lib i tried:

```auto
import pathlib
import importlib.util
import sys

def import_from_path(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module

CURRENT_EDA_PLUGIN_PATH = pathlib.Path( __file__ ).parent.resolve()
print(f"CURRENT_EDA_PLUGIN_PATH: {CURRENT_EDA_PLUGIN_PATH}")
MODULE_UTILS_PATH = f"{CURRENT_EDA_PLUGIN_PATH.parent.parent.parent.parent}/plugins/module_utils"
get_combined_instance_config = import_from_path("get_combined_instance_config", f"{MODULE_UTILS_PATH}/instance_config.py")
Client = import_from_path("Client", f"{MODULE_UTILS_PATH}/client.py")
TableClient = import_from_path("TableClient", f"{MODULE_UTILS_PATH}/table.py")

```

But kept getting `ImportError: attempted relative import with no known parent package`

The working approach with sys.path is

```auto
import sys
import os
project_root = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '../../../..'))
if project_root not in sys.path:
    sys.path.insert(0, project_root)

from plugins.module_utils.instance_config import get_combined_instance_config
from plugins.module_utils import client, table

```
