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

Unable to open /plugins/ssot/history/ on one of my nautobot instance #476

Open
dylanbob opened this issue Jul 9, 2024 · 6 comments
Open
Assignees
Labels
type: bug Issues/PRs addressing a bug.

Comments

@dylanbob
Copy link

dylanbob commented Jul 9, 2024

Environment

  • Python version: 3.11.9

  • Nautobot version: 2.2.4

  • nautobot-ssot version: How can I get that? probably 2.6.1

Expected Behavior

The /plugins/ssot/history/ would show

Observed Behavior

An error message was shown instead:

AttributeError at /plugins/ssot/history/

'NoneType' object has no attribute 'class_path'

Request Method: 	GET
Request URL: 	https://xxx.xxx.xxx.xxx/plugins/ssot/history/
Django Version: 	3.2.25
Exception Type: 	AttributeError
Exception Value: 	

'NoneType' object has no attribute 'class_path'

Exception Location: 	/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py, line 137, in get_source_url
Python Executable: 	/usr/local/bin/python3.11
Python Version: 	3.11.9
Python Path: 	

['.',
 '',
 '/opt/nautobot',
 '/usr/local/bin',
 '/usr/local/lib/python311.zip',
 '/usr/local/lib/python3.11',
 '/usr/local/lib/python3.11/lib-dynload',
 '/opt/nautobot/.local/lib/python3.11/site-packages',
 '/usr/local/lib/python3.11/site-packages']

Server time: 	Tue, 09 Jul 2024 16:10:41 +0200

Here is the complete traceback:

Environment:


Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/

Django Version: 3.2.25
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotConstanceConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'django_celery_results',
 'rest_framework',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.virtualization',
 'drf_spectacular',
 'drf_spectacular_sidecar',
 'graphene_django',
 'health_check',
 'health_check.storage',
 'django_extensions',
 'constance.backends.database',
 'django_ajax_tables',
 'silk',
 'nautobot_device_lifecycle_mgmt.NautobotDeviceLifecycleManagementConfig',
 'nautobot_ssot.NautobotSSOTAppConfig',
 'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'silk.middleware.SilkyMiddleware',
 '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']


Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
   'NoneType' object has no attribute 'class_path'
   10 :                     {% else %}
   11 :                         <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
   12 :                     {% endif %}
   13 :                 {% endfor %}
   14 :             </tr>
   15 :         </thead>
   16 :     {% endif %}
   17 :     <tbody>
   18 :         {% for row in table.page.object_list|default:table.rows %}
   19 :             <tr {{ row.attrs.as_html }}>
   20 :                  {% for column, cell in row.items %} 
   21 :                     <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   22 :                 {% endfor %}
   23 :             </tr>
   24 :         {% empty %}
   25 :             {% if table.empty_text %}
   26 :                 <tr>
   27 :                     <td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
   28 :                 </tr>
   29 :             {% endif %}
   30 :         {% endfor %}


Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 166, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 348, in get
    return render(request, self.template_name, context)
  File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 519, in render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
    return template.render(context={"table": table}, request=request)
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 214, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 170, in render
    values = list(values)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
    column.current_value = self.get_cell(column.name)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
    return self._get_and_render_with(
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
    return render_func(bound_column, value)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
    return bound_column.link(content, **render_kwargs) if bound_column.link else content
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
    attrs = self.get_attrs(**kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
    attrs["href"] = self.compose_url(**kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
    return call_with_appropriate(self.url, kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
    return fn(**kwargs)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 60, in <lambda>
    source = Column(linkify=lambda record: record.get_source_url())
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},

Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'

Steps to Reproduce

I do not realy know... I can only give you a lead, which is what I did.

  1. Import jobs using git
  2. Change/move jobs around, resyncing them
  3. Try to access /plugins/ssot/history/
@glennmatthews
Copy link
Contributor

My interpretation here is that SSOT get_source_url() is not accounting for the possibility that there is a JobResult from a Job that has subsequently been uninstalled or deleted.

@glennmatthews glennmatthews added the type: bug Issues/PRs addressing a bug. label Jul 9, 2024
@rifen
Copy link

rifen commented Jul 10, 2024

Ran into this as well, seemed like exactly that. After I had deleted all my not installed apps after a git repo sync then this began to occur in the dashboard and the history. Though the history is giving a <class 'MemoryError'> and the Dashboard is giving me AttributeError: 'NoneType' object has no attribute 'class_path'

@Kircheneer
Copy link
Contributor

Should be a straight-forward fix, to check if the job result exists here:

  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},

@Kircheneer
Copy link
Contributor

@dylanbob

nautobot-ssot version: How can I get that? probably 2.6.1

Under Apps -> Installed Apps or with pip show

As for the actual issue, we have found that we are unable to replicate this, at least consistently. Are you able to do this?

@dylanbob
Copy link
Author

dylanbob commented Sep 9, 2024

Hi. My environment changed since I opened this issue, now I have:

  • Python version: 3.11.9
  • Nautobot version: 2.3.1
  • nautobot-ssot version: 3.0.1

I was in 2.6.1 when I opened the issue.

I was able to reproduce the issue right now. Steps :

  1. import a job, using git (in my particular case)
  2. execute the job
  3. delete the job
  4. try to access /plugins/ssot/history/

At 4., the error occurs, here is the traceback:

Environment:


Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/

Django Version: 4.2.15
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotConstanceConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'django_celery_results',
 'rest_framework',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.cloud',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.virtualization',
 'drf_spectacular',
 'drf_spectacular_sidecar',
 'graphene_django',
 'health_check',
 'health_check.storage',
 'django_extensions',
 'django_ajax_tables',
 'silk',
 'nautobot_ssot.NautobotSSOTAppConfig',
 'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'silk.middleware.SilkyMiddleware',
 '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']


Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
   'NoneType' object has no attribute 'class_path'
   10 :                     {% else %}
   11 :                         <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
   12 :                     {% endif %}
   13 :                 {% endfor %}
   14 :             </tr>
   15 :         </thead>
   16 :     {% endif %}
   17 :     <tbody>
   18 :         {% for row in table.page.object_list|default:table.rows %}
   19 :             <tr {{ row.attrs.as_html }}>
   20 :                  {% for column, cell in row.items %} 
   21 :                     <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   22 :                 {% endfor %}
   23 :             </tr>
   24 :         {% empty %}
   25 :             {% if table.empty_text %}
   26 :                 <tr>
   27 :                     <td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
   28 :                 </tr>
   29 :             {% endif %}
   30 :         {% endfor %}


Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 168, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 391, in get
    return render(request, self.template_name, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
    result = block.nodelist.render(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
    result = block.nodelist.render(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 541, in render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
    return nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 208, in render
    return template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 177, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
    return nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
    return template.render(context={"table": table}, request=request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 238, in render
    nodelist.append(node.render_annotated(context))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 193, in render
    values = list(values)
             ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
    column.current_value = self.get_cell(column.name)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
    return self._get_and_render_with(
           
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
    return render_func(bound_column, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
    return bound_column.link(content, **render_kwargs) if bound_column.link else content
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
    attrs = self.get_attrs(**kwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
    attrs["href"] = self.compose_url(**kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
    return call_with_appropriate(self.url, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
    return fn(**kwargs)
           ^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 58, in <lambda>
    source = Column(linkify=lambda record: record.get_source_url())
                                           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 138, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'

@Renrut5
Copy link
Contributor

Renrut5 commented Sep 26, 2024

@Kircheneer @dylanbob

I'm still unable to replicate this issue in my environment.

I have:

  • Nautobot v2.3.1
  • SSoT App v3.0.1
  • Python v3.11

Steps I took:

  • Imported SSoT jobs via Git repository
  • Ran job from Git repo a couple times
  • Deleted jobs by deleting get repo from Nautobot

When I go to /plugins/ssot/history/, I don't get any errors.
image

I do get 404 errors when I try to open up one of the links to the missing job, though it's not the same error as described.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Issues/PRs addressing a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants