Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/+add-pulp-exceptions.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add more Pulp Exceptions.
178 changes: 178 additions & 0 deletions pulp_deb/app/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
from gettext import gettext as _

from pulpcore.plugin.exceptions import PulpException


class NoReleaseFile(PulpException):
"""
Raised when no Release file can be found at the expected URL.
"""

error_code = "DEB0001"

def __init__(self, url):
super().__init__()
self.url = url

def __str__(self):
return f"[{self.error_code}] " + _(
"Could not find a Release file at '{url}', try checking the 'url' and "
"'distributions' option on your remote"
).format(url=self.url)


class NoValidSignatureForKey(PulpException):
"""
Raised when verification of a Release file with the provided GPG key fails.
"""

error_code = "DEB0002"

def __init__(self, url):
super().__init__()
self.url = url

def __str__(self):
return f"[{self.error_code}] " + _(
"Unable to verify any Release files from '{url}' using the GPG key provided."
).format(url=self.url)


class NoPackageIndexFile(PulpException):
"""
Raised when no suitable package index file can be found.
"""

error_code = "DEB0003"

def __init__(self, relative_dir):
super().__init__()
self.relative_dir = relative_dir

def __str__(self):
return f"[{self.error_code}] " + _(
"No suitable package index files found in '{relative_dir}'. If you are syncing from "
"a partial mirror, you can ignore this error for individual remotes "
"(ignore_missing_package_indices='True') or system wide "
"(FORCE_IGNORE_MISSING_PACKAGE_INDICES setting)."
).format(relative_dir=self.relative_dir)


class MissingReleaseFileField(PulpException):
"""
Raised when an upstream Release file is missing a required field.
"""

error_code = "DEB0004"

def __init__(self, distribution, field):
super().__init__()
self.distribution = distribution
self.field = field

def __str__(self):
return f"[{self.error_code}] " + _(
"The release file for distribution '{distribution}' is missing "
"the required field '{field}'."
).format(distribution=self.distribution, field=self.field)


class UnknownNoSupportForArchitectureAllValue(PulpException):
"""
Raised when a Release file contains an unknown 'No-Support-for-Architecture-all' value.
"""

error_code = "DEB0005"

def __init__(self, release_file_path, unknown_value):
super().__init__()
self.release_file_path = release_file_path
self.unknown_value = unknown_value

def __str__(self):
return f"[{self.error_code}] " + _(
"The Release file at '{release_file_path}' contains the "
"'No-Support-for-Architecture-all' field, with unknown value '{unknown_value}'! "
"pulp_deb currently only understands the value 'Packages' for this field, please "
"open an issue at https://github.com/pulp/pulp_deb/issues specifying the remote "
"you are attempting to sync, so that we can improve pulp_deb!"
).format(
release_file_path=self.release_file_path,
unknown_value=self.unknown_value,
)


class DuplicateReleaseFile(PulpException):
"""
Raised when multiple ReleaseFile objects exist where only one is expected.
"""

error_code = "DEB0006"

def __init__(self, count):
super().__init__()
self.count = count

def __str__(self):
return f"[{self.error_code}] " + _(
"Previous ReleaseFile count: {count}. There should only be one."
).format(count=self.count)


class DuplicatePackageIndex(PulpException):
"""
Raised when multiple PackageIndex objects exist where only one is expected.
"""

error_code = "DEB0007"

def __init__(self, count):
super().__init__()
self.count = count

def __str__(self):
return f"[{self.error_code}] " + _(
"Previous PackageIndex count: {count}. There should only be one."
).format(count=self.count)


class SourceSyncNotSupported(PulpException):
"""
Raised when attempting to sync source repositories, which is not yet implemented.
"""

error_code = "DEB0008"

def __str__(self):
return f"[{self.error_code}] " + _("Syncing source repositories is not yet implemented.")


class DependencySolvingNotSupported(PulpException):
"""
Raised when advanced copy with dependency solving is requested.
"""

error_code = "DEB0009"

def __str__(self):
return f"[{self.error_code}] " + _(
"Advanced copy with dependency solving is not yet implemented."
)


class DuplicatePackageChecksumError(PulpException):
"""
Raised when newly added packages have the same name, version, and architecture
but different checksums.
"""

error_code = "DEB0011"

def __str__(self):
return f"[{self.error_code}] " + _(
"Cannot create repository version since there are newly added packages with the "
"same name, version, and architecture, but a different checksum. If the log level "
"is DEBUG, you can find a list of affected packages in the Pulp log. You can often "
"work around this issue by restricting syncs to only those distirbution component "
"combinations, that do not contain colliding duplicates!"
)
10 changes: 2 additions & 8 deletions pulp_deb/app/models/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)
from pulpcore.plugin.util import batch_qs, get_domain_pk

from pulp_deb.app.exceptions import DuplicatePackageChecksumError
from pulp_deb.app.models import (
AptReleaseSigningService,
AptRemote,
Expand Down Expand Up @@ -225,14 +226,7 @@ def handle_duplicate_packages(new_version):
)
log.debug(message.format(package_fields, distribution_components))

message = _(
"Cannot create repository version since there are newly added packages with the "
"same name, version, and architecture, but a different checksum. If the log level "
"is DEBUG, you can find a list of affected packages in the Pulp log. You can often "
"work around this issue by restricting syncs to only those distirbution component "
"combinations, that do not contain colliding duplicates!"
)
raise ValueError(message)
raise DuplicatePackageChecksumError()

# Now remove existing packages that are duplicates of any packages added to new_version
if package_qs_added.count() and content_qs_existing.count():
Expand Down
3 changes: 2 additions & 1 deletion pulp_deb/app/tasks/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pulpcore.plugin.models import RepositoryVersion
from pulpcore.plugin.util import get_domain_pk

from pulp_deb.app.exceptions import DependencySolvingNotSupported
from pulp_deb.app.models import (
AptRepository,
Package,
Expand Down Expand Up @@ -105,7 +106,7 @@ def process_entry(entry):
)

if dependency_solving:
raise NotImplementedError("Advanced copy with dependency solving is not yet implemented.")
raise DependencySolvingNotSupported()

for entry in config:
(
Expand Down
108 changes: 15 additions & 93 deletions pulp_deb/app/tasks/synchronizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from django.db.utils import IntegrityError
from rest_framework.exceptions import ValidationError

from pulpcore.plugin.exceptions import DigestValidationError
from pulpcore.plugin.exceptions import DigestValidationError, SyncError
from pulpcore.plugin.models import (
Artifact,
ProgressReport,
Expand All @@ -47,6 +47,16 @@
CHECKSUM_TYPE_MAP,
NO_MD5_WARNING_MESSAGE,
)
from pulp_deb.app.exceptions import (
DuplicatePackageIndex,
DuplicateReleaseFile,
MissingReleaseFileField,
NoPackageIndexFile,
NoReleaseFile,
NoValidSignatureForKey,
SourceSyncNotSupported,
UnknownNoSupportForArchitectureAllValue,
)
from pulp_deb.app.models import (
AptRemote,
AptRepository,
Expand All @@ -73,92 +83,6 @@
log = logging.getLogger(__name__)


class NoReleaseFile(Exception):
"""
Exception to signal, that no file representing a release is present.
"""

def __init__(self, url, *args, **kwargs):
"""
Exception to signal, that no file representing a release is present.
"""
super().__init__(
"Could not find a Release file at '{}', try checking the 'url' and "
"'distributions' option on your remote".format(url),
*args,
**kwargs,
)


class NoValidSignatureForKey(Exception):
"""
Exception to signal, that verification of release file with provided GPG key fails.
"""

def __init__(self, url, *args, **kwargs):
"""
Exception to signal, that verification of release file with provided GPG key fails.
"""
super().__init__(
"Unable to verify any Release files from '{}' using the GPG key provided.".format(url),
*args,
**kwargs,
)


class NoPackageIndexFile(Exception):
"""
Exception to signal, that no file representing a package index is present.
"""

def __init__(self, relative_dir, *args, **kwargs):
"""
Exception to signal, that no file representing a package index is present.
"""
self.relative_dir = relative_dir
message = (
"No suitable package index files found in '{}'. If you are syncing from a partial "
"mirror, you can ignore this error for individual remotes "
"(ignore_missing_package_indices='True') or system wide "
"(FORCE_IGNORE_MISSING_PACKAGE_INDICES setting)."
)
super().__init__(_(message).format(relative_dir), *args, **kwargs)

pass


class MissingReleaseFileField(Exception):
"""
Exception signifying that the upstream release file is missing a required field.
"""

def __init__(self, distribution, field, *args, **kwargs):
"""
The upstream release file is missing a required field.
"""
message = "The release file for distribution '{}' is missing the required field '{}'."
super().__init__(_(message).format(distribution, field), *args, **kwargs)


class UnknownNoSupportForArchitectureAllValue(Exception):
"""
Exception Signifying that the Release file contains the 'No-Support-for-Architecture-all' field,
but with a value other than 'Packages'. We interpret this as an error since this would likely
signify some unknown repo format, that pulp_deb is more likely to get wrong than right!
"""

def __init__(self, release_file_path, unknown_value, *args, **kwargs):
message = (
"The Release file at '{}' contains the 'No-Support-for-Architecture-all' field, with "
"unknown value '{}'! pulp_deb currently only understands the value 'Packages' for "
"this field, please open an issue at https://github.com/pulp/pulp_deb/issues "
"specifying the remote you are attempting to sync, so that we can improve pulp_deb!"
)
super().__init__(_(message).format(unknown_value), *args, **kwargs)

pass


def synchronize(remote_pk, repository_pk, mirror, optimize):
"""
Sync content from the remote repository.
Expand All @@ -180,7 +104,7 @@ def synchronize(remote_pk, repository_pk, mirror, optimize):
previous_repo_version = repository.latest_version()

if not remote.url:
raise ValueError(_("A remote must have a url specified to synchronize."))
raise SyncError(_("A remote must have a url specified to synchronize."))

if optimize and mirror:
skip_dist = []
Expand Down Expand Up @@ -902,7 +826,7 @@ async def _handle_flat_repo(

# Handle source package index
if self.remote.sync_sources:
raise NotImplementedError("Syncing source repositories is not yet implemented.")
raise SourceSyncNotSupported()

# Await all tasks
await asyncio.gather(*pending_tasks)
Expand Down Expand Up @@ -1315,8 +1239,7 @@ def get_previous_release_file(previous_version, distribution):
ReleaseFile.objects.filter(distribution=distribution)
)
if previous_release_file_qs.count() > 1:
message = "Previous ReleaseFile count: {}. There should only be one."
raise Exception(message.format(previous_release_file_qs.count()))
raise DuplicateReleaseFile(count=previous_release_file_qs.count())
return previous_release_file_qs.first()


Expand All @@ -1329,8 +1252,7 @@ def _get_previous_package_index(previous_version, relative_path):
PackageIndex.objects.filter(relative_path=relative_path)
)
if previous_package_index_qs.count() > 1:
message = "Previous PackageIndex count: {}. There should only be one."
raise Exception(message.format(previous_package_index_qs.count()))
raise DuplicatePackageIndex(count=previous_package_index_qs.count())
return previous_package_index_qs.first()


Expand Down
1 change: 1 addition & 0 deletions pulp_deb/tests/functional/api/test_duplicate_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def test_add_duplicates_to_repo(
deb_modify_repository(repository, {"add_content_units": [href1, href2]})

# Assert the error message.
assert "[DEB0011]" in str(exception.value.task.error["description"])
assert "Cannot create repository version since there are newly added packages with" in str(
exception.value.task.error["description"]
)
Loading
Loading