From 2cd48e6e080930c3b6817ee3ec92388e350cd7a2 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 12 Jan 2022 10:29:11 +0100 Subject: [PATCH] cloudinit/importer.py: print a meaningful message if import fails Sometimes an import might fail for different reasons: the string is wrongly typed, or the module has a dependency that is not installed in python. We should print that there is an import error, otherwise it might be really difficult to understand what is the root cause of this issue. Currently, cloud-init just ignores the error and continues. This can have fatal consequences, especially when used to pick the datasource to use. For example, we can have a missing/misspelled datasource file: $ ls cloudinit/sources/DataSourceInexistent.py ls: cannot access 'cloudinit/sources/DataSourceInexistent.py': No such file or directory $ python >>> __import__("cloudinit.sources.DataSourceInexistent") and in this case cloud-init should also hint that the error is "No module named 'cloudinit.sources.DataSourceInexistent'" If instead the datasource exists but uses a dependency that is not installed (for example netifaces for DataSourceVMware): $ ls cloudinit/sources/DataSourceVMWare.py cloudinit/sources/DataSourceVMWare.py $ python >>> __import__("cloudinit.sources.DataSourceVMware") then cloud-init should hint that the error is "No module named 'netifaces'" Signed-off-by: Emanuele Giuseppe Esposito --- cloudinit/sources/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index 9083f39953a5..d55997babea9 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -929,6 +929,11 @@ def list_sources(cfg_list, depends, pkg_list): m_locs, _looked_locs = importer.find_module( ds_name, pkg_list, ["get_datasource_list"] ) + if not m_locs: + LOG.error( + f"Could not import {ds_name}. Does the DataSource exist and " + "is it importable?" + ) for m_loc in m_locs: mod = importer.import_module(m_loc) lister = getattr(mod, "get_datasource_list")