#!/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()