Add dry-run option
This will help us validate and debug the prune command. Change-Id: I54ba30e1963593762e1e1435bc7e67e7eb637d3e
This commit is contained in:
parent
404b903c77
commit
66bf00a416
@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Red Hat, Inc.
|
# Copyright 2019 Red Hat, Inc.
|
||||||
# Copyright 2021 Acme Gating, LLC
|
# Copyright 2021, 2024 Acme Gating, LLC
|
||||||
#
|
#
|
||||||
# This module is free software: you can redistribute it and/or modify
|
# This module is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -553,8 +553,8 @@ class RegistryServer:
|
|||||||
# same host/port settings.
|
# same host/port settings.
|
||||||
cherrypy.server.httpserver = None
|
cherrypy.server.httpserver = None
|
||||||
|
|
||||||
def prune(self):
|
def prune(self, dry_run):
|
||||||
self.store.prune()
|
self.store.prune(dry_run)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -566,6 +566,9 @@ def main():
|
|||||||
parser.add_argument('-d', dest='debug',
|
parser.add_argument('-d', dest='debug',
|
||||||
help='Debug log level',
|
help='Debug log level',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
parser.add_argument('--dry-run', dest='dry_run',
|
||||||
|
help='Do not actually delete anything when pruning',
|
||||||
|
action='store_true')
|
||||||
parser.add_argument('command',
|
parser.add_argument('command',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
help='Command: serve, prune',
|
help='Command: serve, prune',
|
||||||
@ -591,7 +594,7 @@ def main():
|
|||||||
s.start()
|
s.start()
|
||||||
cherrypy.engine.block()
|
cherrypy.engine.block()
|
||||||
elif args.command == 'prune':
|
elif args.command == 'prune':
|
||||||
s.prune()
|
s.prune(args.dry_run)
|
||||||
else:
|
else:
|
||||||
print("Unknown command: %s", args.command)
|
print("Unknown command: %s", args.command)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -258,7 +258,7 @@ class Storage:
|
|||||||
path = os.path.join(namespace, 'repos', repo, 'manifests')
|
path = os.path.join(namespace, 'repos', repo, 'manifests')
|
||||||
return self.backend.list_objects(path)
|
return self.backend.list_objects(path)
|
||||||
|
|
||||||
def prune(self):
|
def prune(self, dry_run):
|
||||||
"""Prune the registry
|
"""Prune the registry
|
||||||
|
|
||||||
Prune all namespaces in the registry according to configured
|
Prune all namespaces in the registry according to configured
|
||||||
@ -273,13 +273,14 @@ class Storage:
|
|||||||
for namespace in self.backend.list_objects(''):
|
for namespace in self.backend.list_objects(''):
|
||||||
uploadpath = os.path.join(namespace.path, 'uploads/')
|
uploadpath = os.path.join(namespace.path, 'uploads/')
|
||||||
for upload in self.backend.list_objects(uploadpath):
|
for upload in self.backend.list_objects(uploadpath):
|
||||||
self._prune(upload, upload_target)
|
self._prune(upload, upload_target, dry_run)
|
||||||
if not manifest_target:
|
if not manifest_target:
|
||||||
continue
|
continue
|
||||||
repopath = os.path.join(namespace.path, 'repos/')
|
repopath = os.path.join(namespace.path, 'repos/')
|
||||||
kept_manifests = []
|
kept_manifests = []
|
||||||
for repo in self.backend.list_objects(repopath):
|
for repo in self.backend.list_objects(repopath):
|
||||||
kept_manifests.extend(self._prune(repo, manifest_target))
|
kept_manifests.extend(
|
||||||
|
self._prune(repo, manifest_target, dry_run))
|
||||||
# mark/sweep manifest blobs
|
# mark/sweep manifest blobs
|
||||||
layers = set()
|
layers = set()
|
||||||
for manifest in kept_manifests:
|
for manifest in kept_manifests:
|
||||||
@ -290,7 +291,7 @@ class Storage:
|
|||||||
blobpath = os.path.join(namespace.path, 'blobs/')
|
blobpath = os.path.join(namespace.path, 'blobs/')
|
||||||
for blob in self.backend.list_objects(blobpath):
|
for blob in self.backend.list_objects(blobpath):
|
||||||
if blob.name not in layers:
|
if blob.name not in layers:
|
||||||
self._prune(blob, upload_target)
|
self._prune(blob, upload_target, dry_run)
|
||||||
|
|
||||||
def _get_layers_from_manifest(self, namespace, path):
|
def _get_layers_from_manifest(self, namespace, path):
|
||||||
self.log.debug('Get layers %s', path)
|
self.log.debug('Get layers %s', path)
|
||||||
@ -310,14 +311,15 @@ class Storage:
|
|||||||
layers.append(layer['digest'])
|
layers.append(layer['digest'])
|
||||||
return layers
|
return layers
|
||||||
|
|
||||||
def _prune(self, root_obj, target):
|
def _prune(self, root_obj, target, dry_run):
|
||||||
kept = []
|
kept = []
|
||||||
if root_obj.isdir:
|
if root_obj.isdir:
|
||||||
for obj in self.backend.list_objects(root_obj.path):
|
for obj in self.backend.list_objects(root_obj.path):
|
||||||
kept.extend(self._prune(obj, target))
|
kept.extend(self._prune(obj, target, dry_run))
|
||||||
if not kept and root_obj.ctime < target:
|
if not kept and root_obj.ctime < target:
|
||||||
self.log.debug('Prune %s', root_obj.path)
|
self.log.debug('Prune %s', root_obj.path)
|
||||||
self.backend.delete_object(root_obj.path)
|
if not dry_run:
|
||||||
|
self.backend.delete_object(root_obj.path)
|
||||||
else:
|
else:
|
||||||
self.log.debug('Keep %s', root_obj.path)
|
self.log.debug('Keep %s', root_obj.path)
|
||||||
kept.append(root_obj)
|
kept.append(root_obj)
|
||||||
|
Loading…
Reference in New Issue
Block a user