More download/unpack CLI progress
This commit is contained in:
parent
4497e1e793
commit
67f994f190
@ -6,9 +6,10 @@ import argparse
|
|||||||
from spoc import repo_local
|
from spoc import repo_local
|
||||||
from spoc import repo_online
|
from spoc import repo_online
|
||||||
from spoc import repo_publish
|
from spoc import repo_publish
|
||||||
|
from spoc.exceptions import ImageNotFoundError
|
||||||
from spoc.image import Image
|
from spoc.image import Image
|
||||||
from spoc.imagebuilder import ImageBuilder
|
from spoc.imagebuilder import ImageBuilder
|
||||||
from spoc.cli import ActionQueue, ActionItem, readable_size
|
from spoc.cli import ActionQueue, readable_size
|
||||||
|
|
||||||
ACTION_LIST = 1
|
ACTION_LIST = 1
|
||||||
ACTION_DOWNLOAD = 2
|
ACTION_DOWNLOAD = 2
|
||||||
@ -36,17 +37,24 @@ def listing(repo_type):
|
|||||||
print(image)
|
print(image)
|
||||||
|
|
||||||
def download(image_name):
|
def download(image_name):
|
||||||
actionqueue = ActionQueue()
|
queue = ActionQueue()
|
||||||
local_images = repo_local.get_images()
|
local_images = repo_local.get_images()
|
||||||
for layer in repo_online.get_image(image_name)['layers']:
|
for layer in repo_online.get_image(image_name)['layers']:
|
||||||
if layer not in local_images:
|
if layer not in local_images:
|
||||||
image = Image(layer, False)
|
queue.download_image(Image(layer, False))
|
||||||
actionqueue.append(ActionItem(f'Downloading {image_name}', image.download))
|
queue.process()
|
||||||
actionqueue.append(ActionItem(f'Unpacking {image_name}', image.unpack_downloaded))
|
|
||||||
actionqueue.process()
|
|
||||||
|
|
||||||
def delete(image_name):
|
def delete(image_name):
|
||||||
Image(image_name, False).delete()
|
# TODO: Check if any container or image doesn't depend
|
||||||
|
# TODO: Some kind of autoremove routine for images unused in containers
|
||||||
|
try:
|
||||||
|
image = Image(image_name)
|
||||||
|
except ImageNotFoundError:
|
||||||
|
return
|
||||||
|
queue = ActionQueue()
|
||||||
|
for layer in reversed(image.layers):
|
||||||
|
queue.delete_image(Image(layer, False))
|
||||||
|
queue.process()
|
||||||
|
|
||||||
def build(filename, force, do_publish):
|
def build(filename, force, do_publish):
|
||||||
# Check if a build is needed and attempt to build the image from image file
|
# Check if a build is needed and attempt to build the image from image file
|
||||||
@ -68,8 +76,8 @@ def publish(image_name, force):
|
|||||||
# Check if publishing is needed and attempt to publish the image
|
# Check if publishing is needed and attempt to publish the image
|
||||||
if force or image_name not in repo_publish.get_images():
|
if force or image_name not in repo_publish.get_images():
|
||||||
image = Image(image_name)
|
image = Image(image_name)
|
||||||
image.unpublish()
|
|
||||||
print(f'Publishing image {image_name}')
|
print(f'Publishing image {image_name}')
|
||||||
|
image.unpublish()
|
||||||
image.publish()
|
image.publish()
|
||||||
print(f'Image {image_name} compressed from {readable_size(image.size)} to {readable_size(image.dlsize)} and published successfully')
|
print(f'Image {image_name} compressed from {readable_size(image.size)} to {readable_size(image.dlsize)} and published successfully')
|
||||||
else:
|
else:
|
||||||
|
@ -10,8 +10,12 @@ class ActionQueue:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.queue = []
|
self.queue = []
|
||||||
|
|
||||||
def append(self, actionitem):
|
def download_image(self, image):
|
||||||
self.queue.append(actionitem)
|
self.queue.append(ActionItem(f'Downloading image {image.name}', image.download))
|
||||||
|
self.queue.append(ActionItem(f'Unpacking image {image.name}', image.unpack_downloaded))
|
||||||
|
|
||||||
|
def delete_image(self, image):
|
||||||
|
self.queue.append(ActionItem(f'Deleting image {image.name}', image.delete, False))
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
index = 0
|
index = 0
|
||||||
@ -22,23 +26,30 @@ class ActionQueue:
|
|||||||
item.run()
|
item.run()
|
||||||
|
|
||||||
class ActionItem:
|
class ActionItem:
|
||||||
def __init__(self, text, action):
|
def __init__(self, text, action, has_progress=True):
|
||||||
self.text = text
|
self.text = text
|
||||||
self.action = action
|
self.action = action
|
||||||
self.units_total = 0
|
self.has_progress = has_progress
|
||||||
|
self.units_total = 1
|
||||||
self.units_done = 0
|
self.units_done = 0
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
if self.has_progress:
|
||||||
with ThreadPoolExecutor() as executor:
|
with ThreadPoolExecutor() as executor:
|
||||||
future = executor.submit(self.action, self)
|
future = executor.submit(self.action, self)
|
||||||
while not future.done():
|
while not future.done():
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
self.print_status()
|
self.print_progress()
|
||||||
# Get the result of the future and let it raise exception, if there was any
|
# Get the result of the future and let it raise exception, if there was any
|
||||||
data = future.result()
|
data = future.result()
|
||||||
self.print_status('\n')
|
self.print_progress('\n')
|
||||||
|
else:
|
||||||
|
self.print_progress()
|
||||||
|
self.action()
|
||||||
|
self.units_done = 1
|
||||||
|
self.print_progress('\n')
|
||||||
|
|
||||||
def print_status(self, end='\r'):
|
def print_progress(self, end='\r'):
|
||||||
print(f'\x1b[K{self.text} ({self.units_done}/{self.units_total}) [{self.units_done/self.units_total*100:.2f} %]', end=end)
|
print(f'\x1b[K{self.text} ({self.units_done}/{self.units_total}) [{self.units_done/self.units_total*100:.2f} %]', end=end)
|
||||||
|
|
||||||
def readable_size(bytes):
|
def readable_size(bytes):
|
||||||
|
Loading…
Reference in New Issue
Block a user