spoc/usr/bin/spoc-image

128 lines
4.5 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import argparse
from spoc import repo_local
from spoc import repo_online
from spoc import repo_publish
from spoc.image import Image
from spoc.imagebuilder import ImageBuilder
from spoc.cli import ActionQueue, ActionItem, readable_size
ACTION_LIST = 1
ACTION_DOWNLOAD = 2
ACTION_DELETE = 3
ACTION_BUILD = 4
ACTION_PUBLISH = 5
ACTION_UNPUBLISH = 6
def get_image_name(file_path):
# Read and return image name from image file
with open(file_path) as f:
for line in f:
if line.startswith('IMAGE '):
return line.split()[1]
return None
def listing(repo_type):
if repo_type == 'installed':
images = repo_local.get_images()
elif repo_type == 'online':
images = repo_online.get_images()
elif repo_type == 'published':
images = repo_publish.get_images()
for image in images:
print(image)
def download(image_name):
actionqueue = ActionQueue()
local_images = repo_local.get_images()
for layer in repo_online.get_image(image_name)['layers']:
if layer not in local_images:
image = Image(layer, False)
actionqueue.append(ActionItem(f'Downloading {image_name}', image.download))
actionqueue.append(ActionItem(f'Unpacking {image_name}', image.unpack_downloaded))
actionqueue.process()
def delete(image_name):
Image(image_name, False).delete()
def build(filename, force, do_publish):
# Check if a build is needed and attempt to build the image from image file
image_name = get_image_name(filename)
if force or image_name not in repo_local.get_images():
image = Image(image_name, False)
print(f'Building image {image_name} from file {filename}')
image.delete()
image.create(ImageBuilder(), filename)
print(f'Image {image_name} built successfully')
# If publishing was requested, force publish after successful build
force = True
else:
print(f'Image {image_name} already built, skipping build task')
if do_publish:
publish(image_name, force)
def publish(image_name, force):
# Check if publishing is needed and attempt to publish the image
if force or image_name not in repo_publish.get_images():
image = Image(image_name)
image.unpublish()
print(f'Publishing image {image_name}')
image.publish()
print(f'Image {image_name} compressed from {readable_size(image.size)} to {readable_size(image.dlsize)} and published successfully')
else:
print(f'Image {image_name} already published, skipping publish task')
def unpublish(image_name):
Image(image_name, False).unpublish()
parser = argparse.ArgumentParser(description='SPOC image manager')
parser.set_defaults(action=None)
subparsers = parser.add_subparsers()
parser_list = subparsers.add_parser('list')
parser_list.set_defaults(action=ACTION_LIST)
parser_list.add_argument('type', choices=('installed', 'online', 'published'), default='installed', const='installed', nargs='?')
parser_download = subparsers.add_parser('download')
parser_download.set_defaults(action=ACTION_DOWNLOAD)
parser_download.add_argument('image')
parser_delete = subparsers.add_parser('delete')
parser_delete.set_defaults(action=ACTION_DELETE)
parser_delete.add_argument('image')
parser_build = subparsers.add_parser('build')
parser_build.set_defaults(action=ACTION_BUILD)
parser_build.add_argument('-f', '--force', action='store_true', help='Force rebuild already existing image')
parser_build.add_argument('-p', '--publish', action='store_true', help='Publish the image after successful build')
parser_build.add_argument('file')
parser_publish = subparsers.add_parser('publish')
parser_publish.set_defaults(action=ACTION_PUBLISH)
parser_publish.add_argument('-f', '--force', action='store_true', help='Force republish already published image')
parser_publish.add_argument('image')
parser_unpublish = subparsers.add_parser('unpublish')
parser_unpublish.set_defaults(action=ACTION_UNPUBLISH)
parser_unpublish.add_argument('image')
args = parser.parse_args()
if args.action == ACTION_LIST:
listing(args.type)
elif args.action == ACTION_DOWNLOAD:
download(args.image)
elif args.action == ACTION_DELETE:
delete(args.image)
elif args.action == ACTION_BUILD:
build(args.file, args.force, args.publish)
elif args.action == ACTION_PUBLISH:
publish(args.image, args.force)
elif args.action == ACTION_UNPUBLISH:
unpublish(args.image)
else:
parser.print_usage()