From bbd74eabd1719541a638c3dcfddc4bba336c0850 Mon Sep 17 00:00:00 2001 From: Antoine Legrand Date: Thu, 23 Mar 2017 22:50:07 +0100 Subject: [PATCH] Allow force push for app --- data/interfaces/appr.py | 2 +- data/oci_model/release.py | 101 ++++++++++++++++---------------- endpoints/appr/registry.py | 1 - endpoints/appr/test/test_api.py | 4 -- 4 files changed, 53 insertions(+), 55 deletions(-) diff --git a/data/interfaces/appr.py b/data/interfaces/appr.py index 04ebf1bdc..5d18316ff 100644 --- a/data/interfaces/appr.py +++ b/data/interfaces/appr.py @@ -350,7 +350,7 @@ class OCIAppModel(AppRegistryDataInterface): repo_kind='application') tag_name = package.release oci_model.release.create_app_release(repo, tag_name, package.manifest(), - data['content']['digest']) + data['content']['digest'], force) def delete_release(self, package_name, release, media_type): """ Remove/Delete an app-release from an app-repository. diff --git a/data/oci_model/release.py b/data/oci_model/release.py index a343608d5..2251be6a9 100644 --- a/data/oci_model/release.py +++ b/data/oci_model/release.py @@ -32,55 +32,6 @@ def get_app_release(repo, tag_name, media_type): return (tag, manifest, blob) -def create_app_release(repo, tag_name, manifest, digest): - """ Create a new application release, it includes creating a new Tag, ManifestList, - ManifestListManifests, Manifest, ManifestBlob. - - To deduplicate the ManifestList, the manifestlist_json is kept ordered by the manifest.id. - To find the insert point in the ManifestList it uses bisect on the manifest-ids list. - """ - with db_transaction(): - # Create/get the package manifest - manifest = manifest_model.get_or_create_manifest(manifest, manifest['mediaType']) - # get the tag - tag = tag_model.get_or_initialize_tag(repo, tag_name) - - if tag.manifest_list is None: - tag.manifest_list = ManifestList(media_type=ManifestList.media_type.get_id(LIST_MEDIA_TYPE), - schema_version=SCHEMA_VERSION, - manifest_list_json=[]) - - elif tag_model.tag_media_type_exists(tag, manifest.media_type): - raise PackageAlreadyExists("package exists already") - - list_json = tag.manifest_list.manifest_list_json - mlm_query = (ManifestListManifest - .select() - .where(ManifestListManifest.manifest_list == tag.manifest_list)) - list_manifest_ids = sorted([mlm.manifest_id for mlm in mlm_query]) - insert_point = bisect.bisect_left(list_manifest_ids, manifest.id) - list_json.insert(insert_point, manifest.manifest_json) - list_manifest_ids.insert(insert_point, manifest.id) - manifestlist = manifest_list_model.get_or_create_manifest_list(list_json, LIST_MEDIA_TYPE, - SCHEMA_VERSION) - manifest_list_model.create_manifestlistmanifest(manifestlist, list_manifest_ids, list_json) - - tag = tag_model.create_or_update_tag(repo, tag_name, manifest_list=manifestlist, - tag_kind="release") - blob_digest = digest - - try: - (ManifestBlob - .select() - .join(Blob) - .where(ManifestBlob.manifest == manifest, - Blob.digest == _ensure_sha256_header(blob_digest)).get()) - except ManifestBlob.DoesNotExist: - blob = blob_model.get_blob(blob_digest) - ManifestBlob.create(manifest=manifest, blob=blob) - return tag - - def delete_app_release(repo, tag_name, media_type): """ Delete a Tag/media-type couple """ media_type_id = ManifestListManifest.media_type.get_id(manifest_media_type(media_type)) @@ -114,6 +65,58 @@ def delete_app_release(repo, tag_name, media_type): return tag +def create_app_release(repo, tag_name, manifest, digest, force=False): + """ Create a new application release, it includes creating a new Tag, ManifestList, + ManifestListManifests, Manifest, ManifestBlob. + + To deduplicate the ManifestList, the manifestlist_json is kept ordered by the manifest.id. + To find the insert point in the ManifestList it uses bisect on the manifest-ids list. + """ + with db_transaction(): + # Create/get the package manifest + manifest = manifest_model.get_or_create_manifest(manifest, manifest['mediaType']) + # get the tag + tag = tag_model.get_or_initialize_tag(repo, tag_name) + + if tag.manifest_list is None: + tag.manifest_list = ManifestList(media_type=ManifestList.media_type.get_id(LIST_MEDIA_TYPE), + schema_version=SCHEMA_VERSION, + manifest_list_json=[]) + + elif tag_model.tag_media_type_exists(tag, manifest.media_type): + if force: + delete_app_release(repo, tag_name, manifest.media_type.name) + else: + raise PackageAlreadyExists("package exists already") + + list_json = tag.manifest_list.manifest_list_json + mlm_query = (ManifestListManifest + .select() + .where(ManifestListManifest.manifest_list == tag.manifest_list)) + list_manifest_ids = sorted([mlm.manifest_id for mlm in mlm_query]) + insert_point = bisect.bisect_left(list_manifest_ids, manifest.id) + list_json.insert(insert_point, manifest.manifest_json) + list_manifest_ids.insert(insert_point, manifest.id) + manifestlist = manifest_list_model.get_or_create_manifest_list(list_json, LIST_MEDIA_TYPE, + SCHEMA_VERSION) + manifest_list_model.create_manifestlistmanifest(manifestlist, list_manifest_ids, list_json) + + tag = tag_model.create_or_update_tag(repo, tag_name, manifest_list=manifestlist, + tag_kind="release") + blob_digest = digest + + try: + (ManifestBlob + .select() + .join(Blob) + .where(ManifestBlob.manifest == manifest, + Blob.digest == _ensure_sha256_header(blob_digest)).get()) + except ManifestBlob.DoesNotExist: + blob = blob_model.get_blob(blob_digest) + ManifestBlob.create(manifest=manifest, blob=blob) + return tag + + def get_releases(repo, media_type=None): """ Returns an array of Tag.name for a repo, can filter by media_type. """ release_query = (Tag diff --git a/endpoints/appr/registry.py b/endpoints/appr/registry.py index e0f41af51..e8bc0deff 100644 --- a/endpoints/appr/registry.py +++ b/endpoints/appr/registry.py @@ -196,7 +196,6 @@ def push(namespace, package_name): {"package": reponame, "scopes": ['create']}) Package.create_repository(reponame, private, owner) - if not ModifyRepositoryPermission(namespace, package_name).can(): raise UnauthorizedAccess("Unauthorized access for: %s" % reponame, {"package": reponame, "scopes": ['push']}) diff --git a/endpoints/appr/test/test_api.py b/endpoints/appr/test/test_api.py index 74311d09f..9eda9fc67 100644 --- a/endpoints/appr/test/test_api.py +++ b/endpoints/appr/test/test_api.py @@ -186,10 +186,6 @@ class TestQuayModels(CnrTestModels): def load_db(self, appconfig): return appconfig - @pytest.mark.xfail - def test_save_package_exists_force(self, newdb, package_b64blob): - CnrTestModels.test_save_package_exists_force(self, newdb, package_b64blob) - @pytest.mark.xfail def test_channel_delete_releases(self, db_with_data1): """ Can't remove a release from the channel, only delete the channel entirely """