diff --git a/data/database.py b/data/database.py index f2c300933..5a262febe 100644 --- a/data/database.py +++ b/data/database.py @@ -1189,6 +1189,7 @@ class UserRegion(BaseModel): indexes = ((("user", "location"), True),) +@deprecated_model class Image(BaseModel): # This class is intentionally denormalized. Even though images are supposed # to be globally unique we can't treat them as such for permissions and @@ -1939,6 +1940,7 @@ class ManifestBlob(BaseModel): indexes = ((("manifest", "blob"), True),) +@deprecated_model class ManifestLegacyImage(BaseModel): """ For V1-compatible manifests only, this table maps from the manifest to its associated Docker diff --git a/data/migrations/versions/a0fc06d604a4_unlink_deprecated_tables.py b/data/migrations/versions/a0fc06d604a4_unlink_deprecated_tables.py new file mode 100644 index 000000000..06e02790f --- /dev/null +++ b/data/migrations/versions/a0fc06d604a4_unlink_deprecated_tables.py @@ -0,0 +1,337 @@ +"""Unlink deprecated tables + +Revision ID: a0fc06d604a4 +Revises: d94d328733e4 +Create Date: 2022-05-27 11:02:09.738779 + +""" + +# revision identifiers, used by Alembic. +revision = "a0fc06d604a4" +down_revision = "46980ea2dde5" + +import sqlalchemy as sa + + +def upgrade(op, tables, tester): + # DerivedStorageForImage + op.drop_constraint( + op.f("fk_derivedstorageforimage_derivative_id_imagestorage"), + "derivedstorageforimage", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_derivedstorageforimage_source_image_id_image"), + "derivedstorageforimage", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_derivedstorageforimage_transformation_constraint"), + "derivedstorageforimage", + type_="foreignkey", + ) + + # RepositoryTag + op.drop_constraint( + op.f("fk_repositorytag_image_id_image"), + "repositorytag", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_repositorytag_repository_id_repository"), + "repositorytag", + type_="foreignkey", + ) + + # TorrentInfo + op.drop_constraint( + op.f("fk_torrentinfo_storage_id_imagestorage"), + "torrentinfo", + type_="foreignkey", + ) + + # TagManifest + op.drop_constraint( + op.f("fk_tagmanifest_tag_id_repositorytag"), + "tagmanifest", + type_="foreignkey", + ) + + # TagManifestToManifest + op.drop_constraint( + op.f("fk_tagmanifesttomanifest_manifest_id_manifest"), + "tagmanifesttomanifest", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifesttomanifest_tag_manifest_id_tagmanifest"), + "tagmanifesttomanifest", + type_="foreignkey", + ) + + # TagManifestLabel + op.drop_constraint( + op.f("fk_tagmanifestlabel_annotated_id_tagmanifest"), + "tagmanifestlabel", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabel_label_id_label"), + "tagmanifestlabel", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabel_repository_id_repository"), + "tagmanifestlabel", + type_="foreignkey", + ) + + # TagManifestLabelMap + op.drop_constraint( + op.f("fk_tagmanifestlabelmap_label_id_label"), + "tagmanifestlabelmap", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabelmap_manifest_id_manifest"), + "tagmanifestlabelmap", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabelmap_manifest_label_id_manifestlabel"), + "tagmanifestlabelmap", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabelmap_tag_manifest_id_tagmanifest"), + "tagmanifestlabelmap", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagmanifestlabelmap_tag_manifest_label_id_tagmanifestlabel"), + "tagmanifestlabelmap", + type_="foreignkey", + ) + + # TagToRepositoryTag + op.drop_constraint( + op.f("fk_tagtorepositorytag_repository_id_repository"), + "tagtorepositorytag", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagtorepositorytag_repository_tag_id_repositorytag"), + "tagtorepositorytag", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_tagtorepositorytag_tag_id_tag"), "tagtorepositorytag", type_="foreignkey" + ) + + # Image + op.drop_constraint(op.f("fk_image_repository_id_repository"), "image", type_="foreignkey") + op.drop_constraint(op.f("fk_image_storage_id_imagestorage"), "image", type_="foreignkey") + + # ManifestLegacyImage + op.drop_constraint( + op.f("fk_manifestlegacyimage_image_id_image"), "manifestlegacyimage", type_="foreignkey" + ) + op.drop_constraint( + op.f("fk_manifestlegacyimage_manifest_id_manifest"), + "manifestlegacyimage", + type_="foreignkey", + ) + op.drop_constraint( + op.f("fk_manifestlegacyimage_repository_id_repository"), + "manifestlegacyimage", + type_="foreignkey", + ) + + +def downgrade(op, tables, tester): + # DerivedStorageForImage + op.create_foreign_key( + op.f("fk_derivedstorageforimage_derivative_id_imagestorage"), + "derivedstorageforimage", + "imagestorage", + ["derivative_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_derivedstorageforimage_source_image_id_image"), + "derivedstorageforimage", + "image", + ["source_image_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_derivedstorageforimage_transformation_constraint"), + "derivedstorageforimage", + "imagestoragetransformation", + ["transformation_id"], + ["id"], + ) + + # RepositoryTag + op.create_foreign_key( + op.f("fk_repositorytag_image_id_image"), + "repositorytag", + "image", + ["image_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_repositorytag_repository_id_repository"), + "repositorytag", + "repository", + ["repository_id"], + ["id"], + ) + + # TorrentInfo + op.create_foreign_key( + op.f("fk_torrentinfo_storage_id_imagestorage"), + "torrentinfo", + "imagestorage", + ["storage_id"], + ["id"], + ) + + # TagManifest + op.create_foreign_key( + op.f("fk_tagmanifest_tag_id_repositorytag"), + "tagmanifest", + "repositorytag", + ["tag_id"], + ["id"], + ) + + # TagManifestToManifest + op.create_foreign_key( + op.f("fk_tagmanifesttomanifest_manifest_id_manifest"), + "tagmanifesttomanifest", + "manifest", + ["manifest_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifesttomanifest_tag_manifest_id_tagmanifest"), + "tagmanifesttomanifest", + "tagmanifest", + ["tag_manifest_id"], + ["id"], + ) + + # TagManifestLabel + op.create_foreign_key( + op.f("fk_tagmanifestlabel_annotated_id_tagmanifest"), + "tagmanifestlabel", + "tagmanifest", + ["annotated_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabel_label_id_label"), + "tagmanifestlabel", + "label", + ["label_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabel_repository_id_repository"), + "tagmanifestlabel", + "repository", + ["repository_id"], + ["id"], + ) + + # TagManifestLabelMap + op.create_foreign_key( + op.f("fk_tagmanifestlabelmap_label_id_label"), + "tagmanifestlabelmap", + "label", + ["label_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabelmap_manifest_id_manifest"), + "tagmanifestlabelmap", + "manifest", + ["manifest_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabelmap_manifest_label_id_manifestlabel"), + "tagmanifestlabelmap", + "manifest_label", + ["manifest_label_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabelmap_tag_manifest_id_tagmanifest"), + "tagmanifestlabelmap", + "tagmanifest", + ["tag_manifest_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagmanifestlabelmap_tag_manifest_label_id_tagmanifestlabel"), + "tagmanifestlabelmap", + "tagmanifestlabel", + ["tag_manifest_label_id"], + ["id"], + ) + + # TagToRepositoryTag + op.create_foreign_key( + op.f("fk_tagtorepositorytag_repository_id_repository"), + "tagtorepositorytag", + "repository", + ["repository_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagtorepositorytag_repository_tag_id_repositorytag"), + "tagtorepositorytag", + "repositorytag", + ["repository_tag_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_tagtorepositorytag_tag_id_tag"), + "tagtorepositorytag", + "tag", + ["tag_id"], + ["id"], + ) + + # Image + op.create_foreign_key( + op.f("fk_image_repository_id_repository"), "image", "repository", ["repository_id"], ["id"] + ) + op.create_foreign_key( + op.f("fk_image_storage_id_imagestorage"), "image", "imagestorage", ["storage_id"], ["id"] + ) + + # ManifestLegacyImage + op.create_foreign_key( + op.f("fk_manifestlegacyimage_image_id_image"), + "manifestlegacyimage", + "image", + ["image_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_manifestlegacyimage_manifest_id_manifest"), + "manifestlegacyimage", + "manifest", + ["manifest_id"], + ["id"], + ) + op.create_foreign_key( + op.f("fk_manifestlegacyimage_repository_id_repository"), + "manifestlegacyimage", + "repository", + ["repository_id"], + ["id"], + ) diff --git a/data/model/oci/test/test_oci_manifest.py b/data/model/oci/test/test_oci_manifest.py index 5c9cf950d..890a1bc88 100644 --- a/data/model/oci/test/test_oci_manifest.py +++ b/data/model/oci/test/test_oci_manifest.py @@ -416,7 +416,6 @@ def test_get_or_create_manifest_with_remote_layers(initialized_db): assert remote_digest not in manifest.local_blob_digests assert manifest.has_remote_layer - assert not manifest.has_legacy_image assert manifest.get_schema1_manifest("foo", "bar", "baz", None) is None # Write the manifest. diff --git a/data/registry_model/registry_oci_model.py b/data/registry_model/registry_oci_model.py index 9e93dc021..ea7c8d40a 100644 --- a/data/registry_model/registry_oci_model.py +++ b/data/registry_model/registry_oci_model.py @@ -12,8 +12,6 @@ from data.model.oci.retriever import RepositoryContentRetriever from data.readreplica import ReadOnlyModeException from data.database import ( db_transaction, - Image, - IMAGE_NOT_SCANNED_ENGINE_VERSION, db_disallow_replica_use, ) from data.registry_model.interface import RegistryDataInterface @@ -551,16 +549,11 @@ class OCIModel(RegistryDataInterface): re-indexed. """ with db_disallow_replica_use(): - # TODO: change from using the Image row once we've moved all security info into MSS. manifest_id = manifest_or_legacy_image.as_manifest()._db_id - image = oci.shared.get_legacy_image_for_manifest(manifest_id) - if image is None: - return None + manifestsecuritystatus = oci.shared.get_manifestsecuritystatus_for_manifest(manifest_id) - assert image - image.security_indexed = False - image.security_indexed_engine = IMAGE_NOT_SCANNED_ENGINE_VERSION - image.save() + if manifestsecuritystatus is not None: + manifestsecuritystatus.delete_instance() def list_manifest_layers(self, manifest, storage, include_placements=False): try: diff --git a/data/secscan_model/test/test_secscan_interface.py b/data/secscan_model/test/test_secscan_interface.py index 6d217b869..f9c4cfacc 100644 --- a/data/secscan_model/test/test_secscan_interface.py +++ b/data/secscan_model/test/test_secscan_interface.py @@ -22,15 +22,13 @@ from data.secscan_model.secscan_v4_model import V4SecurityScanner @pytest.mark.parametrize( - "indexed_v2, indexed_v4, expected_status", + "indexed_v4, expected_status", [ - (False, False, ScanLookupStatus.NOT_YET_INDEXED), - (False, True, ScanLookupStatus.UNSUPPORTED_FOR_INDEXING), - # (True, False, ScanLookupStatus.FAILED_TO_INDEX), - # (True, True, ScanLookupStatus.UNSUPPORTED_FOR_INDEXING), + (False, ScanLookupStatus.NOT_YET_INDEXED), + (True, ScanLookupStatus.UNSUPPORTED_FOR_INDEXING), ], ) -def test_load_security_information(indexed_v2, indexed_v4, expected_status, initialized_db): +def test_load_security_information(indexed_v4, expected_status, initialized_db): secscan_model.configure(app, instance_keys, storage) repository_ref = registry_model.lookup_repository("devtable", "simple")