Fix app update logic determining layers to retain

This commit is contained in:
Disassembler 2020-04-16 18:29:05 +02:00
parent 2047753096
commit 3f70400ced
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499

View File

@ -200,8 +200,10 @@ def install_app(app_name, queue):
for container in new_containers: for container in new_containers:
required_images.extend(repo_online.get_image(container['image'])['layers']) required_images.extend(repo_online.get_image(container['image'])['layers'])
local_images = repo_local.get_images() local_images = repo_local.get_images()
# Layers need to be downloaded in correct order # Create (deduplicate) set of layers while retaining the correct order
for layer in list(dict.fromkeys(required_images)): required_images = list(dict.fromkeys(required_images))
# Download layers in correct order
for layer in required_images:
if layer not in local_images: if layer not in local_images:
queue.download_image(Image(layer, False)) queue.download_image(Image(layer, False))
queue.install_app(App(app_name, False, False)) queue.install_app(App(app_name, False, False))
@ -212,8 +214,11 @@ def uninstall_app(app_name, queue):
queue.uninstall_app(app) queue.uninstall_app(app)
# Remove unused layers # Remove unused layers
removed_containers = [container.name for container in app.containers] removed_containers = [container.name for container in app.containers]
retained_containers = [definition for name,definition in repo_local.get_containers().items() if name not in removed_containers] retained_layers = set()
remove_unused_layers(retained_containers, queue) for name,definition in repo_local.get_containers().items():
if name not in removed_containers:
retained_layers.update(definition['layers'])
remove_unused_layers(retained_layers, queue)
def update_app(app_name, queue): def update_app(app_name, queue):
# Enqueue layers and application download, registration and update script execution # Enqueue layers and application download, registration and update script execution
@ -222,27 +227,29 @@ def update_app(app_name, queue):
for container in new_containers: for container in new_containers:
required_images.extend(repo_online.get_image(container['image'])['layers']) required_images.extend(repo_online.get_image(container['image'])['layers'])
local_images = repo_local.get_images() local_images = repo_local.get_images()
# Layers need to be downloaded in correct order # Create (deduplicate) set of layers while retaining the correct order
for layer in list(dict.fromkeys(required_images)): required_images = list(dict.fromkeys(required_images))
# Download layers in correct order
for layer in required_images:
if layer not in local_images: if layer not in local_images:
queue.download_image(Image(layer, False)) queue.download_image(Image(layer, False))
app = App(app_name, False) app = App(app_name, False)
queue.update_app(app) queue.update_app(app)
# Remove unused layers # Remove unused layers
removed_containers = [container.name for container in app.containers] removed_containers = [container.name for container in app.containers]
retained_containers = [definition for name,definition in repo_local.get_containers().items() if name not in removed_containers] + new_containers retained_layers = set(required_images)
remove_unused_layers(retained_containers, queue) for name,definition in repo_local.get_containers().items():
if name not in removed_containers:
retained_layers.update(definition['layers'])
remove_unused_layers(retained_layers, queue)
def remove_unused_layers(retained_containers, queue): def remove_unused_layers(retained_layers, queue):
# Enqueue removal of images which won't be used in any locally defined containers anymore # Enqueue removal of images which won't be used in any locally defined containers anymore
used_images = set()
for definition in retained_containers:
used_images.update(definition['layers'])
# Build dependency tree to safely remove the images in order of dependency
depsolver = DepSolver() depsolver = DepSolver()
for image in set(repo_local.get_images()) - used_images: # Build dependency tree to safely remove the images in order of dependency
for image in set(repo_local.get_images()) - retained_layers:
image = Image(image) image = Image(image)
depsolver.add(image.name, set(image.layers) - used_images, image) depsolver.add(image.name, set(image.layers) - retained_layers, image)
# Enqueue the removal actions # Enqueue the removal actions
for image in reversed(depsolver.solve()): for image in reversed(depsolver.solve()):
queue.delete_image(image) queue.delete_image(image)