From 2c7c26215cf5e2ce31a3cf5be9f0802a43e2b309 Mon Sep 17 00:00:00 2001 From: Gerrod Ubben Date: Thu, 5 Mar 2026 15:57:31 -0500 Subject: [PATCH] Fix ALLOWED_CONTENT_CHECKSUMS check failing on settings import Moved the check to separate Django check ran after database commands. Loosen the restrictions on Forbidden Checksums being present to just a warning. fixes: #7380 Generated by: claude-opus-4.6 (cherry picked from commit 1e4afec5de06b4b7667107d6b6ec4c96c3e01e43) --- CHANGES/7380.bugfix | 1 + pulpcore/app/checks.py | 63 ++++++++++++++++++++++++++++++++++++++- pulpcore/app/settings.py | 64 ---------------------------------------- 3 files changed, 63 insertions(+), 65 deletions(-) create mode 100644 CHANGES/7380.bugfix diff --git a/CHANGES/7380.bugfix b/CHANGES/7380.bugfix new file mode 100644 index 00000000000..2e923abd0c5 --- /dev/null +++ b/CHANGES/7380.bugfix @@ -0,0 +1 @@ +Moved artifact checksum validation from module-level settings code to a Django system check. diff --git a/pulpcore/app/checks.py b/pulpcore/app/checks.py index ec7c405ef80..c6e7214f00c 100644 --- a/pulpcore/app/checks.py +++ b/pulpcore/app/checks.py @@ -1,7 +1,16 @@ from pathlib import Path from django.conf import settings -from django.core.checks import Error as CheckError, Warning as CheckWarning, register +from django.core.checks import ( + Debug as CheckDebug, + Error as CheckError, + Warning as CheckWarning, + Tags, + register, +) +from django.db.models import Q + +from pulpcore import constants @register(deploy=True) @@ -56,3 +65,55 @@ def storage_paths(app_configs, **kwargs): ) return warnings + + +@register(Tags.database) +def check_artifact_checksums(app_configs, **kwargs): + from pulpcore.app.models import Artifact, RemoteArtifact + + messages = [] + allowed = set(settings.ALLOWED_CONTENT_CHECKSUMS) + forbidden = set(constants.ALL_KNOWN_CONTENT_CHECKSUMS).difference(allowed) + + try: + for checksum in allowed: + if Artifact.objects.filter(**{checksum: None}).exists(): + messages.append( + CheckError( + f"There have been identified artifacts missing checksum '{checksum}'. " + "Run 'pulpcore-manager handle-artifact-checksums' first to populate " + "missing artifact checksums.", + id="pulpcore.E002", + ) + ) + for checksum in forbidden: + if Artifact.objects.exclude(**{checksum: None}).exists(): + messages.append( + CheckWarning( + f"There have been identified artifacts with forbidden checksum " + f"'{checksum}'. Run 'pulpcore-manager handle-artifact-checksums' " + "to unset forbidden checksums.", + id="pulpcore.W004", + ) + ) + + has_any_checksum = ~Q(**{c: None for c in constants.ALL_KNOWN_CONTENT_CHECKSUMS}) + missing_allowed = Q(**{c: None for c in allowed}) + if RemoteArtifact.objects.filter(has_any_checksum & missing_allowed).exists(): + messages.append( + CheckWarning( + "Detected remote content without allowed checksums. " + "Run 'pulpcore-manager handle-artifact-checksums --report' to " + "view this content.", + id="pulpcore.W005", + ) + ) + except Exception: + messages.append( + CheckDebug( + "Skipping artifact checksum checks (table may not exist yet).", + id="pulpcore.D001", + ) + ) + + return messages diff --git a/pulpcore/app/settings.py b/pulpcore/app/settings.py index d385b90c7a0..25ef88b14f6 100644 --- a/pulpcore/app/settings.py +++ b/pulpcore/app/settings.py @@ -19,7 +19,6 @@ from django.conf import global_settings from django.core.files.storage import storages # noqa: F401 from django.core.exceptions import ImproperlyConfigured -from django.db import connection from pulpcore import constants @@ -476,69 +475,6 @@ ALLOWED_CONTENT_CHECKSUMS ) -_SKIPPED_COMMANDS_FOR_CONTENT_CHECKS = [ - "handle-artifact-checksums", - "migrate", - "collectstatic", - "openapi", -] - -if not (len(sys.argv) >= 2 and sys.argv[1] in _SKIPPED_COMMANDS_FOR_CONTENT_CHECKS): - try: - with connection.cursor() as cursor: - for checksum in ALLOWED_CONTENT_CHECKSUMS: - # can't import Artifact here so use a direct db connection - cursor.execute(f"SELECT count(pulp_id) FROM core_artifact WHERE {checksum} IS NULL") - row = cursor.fetchone() - if row[0] > 0: - raise ImproperlyConfigured( - ( - "There have been identified artifacts missing checksum '{}'. " - "Run 'pulpcore-manager handle-artifact-checksums' first to populate " - "missing artifact checksums." - ).format(checksum) - ) - for checksum in FORBIDDEN_CHECKSUMS: - # can't import Artifact here so use a direct db connection - cursor.execute( - f"SELECT count(pulp_id) FROM core_artifact WHERE {checksum} IS NOT NULL" - ) - row = cursor.fetchone() - if row[0] > 0: - raise ImproperlyConfigured( - ( - "There have been identified artifacts with forbidden checksum '{}'. " - "Run 'pulpcore-manager handle-artifact-checksums' first to unset " - "forbidden checksums." - ).format(checksum) - ) - - # warn if there are remote artifacts with checksums but no allowed checksums - cond = " AND ".join([f"{c} IS NULL" for c in constants.ALL_KNOWN_CONTENT_CHECKSUMS]) - no_checksum_query = f"SELECT pulp_id FROM core_remoteartifact WHERE {cond}" - cond = " AND ".join([f"{c} IS NULL" for c in ALLOWED_CONTENT_CHECKSUMS]) - cursor.execute( - f"SELECT count(pulp_id) FROM core_remoteartifact WHERE {cond} AND " - f"pulp_id NOT IN ({no_checksum_query})" - ) - row = cursor.fetchone() - if row[0] > 0: - _logger.warning( - ( - "Warning: detected remote content without allowed checksums. " - "Run 'pulpcore-manager handle-artifact-checksums --report' to " - "view this content." - ) - ) - - except ImproperlyConfigured as e: - raise e - except Exception: - # our check could fail if the table hasn't been created yet or we can't get a db connection - pass - finally: - connection.close() - # Ensures the cached property storage.backends uses the right value after dynaconf init storages._backends = settings.STORAGES.copy() storages.backends