Add api function to fully delete a repository.
This commit is contained in:
parent
891f992bf2
commit
4b9c6d9aae
5 changed files with 37 additions and 22 deletions
|
@ -348,3 +348,8 @@ def delete_user_permission(username, namespace_name, repository_name):
|
||||||
raise DataModelException('User does not have permission for repo.')
|
raise DataModelException('User does not have permission for repo.')
|
||||||
|
|
||||||
fetched[0].delete_instance()
|
fetched[0].delete_instance()
|
||||||
|
|
||||||
|
def purge_repository(namespace_name, repository_name):
|
||||||
|
fetched = Repository.get(Repository.name == repository_name,
|
||||||
|
Repository.namespace == namespace_name)
|
||||||
|
fetched.delete_instance(recursive=True, delete_nullable=True)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from util.gravatar import compute_hash
|
||||||
from auth.permissions import (ReadRepositoryPermission,
|
from auth.permissions import (ReadRepositoryPermission,
|
||||||
ModifyRepositoryPermission,
|
ModifyRepositoryPermission,
|
||||||
AdministerRepositoryPermission)
|
AdministerRepositoryPermission)
|
||||||
|
from endpoints.registry import delete_registry_storage
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -138,6 +139,19 @@ def change_repo_visibility_api(namespace, repository):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/repository/<path:repository>', methods=['DELETE'])
|
||||||
|
@api_login_required
|
||||||
|
@parse_repository_name
|
||||||
|
def delete_repository(namespace, repository):
|
||||||
|
permission = AdministerRepositoryPermission(namespace, repository)
|
||||||
|
if permission.can():
|
||||||
|
model.purge_repository(namespace, repository)
|
||||||
|
delete_registry_storage(namespace, repository)
|
||||||
|
return make_response('Deleted', 204)
|
||||||
|
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
def image_view(image):
|
def image_view(image):
|
||||||
return {
|
return {
|
||||||
'id': image.image_id,
|
'id': image.image_id,
|
||||||
|
|
|
@ -302,3 +302,11 @@ def put_image_json(namespace, repository, image_id):
|
||||||
store.put_content(json_path, request.data)
|
store.put_content(json_path, request.data)
|
||||||
generate_ancestry(namespace, repository, image_id, parent_id)
|
generate_ancestry(namespace, repository, image_id, parent_id)
|
||||||
return make_response('true', 200)
|
return make_response('true', 200)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_registry_storage(namespace, repository):
|
||||||
|
""" Caller should have already verified proper permissions. """
|
||||||
|
repository_path = store.repository_namespace_path(namespace, repository)
|
||||||
|
|
||||||
|
logger.debug('Recursively deleting path: %s' % repository_path)
|
||||||
|
store.remove(repository_path)
|
|
@ -82,7 +82,7 @@ def delete_tag(namespace, repository, tag):
|
||||||
methods=['DELETE'])
|
methods=['DELETE'])
|
||||||
@process_auth
|
@process_auth
|
||||||
@parse_repository_name
|
@parse_repository_name
|
||||||
def delete_repository(namespace, repository):
|
def delete_repository_tags(namespace, repository):
|
||||||
permission = ModifyRepositoryPermission(namespace, repository)
|
permission = ModifyRepositoryPermission(namespace, repository)
|
||||||
|
|
||||||
if permission.can():
|
if permission.can():
|
||||||
|
|
|
@ -28,43 +28,31 @@ class Storage(object):
|
||||||
#FIXME(samalba): Move all path resolver in each module (out of the base)
|
#FIXME(samalba): Move all path resolver in each module (out of the base)
|
||||||
def images_list_path(self, namespace, repository):
|
def images_list_path(self, namespace, repository):
|
||||||
return '{0}/{1}/{2}/_images_list'.format(self.repositories,
|
return '{0}/{1}/{2}/_images_list'.format(self.repositories,
|
||||||
namespace,
|
namespace,
|
||||||
repository)
|
repository)
|
||||||
|
|
||||||
def image_json_path(self, namespace, repository, image_id):
|
def image_json_path(self, namespace, repository, image_id):
|
||||||
return '{0}/{1}/{2}/{3}/json'.format(self.images, namespace,
|
return '{0}/{1}/{2}/{3}/json'.format(self.images, namespace,
|
||||||
repository, image_id)
|
repository, image_id)
|
||||||
|
|
||||||
def image_mark_path(self, namespace, repository, image_id):
|
def image_mark_path(self, namespace, repository, image_id):
|
||||||
return '{0}/{1}/{2}/{3}/_inprogress'.format(self.images, namespace,
|
return '{0}/{1}/{2}/{3}/_inprogress'.format(self.images, namespace,
|
||||||
repository, image_id)
|
repository, image_id)
|
||||||
|
|
||||||
def image_checksum_path(self, namespace, repository, image_id):
|
def image_checksum_path(self, namespace, repository, image_id):
|
||||||
return '{0}/{1}/{2}/{3}/_checksum'.format(self.images, namespace,
|
return '{0}/{1}/{2}/{3}/_checksum'.format(self.images, namespace,
|
||||||
repository, image_id)
|
repository, image_id)
|
||||||
|
|
||||||
def image_layer_path(self, namespace, repository, image_id):
|
def image_layer_path(self, namespace, repository, image_id):
|
||||||
return '{0}/{1}/{2}/{3}/layer'.format(self.images, namespace,
|
return '{0}/{1}/{2}/{3}/layer'.format(self.images, namespace,
|
||||||
repository, image_id)
|
repository, image_id)
|
||||||
|
|
||||||
def image_ancestry_path(self, namespace, repository, image_id):
|
def image_ancestry_path(self, namespace, repository, image_id):
|
||||||
return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace,
|
return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace,
|
||||||
repository, image_id)
|
repository, image_id)
|
||||||
|
|
||||||
def tag_path(self, namespace, repository, tagname=None):
|
def repository_namespace_path(self, namespace, repository):
|
||||||
if not tagname:
|
return '{0}/{1}/{2}/'.format(self.images, namespace, repository)
|
||||||
return '{0}/{1}/{2}'.format(self.repositories,
|
|
||||||
namespace,
|
|
||||||
repository)
|
|
||||||
return '{0}/{1}/{2}/tag_{3}'.format(self.repositories,
|
|
||||||
namespace,
|
|
||||||
repository,
|
|
||||||
tagname)
|
|
||||||
|
|
||||||
def index_images_path(self, namespace, repository):
|
|
||||||
return '{0}/{1}/{2}/_index_images'.format(self.repositories,
|
|
||||||
namespace,
|
|
||||||
repository)
|
|
||||||
|
|
||||||
def get_content(self, path):
|
def get_content(self, path):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
Reference in a new issue