Skip to content

Commit cc6d300

Browse files
committed
Add migration to fix alpine PURLs
Signed-off-by: Keshav Priyadarshi <git@keshav.space>
1 parent 8fe43f7 commit cc6d300

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from datetime import datetime
2+
from datetime import timezone
3+
4+
from aboutcode.pipeline import LoopProgress
5+
from django.db import migrations
6+
from packageurl import PackageURL
7+
8+
CHUNK_SIZE = 50000
9+
BATCH_SIZE = 500
10+
11+
12+
class Migration(migrations.Migration):
13+
def fix_alpine_purl_type(apps, schema_editor):
14+
"""Use proper apk package type for Alpine"""
15+
16+
Package = apps.get_model("vulnerabilities", "Package")
17+
batch = []
18+
alpine_packages_query = Package.objects.filter(type="alpine")
19+
20+
log(f"\nFixing PURL for {alpine_packages_query.count():,d} alpine packages")
21+
progress = LoopProgress(
22+
total_iterations=alpine_packages_query.count(),
23+
progress_step=10,
24+
logger=log,
25+
)
26+
for package in progress.iter(alpine_packages_query.iterator(chunk_size=CHUNK_SIZE)):
27+
package.type = "apk"
28+
package.namespace = "alpine"
29+
30+
package.package_url = update_alpine_purl(package.package_url, "apk", "alpine")
31+
package.plain_package_url = update_alpine_purl(
32+
package.plain_package_url, "apk", "alpine"
33+
)
34+
35+
batch.append(package)
36+
if len(batch) >= BATCH_SIZE:
37+
bulk_update_package(Package, batch)
38+
batch.clear()
39+
40+
bulk_update_package(Package, batch)
41+
42+
def reverse_fix_alpine_purl_type(apps, schema_editor):
43+
Package = apps.get_model("vulnerabilities", "Package")
44+
batch = []
45+
alpine_packages_query = Package.objects.filter(type="apk", namespace="alpine")
46+
47+
log(f"\nREVERSE: Fix for {alpine_packages_query.count():,d} alpine packages")
48+
progress = LoopProgress(
49+
total_iterations=alpine_packages_query.count(),
50+
progress_step=10,
51+
logger=log,
52+
)
53+
for package in progress.iter(alpine_packages_query.iterator(chunk_size=CHUNK_SIZE)):
54+
package.type = "alpine"
55+
package.namespace = ""
56+
57+
package.package_url = update_alpine_purl(package.package_url, "alpine", "")
58+
package.plain_package_url = update_alpine_purl(package.plain_package_url, "alpine", "")
59+
60+
batch.append(package)
61+
if len(batch) >= BATCH_SIZE:
62+
bulk_update_package(Package, batch)
63+
batch.clear()
64+
65+
bulk_update_package(Package, batch)
66+
67+
dependencies = [
68+
("vulnerabilities", "0087_update_alpine_advisory_created_by"),
69+
]
70+
71+
operations = [
72+
migrations.RunPython(
73+
code=fix_alpine_purl_type,
74+
reverse_code=reverse_fix_alpine_purl_type,
75+
),
76+
]
77+
78+
79+
def bulk_update_package(package, batch):
80+
if batch:
81+
package.objects.bulk_update(
82+
objs=batch,
83+
fields=[
84+
"type",
85+
"namespace",
86+
"package_url",
87+
"plain_package_url",
88+
],
89+
)
90+
91+
92+
def update_alpine_purl(purl, purl_type, purl_namespace):
93+
package_url = PackageURL.from_string(purl).to_dict()
94+
package_url["type"] = purl_type
95+
package_url["namespace"] = purl_namespace
96+
return str(PackageURL(**package_url))
97+
98+
99+
def log(message):
100+
now_local = datetime.now(timezone.utc).astimezone()
101+
timestamp = now_local.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
102+
message = f"{timestamp} {message}"
103+
print(message)

0 commit comments

Comments
 (0)