Kaynağa Gözat

Closes #5327: Be more strict when capturing anticipated ImportError exceptions

Jeremy Stretch 5 yıl önce
ebeveyn
işleme
9b2dc89c6c

+ 1 - 0
docs/release-notes/version-2.9.md

@@ -6,6 +6,7 @@
 
 
 * [#5304](https://github.com/netbox-community/netbox/issues/5304) - Return server error messages as JSON when handling REST API requests
 * [#5304](https://github.com/netbox-community/netbox/issues/5304) - Return server error messages as JSON when handling REST API requests
 * [#5310](https://github.com/netbox-community/netbox/issues/5310) - Link to rack groups within rack list table
 * [#5310](https://github.com/netbox-community/netbox/issues/5310) - Link to rack groups within rack list table
+* [#5327](https://github.com/netbox-community/netbox/issues/5327) - Be more strict when capturing anticipated ImportError exceptions
 
 
 ### Bug Fixes
 ### Bug Fixes
 
 

+ 9 - 7
netbox/dcim/api/views.py

@@ -396,9 +396,7 @@ class DeviceViewSet(CustomFieldModelViewSet, ConfigContextQuerySetMixin):
         if device.platform is None:
         if device.platform is None:
             raise ServiceUnavailable("No platform is configured for this device.")
             raise ServiceUnavailable("No platform is configured for this device.")
         if not device.platform.napalm_driver:
         if not device.platform.napalm_driver:
-            raise ServiceUnavailable("No NAPALM driver is configured for this device's platform {}.".format(
-                device.platform
-            ))
+            raise ServiceUnavailable(f"No NAPALM driver is configured for this device's platform: {device.platform}.")
 
 
         # Check for primary IP address from NetBox object
         # Check for primary IP address from NetBox object
         if device.primary_ip:
         if device.primary_ip:
@@ -407,21 +405,25 @@ class DeviceViewSet(CustomFieldModelViewSet, ConfigContextQuerySetMixin):
             # Raise exception for no IP address and no Name if device.name does not exist
             # Raise exception for no IP address and no Name if device.name does not exist
             if not device.name:
             if not device.name:
                 raise ServiceUnavailable(
                 raise ServiceUnavailable(
-                    "This device does not have a primary IP address or device name to lookup configured.")
+                    "This device does not have a primary IP address or device name to lookup configured."
+                )
             try:
             try:
                 # Attempt to complete a DNS name resolution if no primary_ip is set
                 # Attempt to complete a DNS name resolution if no primary_ip is set
                 host = socket.gethostbyname(device.name)
                 host = socket.gethostbyname(device.name)
             except socket.gaierror:
             except socket.gaierror:
                 # Name lookup failure
                 # Name lookup failure
                 raise ServiceUnavailable(
                 raise ServiceUnavailable(
-                    f"Name lookup failure, unable to resolve IP address for {device.name}. Please set Primary IP or setup name resolution.")
+                    f"Name lookup failure, unable to resolve IP address for {device.name}. Please set Primary IP or "
+                    f"setup name resolution.")
 
 
         # Check that NAPALM is installed
         # Check that NAPALM is installed
         try:
         try:
             import napalm
             import napalm
             from napalm.base.exceptions import ModuleImportError
             from napalm.base.exceptions import ModuleImportError
-        except ImportError:
-            raise ServiceUnavailable("NAPALM is not installed. Please see the documentation for instructions.")
+        except ModuleNotFoundError as e:
+            if getattr(e, 'name') == 'napalm':
+                raise ServiceUnavailable("NAPALM is not installed. Please see the documentation for instructions.")
+            raise e
 
 
         # Validate the configured driver
         # Validate the configured driver
         try:
         try:

+ 14 - 9
netbox/netbox/authentication.py

@@ -137,19 +137,24 @@ class LDAPBackend:
 
 
     def __new__(cls, *args, **kwargs):
     def __new__(cls, *args, **kwargs):
         try:
         try:
-            import ldap
             from django_auth_ldap.backend import LDAPBackend as LDAPBackend_, LDAPSettings
             from django_auth_ldap.backend import LDAPBackend as LDAPBackend_, LDAPSettings
-        except ImportError:
-            raise ImproperlyConfigured(
-                "LDAP authentication has been configured, but django-auth-ldap is not installed."
-            )
+            import ldap
+        except ModuleNotFoundError as e:
+            if getattr(e, 'name') == 'django_auth_ldap':
+                raise ImproperlyConfigured(
+                    "LDAP authentication has been configured, but django-auth-ldap is not installed."
+                )
+            raise e
 
 
         try:
         try:
             from netbox import ldap_config
             from netbox import ldap_config
-        except ImportError:
-            raise ImproperlyConfigured(
-                "ldap_config.py does not exist"
-            )
+        except ModuleNotFoundError as e:
+            if getattr(e, 'name') == 'ldap_config':
+                raise ImproperlyConfigured(
+                    "LDAP configuration file not found: Check that ldap_config.py has been created alongside "
+                    "configuration.py."
+                )
+            raise e
 
 
         try:
         try:
             getattr(ldap_config, 'AUTH_LDAP_SERVER_URI')
             getattr(ldap_config, 'AUTH_LDAP_SERVER_URI')

+ 20 - 14
netbox/netbox/settings.py

@@ -38,10 +38,12 @@ if platform.python_version_tuple() < ('3', '6'):
 # Import configuration parameters
 # Import configuration parameters
 try:
 try:
     from netbox import configuration
     from netbox import configuration
-except ImportError:
-    raise ImproperlyConfigured(
-        "Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation."
-    )
+except ModuleNotFoundError as e:
+    if getattr(e, 'name') == 'configuration':
+        raise ImproperlyConfigured(
+            "Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation."
+        )
+    raise
 
 
 # Enforce required configuration parameters
 # Enforce required configuration parameters
 for parameter in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY', 'REDIS']:
 for parameter in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY', 'REDIS']:
@@ -183,11 +185,13 @@ if STORAGE_BACKEND is not None:
 
 
         try:
         try:
             import storages.utils
             import storages.utils
-        except ImportError:
-            raise ImproperlyConfigured(
-                "STORAGE_BACKEND is set to {} but django-storages is not present. It can be installed by running 'pip "
-                "install django-storages'.".format(STORAGE_BACKEND)
-            )
+        except ModuleNotFoundError as e:
+            if getattr(e, 'name') == 'storages':
+                raise ImproperlyConfigured(
+                    f"STORAGE_BACKEND is set to {STORAGE_BACKEND} but django-storages is not present. It can be "
+                    f"installed by running 'pip install django-storages'."
+                )
+            raise e
 
 
         # Monkey-patch django-storages to fetch settings from STORAGE_CONFIG
         # Monkey-patch django-storages to fetch settings from STORAGE_CONFIG
         def _setting(name, default=None):
         def _setting(name, default=None):
@@ -596,11 +600,13 @@ for plugin_name in PLUGINS:
     # Import plugin module
     # Import plugin module
     try:
     try:
         plugin = importlib.import_module(plugin_name)
         plugin = importlib.import_module(plugin_name)
-    except ImportError:
-        raise ImproperlyConfigured(
-            "Unable to import plugin {}: Module not found. Check that the plugin module has been installed within the "
-            "correct Python environment.".format(plugin_name)
-        )
+    except ModuleNotFoundError as e:
+        if getattr(e, 'name') == plugin_name:
+            raise ImproperlyConfigured(
+                "Unable to import plugin {}: Module not found. Check that the plugin module has been installed within the "
+                "correct Python environment.".format(plugin_name)
+            )
+        raise e
 
 
     # Determine plugin config and add to INSTALLED_APPS.
     # Determine plugin config and add to INSTALLED_APPS.
     try:
     try: