Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.3: Jobs models from disabled plugins result in inconsistent UI behavior #1563

Closed
jathanism opened this issue Mar 29, 2022 · 4 comments · Fixed by #1590
Closed

v1.3: Jobs models from disabled plugins result in inconsistent UI behavior #1563

jathanism opened this issue Mar 29, 2022 · 4 comments · Fixed by #1590
Assignees
Labels
type: bug Something isn't working as expected
Milestone

Comments

@jathanism
Copy link
Contributor

Environment

  • Python version:
  • Nautobot version:

Steps to Reproduce

  1. Make sure a worker is running
  2. Enable example_plugin (PLUGINS = ["example_plugin"] in nautobot_config.py)
  3. Run migrations
  4. Restart Nautobot to get Job models populated for each job provided by example_plugin
  5. Navigate to Jobs list, then "Example logging" job
  6. Observe that this job is "Installed = True", "Enabled = False"; edit the job, and set "Enabled = True"
  7. Run the job. It should succeed.
  8. Disable example_plugin in nautobot_config.py
  9. Restart Nautobot again
  10. Observe that job is still set to "Installed = True"
  11. Click "Run/Schedule"

Expected Behavior

Job should not run, displaying an error in UI.

Observed Behavior

500 error with

Environment:


Request Method: GET
Request URL: http://localhost:6789/extras/jobs/plugins-example_plugin-jobs-exampleloggingjob/run/

Django Version: 3.2.12
Python Version: 3.9.2
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'cacheops',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'mptt',
 'rest_framework',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotConstanceConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.utilities',
 'nautobot.virtualization',
 'django_rq',
 'drf_spectacular',
 'drf_spectacular_sidecar',
 'graphene_django',
 'health_check',
 'health_check.cache',
 'health_check.storage',
 'django_extensions',
 'nautobot.core.apps.ConstanceDatabaseAppConfig',
 'django_ajax_tables',
 'sentry_sdk',
 'crispy_forms']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'nautobot.core.middleware.ExceptionHandlingMiddleware',
 'nautobot.core.middleware.RemoteUserMiddleware',
 'nautobot.core.middleware.ExternalAuthMiddleware',
 'nautobot.core.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware']



Traceback (most recent call last):
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/sentry_sdk/integrations/django/views.py", line 67, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/jathan/sandbox/src/nautobot/nautobot/utilities/views.py", line 94, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/Users/jathan/sandbox/src/nautobot/nautobot/extras/views.py", line 953, in get
    job_form = job_model.job_class().as_form(initial=normalize_querydict(request.GET))
  File "/Users/jathan/sandbox/src/nautobot/nautobot/extras/jobs.py", line 301, in as_form
    job_model = JobModel.objects.get_for_class_path(self.class_path)
  File "/Users/jathan/Library/Caches/pypoetry/virtualenvs/nautobot-b2ttWva6-py3.9/lib/python3.9/site-packages/django/utils/functional.py", line 61, in __get__
    return self.fget(cls)
  File "/Users/jathan/sandbox/src/nautobot/nautobot/extras/jobs.py", line 154, in class_path
    raise RuntimeError(

Exception Type: RuntimeError at /extras/jobs/plugins-example_plugin-jobs-exampleloggingjob/run/
Exception Value: Unknown/unexpected job file_path /Users/jathan/sandbox/src/nautobot/examples/example_plugin/example_plugin/jobs.py, should be one of /Users/jathan/.nautobot/jobs, /Users/jathan/.nautobot/git
@jathanism jathanism added type: bug Something isn't working as expected status: accepted labels Mar 29, 2022
@glennmatthews
Copy link
Contributor

On the one hand, this is incorrect usage (after installing or uninstalling a plugin you should run nautobot-server post_upgrade), but on the other hand we should at least have code to catch and gracefully handle this issue. Thanks for finding and documenting this. :-)

@bryanculver bryanculver added this to the v1.3.0 milestone Mar 30, 2022
@jathanism
Copy link
Contributor Author

jathanism commented Mar 30, 2022

Just as a quick initial pass, catching the exception and printing an error message like this:

index 5c570b600..d2ded44f6 100644
--- a/nautobot/extras/views.py
+++ b/nautobot/extras/views.py
@@ -950,7 +950,12 @@ class JobView(ObjectPermissionRequiredMixin, View):
     def get(self, request, class_path=None, slug=None):
         job_model = self._get_job_model_or_404(class_path, slug)

-        job_form = job_model.job_class().as_form(initial=normalize_querydict(request.GET))
+        try:
+            job_form = job_model.job_class().as_form(initial=normalize_querydict(request.GET))
+        except RuntimeError as err:
+            job_form = None
+            messages.error(request, f"Unable to run or schedule job: {err}")
+
         schedule_form = forms.JobScheduleForm(initial=normalize_querydict(request.GET))

         return render(
(END)

Results in this:
Example_logging_job__-_Nautobot

So not perfect or ideal, because you can still click the "Run/Schedule" button which results in the same 500 error. Ideally we'd want to go back to the preceding page and display the error there.

@jathanism
Copy link
Contributor Author

Better:
image

@bryanculver
Copy link
Member

Closed with #1590

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug Something isn't working as expected
Projects
No open projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants