Project

Profile

Help

Issue #4340

closed

"artifact" field causes serialization to blow up if the content units were lazily synced

Added by dalley about 5 years ago. Updated over 4 years ago.

Status:
CLOSED - CURRENTRELEASE
Priority:
Normal
Assignee:
Sprint/Milestone:
Start date:
Due date:
Estimated time:
Severity:
2. Medium
Platform Release:
OS:
Triaged:
Yes
Groomed:
No
Sprint Candidate:
No
Tags:
Sprint:
Sprint 48
Quarter:

Description

If you do a lazy sync and then hit up the http GET :8000/pulp/api/v3/content/file/files/ endpoint, you're greeted with a 500 error and the following traceback:


Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: pulp: django.request:ERROR: Internal Server Error: /pulp/api/v3/content/file/files/
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: Traceback (most recent call last):
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/options.py", line 564, in get_field
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return self.fields_map[field_name]
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: KeyError: 'artifact'
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: During handling of the above exception, another exception occurred:
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: Traceback (most recent call last):
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/base.py", line 635, in serializable_value
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     field = self._meta.get_field(field_name)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/options.py", line 566, in get_field
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: django.core.exceptions.FieldDoesNotExist: FileContent has no field named 'artifact'
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: During handling of the above exception, another exception occurred:
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: Traceback (most recent call last):
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     response = get_response(request)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     response = self.process_exception_by_middleware(e, request)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     response = wrapped_callback(request, *callback_args, **callback_kwargs)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return view_func(*args, **kwargs)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/viewsets.py", line 116, in view
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return self.dispatch(request, *args, **kwargs)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/views.py", line 495, in dispatch
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     response = self.handle_exception(exc)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/views.py", line 455, in handle_exception
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     self.raise_uncaught_exception(exc)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/views.py", line 492, in dispatch
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     response = handler(request, *args, **kwargs)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/mixins.py", line 45, in list
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return self.get_paginated_response(serializer.data)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/serializers.py", line 765, in data
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     ret = super(ListSerializer, self).data
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/serializers.py", line 262, in data
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     self._data = self.to_representation(self.instance)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/serializers.py", line 683, in to_representation
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     self.child.to_representation(item) for item in iterable
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/serializers.py", line 683, in <listcomp>
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     self.child.to_representation(item) for item in iterable
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/serializers.py", line 514, in to_representation
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     attribute = field.get_attribute(instance)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/rest_framework/relations.py", line 182, in get_attribute
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     value = attribute_instance.serializable_value(self.source_attrs[-1])
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/base.py", line 637, in serializable_value
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return getattr(self, field_name)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/pulp_file/app/models.py", line 33, in artifact
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return self._artifacts.get().pk
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     return getattr(self.get_queryset(), name)(*args, **kwargs)
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:   File "/usr/local/lib/pulp/lib64/python3.7/site-packages/django/db/models/query.py", line 399, in get
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]:     self.model._meta.object_name
Dec 20 18:18:08 p3.pulp.vm gunicorn[10767]: pulpcore.app.models.content.Artifact.DoesNotExist: Artifact matching query does not exist

The problem is that if you use lazy sync, there's no artifact, so this code will fail.

    @property
    def artifact(self):
        """
        Return the artifact id (there is only one for this content type).
        """
        return self._artifacts.get().pk

This problem is not specific to the file plugin, it's one which probably affects every plugin that copied this setter... which is all of them?

A simple fix to this would be to do something like this:

        x = self._artifacts.first()
        if x is None:
            return None
        return x.pk

Then, when the "artifact" has not yet been created, it would be listed as "null".


Related issues

Related to Pulp - Issue #4329: Not able to get URLs for the content types present in the repository versionCLOSED - DUPLICATEdalleyActions
Copied to File Support - Test #4463: Assert that accessing content endpoint does not raise 500 for lazy synced contentCLOSED - COMPLETEkersomActions
Actions #1

Updated by gmbnomis about 5 years ago

Just to confirm: I had the same issue in pulp_cookbook and solved it the way you propose above. The property looks as follows now (not pushed to GitHub yet):

    @property
    def artifact(self):
        try:
            return self._artifacts.get().pk
        except Artifact.DoesNotExist:
            return None

And I added a ping to the cookbook plugin maintainer to the checklist ;-)

Actions #2

Updated by gmbnomis about 5 years ago

Actions #3

Updated by dalley about 5 years ago

Thanks!

Long term, I would really like to get rid of this boilerplate entirely (somehow), but I decided to leave that discussion off the issue for the time being.

Actions #4

Updated by dalley about 5 years ago

  • Related to Issue #4329: Not able to get URLs for the content types present in the repository version added
Actions #5

Updated by CodeHeeler about 5 years ago

  • Triaged changed from No to Yes
  • Sprint set to Sprint 47
Actions #6

Updated by rchan about 5 years ago

  • Sprint changed from Sprint 47 to Sprint 48
Actions #7

Updated by dalley about 5 years ago

  • Tags Pulp 3 RC Blocker added
Actions #8

Updated by dalley about 5 years ago

  • Status changed from ASSIGNED to POST

This issue will be fixed by this PR as part of a larger effort to purge this boilerplate from the plugins.

https://github.com/pulp/pulp_file/pull/159

Story here with more details:

https://pulp.plan.io/issues/4366

Since the idea will be to get rid of this boilerplate altogether, I'm going to get rid of the checklist and consider this issue fixed as soon as the File PR is merged. The linked story has a checklist which I will use.

Actions #9

Updated by dalley about 5 years ago

  • Status changed from POST to MODIFIED
Actions #10

Updated by bherring about 5 years ago

  • Copied to Test #4463: Assert that accessing content endpoint does not raise 500 for lazy synced content added
Actions #11

Updated by bmbouter almost 5 years ago

  • Tags deleted (Pulp 3, Pulp 3 RC Blocker)
Actions #12

Updated by bmbouter over 4 years ago

  • Sprint/Milestone set to 0.1.0
Actions #13

Updated by bmbouter over 4 years ago

  • Status changed from MODIFIED to CLOSED - CURRENTRELEASE

Also available in: Atom PDF