Skip to content
This repository has been archived by the owner on Dec 7, 2022. It is now read-only.
/ pulp Public archive

Commit

Permalink
Make an Artifact from a PulpTemporaryUploadedFile
Browse files Browse the repository at this point in the history
Adds the Artifact.create_and_validate staticmethod that creates an
in-memory, unsaved Artifact from a PulpTemporaryUploadedFile. Uploaded
files to Pulp show up with that type so that is convenient for plugin
writers. Also as the file is received by Django it auto-computes all of
the digest types.

This PR also moves SizeValidationError and DigestValidation error to
pulpcore.exceptions instead of living in pulpcore.plugin.downloads.

The ArtifactSerializer is also exposed via the plugin API with this
change also.

https://pulp.plan.io/issues/4072
closes #4072
  • Loading branch information
Brian Bouterse committed Oct 9, 2018
1 parent d65d2d8 commit 50251ae
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 18 deletions.
6 changes: 3 additions & 3 deletions docs/plugins/plugin-api/download.rst
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,6 @@ descendants of BaseDownloader.
Validation Exceptions
---------------------

.. autoclass:: pulpcore.plugin.download.DigestValidationError
.. autoclass:: pulpcore.plugin.download.SizeValidationError
.. autoclass:: pulpcore.plugin.download.DownloaderValidationError
.. autoclass:: pulpcore.exceptions.DigestValidationError
.. autoclass:: pulpcore.exceptions.SizeValidationError
.. autoclass:: pulpcore.exceptions.ValidationError
2 changes: 0 additions & 2 deletions plugin/pulpcore/plugin/download/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from .base import BaseDownloader, DownloadResult # noqa
from .exceptions import (DigestValidationError, DownloaderValidationError, # noqa
SizeValidationError) # noqa
from .factory import DownloaderFactory # noqa
from .file import FileDownloader # noqa
from .http import HttpDownloader # noqa
18 changes: 9 additions & 9 deletions plugin/pulpcore/plugin/download/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import tempfile

from pulpcore.app.models import Artifact
from .exceptions import DigestValidationError, SizeValidationError
from pulpcore.exceptions import DigestValidationError, SizeValidationError


log = logging.getLogger(__name__)
Expand Down Expand Up @@ -109,11 +109,11 @@ def finalize(self):
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
Raises:
:class:`~pulpcore.plugin.download.DigestValidationError`: When any of the
``expected_digest`` values don't match the digest of the data passed to
:class:`~pulpcore.exceptions.DigestValidationError`: When any of the ``expected_digest``
values don't match the digest of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
:class:`~pulpcore.plugin.download.SizeValidationError`: When the
``expected_size`` value doesn't match the size of the data passed to
:class:`~pulpcore.exceptions.SizeValidationError`: When the ``expected_size`` value
doesn't match the size of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
"""
self._writer.flush()
Expand Down Expand Up @@ -162,8 +162,8 @@ def validate_digests(self):
Validate all digests validate if ``expected_digests`` is set
Raises:
:class:`~pulpcore.plugin.download.DigestValidationError`: When any of the
``expected_digest`` values don't match the digest of the data passed to
:class:`~pulpcore.exceptions.DigestValidationError`: When any of the ``expected_digest``
values don't match the digest of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
"""
if self.expected_digests:
Expand All @@ -176,8 +176,8 @@ def validate_size(self):
Validate the size if ``expected_size`` is set
Raises:
:class:`~pulpcore.plugin.download.SizeValidationError`: When the
``expected_size`` value doesn't match the size of the data passed to
:class:`~pulpcore.exceptions.SizeValidationError`: When the ``expected_size`` value
doesn't match the size of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
"""
if self.expected_size:
Expand Down
1 change: 1 addition & 0 deletions plugin/pulpcore/plugin/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Import Serializers in platform that are potentially useful to plugin writers
from pulpcore.app.serializers import ( # noqa
ArtifactSerializer,
AsyncOperationResponseSerializer,
ContentGuardSerializer,
ContentSerializer,
Expand Down
39 changes: 39 additions & 0 deletions pulpcore/pulpcore/app/models/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from itertools import chain

from pulpcore.app.models import Model, MasterModel, Notes, GenericKeyValueRelation, storage, fields
from pulpcore.exceptions import DigestValidationError, SizeValidationError


class Artifact(Model):
Expand Down Expand Up @@ -107,6 +108,44 @@ def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
self.file.delete(save=False)

@staticmethod
def init_and_validate(file, expected_digests=None, expected_size=None):
"""
Initialize an in-memory Artifact from an uploaded file, and validate digest and size info.
Args:
file (:class:`~pulpcore.app.files.PulpTemporaryUploadedFile`): The
PulpTemporaryUploadedFile to create the Artifact from.
expected_digests (dict): Keyed on the algorithm name provided by hashlib and stores the
value of the expected digest. e.g. {'md5': '912ec803b2ce49e4a541068d495ab570'}
expected_size (int): The number of bytes the download is expected to have.
Raises:
:class:`~pulpcore.exceptions.DigestValidationError`: When any of the ``expected_digest``
values don't match the digest of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
:class:`~pulpcore.exceptions.SizeValidationError`: When the ``expected_size`` value
doesn't match the size of the data passed to
:meth:`~pulpcore.plugin.download.BaseDownloader.handle_data`.
Returns:
An in-memory, unsaved :class:`~pulpcore.plugin.models.Artifact`
"""
if expected_size:
if file.size != expected_size:
raise SizeValidationError()

if expected_digests:
for algorithm, expected_digest in expected_digests.items():
if expected_digest != file.hashers[algorithm].hexdigest():
raise DigestValidationError()

attributes = {'size': file.size, 'file': file}
for algorithm in Artifact.DIGEST_FIELDS:
attributes[algorithm] = file.hashers[algorithm].hexdigest()

return Artifact(**attributes)


class Content(MasterModel):
"""
Expand Down
1 change: 1 addition & 0 deletions pulpcore/pulpcore/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .base import PulpException, exception_to_dict, ResourceImmutableError # noqa
from .http import MissingResource # noqa
from .validation import DigestValidationError, SizeValidationError, ValidationError # noqa
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
from pulpcore.exceptions import PulpException


class DownloaderValidationError(PulpException):
class ValidationError(PulpException):
"""
A base class for all Download Validation Errors.
A base class for all Validation Errors.
"""
pass


class DigestValidationError(DownloaderValidationError):
class DigestValidationError(ValidationError):
"""
Raised when a file fails to validate a digest checksum.
"""
Expand All @@ -22,7 +22,7 @@ def __str__(self):
return _("A file failed validation due to checksum.")


class SizeValidationError(DownloaderValidationError):
class SizeValidationError(ValidationError):
"""
Raised when a file fails to validate a size checksum.
"""
Expand Down

0 comments on commit 50251ae

Please sign in to comment.