Skip to content

Commit

Permalink
Fix a regression in migration 0056
Browse files Browse the repository at this point in the history
Having more than one collection version in the system prevents the
migration 0056 to run, because null as a value is not allowed to appear
more than once.

We need to clean this up very careful, becuase on some systems the
migration may have applied cleanly.

fixes pulp#2040
  • Loading branch information
mdellweg committed Nov 22, 2024
1 parent 94f9386 commit 262e6e1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGES/240.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a regression with migration 0056 failing on multiple null values on a unique constraint.
4 changes: 0 additions & 4 deletions pulp_ansible/app/migrations/0056_collectionversion_sha256.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,4 @@ class Migration(migrations.Migration):
field=models.CharField(default='', max_length=64, null=True),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name="collectionversion",
unique_together={("sha256",), ("namespace", "name", "version")},
),
]
30 changes: 30 additions & 0 deletions pulp_ansible/app/migrations/0058_fix_0056_regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 4.2.16 on 2024-11-22 12:06

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("ansible", "0057_collectionversion_sha256_migrate"),
]

operations = [
# ---------------------------------------------------------------------
# In the current timeline of migrations, this step seems superfluous.
# But in version 0.23.0 we shipped a bad version of 0056.
# This repairs it.
migrations.AlterUniqueTogether(
name="collectionversion",
unique_together={("namespace", "name", "version")},
),
# ---------------------------------------------------------------------
migrations.AddConstraint(
model_name="collectionversion",
constraint=models.UniqueConstraint(
condition=models.Q(("sha256__isnull", False)),
fields=("sha256",),
name="unique_sha256",
),
),
]
9 changes: 7 additions & 2 deletions pulp_ansible/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,18 @@ def __str__(self):

class Meta:
default_related_name = "%(app_label)s_%(model_name)s"
unique_together = (("namespace", "name", "version"), ("sha256",))
unique_together = (("namespace", "name", "version"),)
constraints = [
UniqueConstraint(
fields=("sha256",),
name="unique_sha256",
condition=Q(sha256__isnull=False),
),
UniqueConstraint(
fields=("collection", "is_highest"),
name="unique_is_highest",
condition=Q(is_highest=True),
)
),
]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,49 @@ def test_collection_version_sha256_migrate(migrate):
Collection = apps.get_model("ansible", "Collection")
CollectionVersion = apps.get_model("ansible", "CollectionVersion")

artifact = Artifact.objects.create(
size=8, sha256="SENTINEL", file=SimpleUploadedFile("foo", b"deadbeef")
collection = Collection.objects.create(namespace="snap", name="crackle")

# Create two collection versions, because `sha256=null` can violate the uniquenes constraint.
artifact1 = Artifact.objects.create(
size=8, sha256="SENTINEL1", file=SimpleUploadedFile("foo", b"deadbeef")
)
collection = Collection.objects.create(
cv1 = CollectionVersion.objects.create(
pulp_type="collection_version",
collection=collection,
namespace="snap",
name="crackle",
version="1.0.0",
version_minor="1",
version_major="0",
version_patch="0",
)
cv = CollectionVersion.objects.create(
cv1.contentartifact_set.create(artifact=artifact1)

artifact2 = Artifact.objects.create(
size=8, sha256="SENTINEL2", file=SimpleUploadedFile("foo", b"beefdead")
)
cv2 = CollectionVersion.objects.create(
pulp_type="collection_version",
collection=collection,
namespace="snap",
name="crackle",
version="pop",
version_minor="1",
version_major="2",
version_patch="3",
version="2.0.0",
version_minor="2",
version_major="0",
version_patch="0",
)
cv.contentartifact_set.create(artifact=artifact)
cv2.contentartifact_set.create(artifact=artifact2)

apps = migrate([("ansible", "0056_collectionversion_sha256")])
CollectionVersion = apps.get_model("ansible", "CollectionVersion")

cv = CollectionVersion.objects.get(pk=cv.pk)
assert cv.sha256 == ""
cv1 = CollectionVersion.objects.get(pk=cv1.pk)
assert cv1.sha256 == ""

apps = migrate([("ansible", "0057_collectionversion_sha256_migrate")])
CollectionVersion = apps.get_model("ansible", "CollectionVersion")

cv = CollectionVersion.objects.get(pk=cv.pk)
assert cv.sha256 == "SENTINEL"
cv1 = CollectionVersion.objects.get(pk=cv1.pk)
assert cv1.sha256 == "SENTINEL1"

apps = migrate([("ansible", "0058_fix_0056_regression")])

0 comments on commit 262e6e1

Please sign in to comment.