def _purge_pre_oci_tag(tag, context, allow_non_expired=False): assert tag.repository_id == context.repository.id if not allow_non_expired: assert tag.lifetime_end_ts is not None assert tag.lifetime_end_ts <= pre_oci_tag.get_epoch_timestamp() # If it exists, GC the tag manifest. try: tag_manifest = TagManifest.select().where(TagManifest.tag == tag).get() _garbage_collect_legacy_manifest(tag_manifest.id, context) except TagManifest.DoesNotExist: pass # Add the tag's legacy image to be GCed. context.add_legacy_image_id(tag.image_id) with db_transaction(): # Reload the tag and verify its lifetime_end_ts has not changed. try: reloaded_tag = db_for_update(RepositoryTag.select().where(RepositoryTag.id == tag.id)).get() except RepositoryTag.DoesNotExist: return False assert reloaded_tag.id == tag.id assert reloaded_tag.repository_id == context.repository.id if reloaded_tag.lifetime_end_ts != tag.lifetime_end_ts: return False # Delete mapping rows. TagToRepositoryTag.delete().where(TagToRepositoryTag.repository_tag == reloaded_tag).execute() # Delete the tag. reloaded_tag.delete_instance()
def get_tag_manifest_digests(tags): """ Returns a map from tag ID to its associated manifest digest, if any. """ if not tags: return dict() manifests = TagManifest.select( TagManifest.tag, TagManifest.digest).where(TagManifest.tag << [t.id for t in tags]) return {manifest.tag_id: manifest.digest for manifest in manifests}
def _load_repo_manifests(namespace, repo_name, allow_dead=False): query = (TagManifest.select( TagManifest, RepositoryTag).join(RepositoryTag).join(Image).join(Repository).join( Namespace, on=(Namespace.id == Repository.namespace_user)).where( Repository.name == repo_name, Namespace.username == namespace)) if not allow_dead: query = _tag_alive(query) return query
def _garbage_collect_legacy_manifest(legacy_manifest_id, context): assert legacy_manifest_id is not None # Add the labels to be GCed. query = TagManifestLabel.select().where( TagManifestLabel.annotated == legacy_manifest_id) for manifest_label in query: context.add_label_id(manifest_label.label_id) # Delete the tag manifest. with db_transaction(): try: tag_manifest = TagManifest.select().where( TagManifest.id == legacy_manifest_id).get() except TagManifest.DoesNotExist: return False assert tag_manifest.id == legacy_manifest_id assert tag_manifest.tag.repository_id == context.repository.id # Delete any label mapping rows. (TagManifestLabelMap.delete().where( TagManifestLabelMap.tag_manifest == legacy_manifest_id).execute()) # Delete the label rows. TagManifestLabel.delete().where( TagManifestLabel.annotated == legacy_manifest_id).execute() # Delete the mapping row if it exists. try: tmt = (TagManifestToManifest.select().where( TagManifestToManifest.tag_manifest == tag_manifest).get()) context.add_manifest_id(tmt.manifest_id) tmt_deleted = tmt.delete_instance() if tmt_deleted: gc_table_rows_deleted.labels( table="TagManifestToManifest").inc() except TagManifestToManifest.DoesNotExist: pass # Delete the tag manifest. tag_manifest_deleted = tag_manifest.delete_instance() if tag_manifest_deleted: gc_table_rows_deleted.labels(table="TagManifest").inc() return True
def restore_tag_to_manifest(repo_obj, tag_name, manifest_digest): """ Restores a tag to a specific manifest digest. """ with db_transaction(): # Verify that the manifest digest already existed under this repository under the # tag. try: tag_manifest = (TagManifest.select( TagManifest, RepositoryTag, Image).join(RepositoryTag).join(Image).where( RepositoryTag.repository == repo_obj).where( RepositoryTag.name == tag_name).where( TagManifest.digest == manifest_digest).get()) except TagManifest.DoesNotExist: raise DataModelException( "Cannot restore to unknown or invalid digest") # Lookup the existing image, if any. try: existing_image = get_repo_tag_image(repo_obj, tag_name) except DataModelException: existing_image = None docker_image_id = tag_manifest.tag.image.docker_image_id oci_manifest = None try: oci_manifest = Manifest.get(repository=repo_obj, digest=manifest_digest) except Manifest.DoesNotExist: pass # Change the tag and tag manifest to point to the updated image. updated_tag = create_or_update_tag_for_repo(repo_obj, tag_name, docker_image_id, reversion=True, oci_manifest=oci_manifest) tag_manifest.tag = updated_tag tag_manifest.save() return existing_image
def upgrade(op, tables, tester): # Backfill migration removed. if not tester.is_testing: assert TagManifest.select().count() == 0