#!/usr/bin/python3 # -*- coding: utf-8 -*- import argparse import os from pkg_resources import parse_version from spoc import repo_local, repo_online, repo_publish from spoc.app import App from spoc.cli import ActionQueue, print_lock, readable_size from spoc.config import LOCK_FILE from spoc.flock import locked from spoc.image import Image def listing(list_type): # Lists applications in particular state if list_type == 'installed': apps = repo_local.get_apps() elif list_type == 'online': apps = repo_online.get_apps() elif list_type == 'updates': online_apps = repo_online.get_apps() apps = [a for a,d in repo_local.get_apps().items() if a in online_apps and parse_version(online_apps[a]['version']) > parse_version(d['version'])] elif list_type == 'published': apps = repo_publish.get_apps() elif list_type == 'running': apps = [app for app in repo_local.get_apps() if App(app).is_running()] elif list_type == 'stopped': apps = [app for app in repo_local.get_apps() if App(app).is_stopped()] for app in apps: print(app) @locked(LOCK_FILE, print_lock) def install(app_name): # Install application from online repository queue = ActionQueue() required_images = [] for container in repo_online.get_app(app_name)['containers'].values(): required_images.extend(repo_online.get_image(container['image'])['layers']) local_images = repo_local.get_images() # Layers need to be downloaded in correct order for layer in list(dict.fromkeys(required_images)): if layer not in local_images: queue.download_image(Image(layer, False)) queue.install_app(App(app_name, False, False)) queue.process() @locked(LOCK_FILE, print_lock) def update(app_name): # Update application from online repository queue = ActionQueue() required_images = [] for container in repo_online.get_app(app_name)['containers'].values(): required_images.extend(repo_online.get_image(container['image'])['layers']) local_images = repo_local.get_images() # Layers need to be downloaded in correct order for layer in list(dict.fromkeys(required_images)): if layer not in local_images: queue.download_image(Image(layer, False)) queue.update_app(App(app_name, False)) queue.process() @locked(LOCK_FILE, print_lock) def uninstall(app_name): # Remove application and its containers from local repository queue = ActionQueue() queue.uninstall_app(App(app_name, False)) queue.process() def start(app_name): # Start all application containers queue = ActionQueue() queue.start_app(App(app_name)) queue.process() def stop(app_name): # Stop all application containers queue = ActionQueue() queue.stop_app(App(app_name)) queue.process() def status(app_name): # Print status of all application containers for container,status in sorted(App(app_name).status().items()): print(f'{container}: {status.value}') def publish(filename, force): app_name = os.path.basename(os.path.dirname(os.path.abspath(filename))) # Check if publishing is needed and attempt to publish the application if force or app_name not in repo_publish.get_apps(): app = App(app_name, False, False) print(f'Publishing application {app_name} from file {os.path.abspath(filename)}') app.unpublish() size, dlsize = app.publish(filename) print(f'Application {app_name} compressed from {readable_size(size)} to {readable_size(dlsize)} and published successfully') else: print(f'Application {app_name} already published, skipping publish task') def unpublish(app_name): # Remove the application from publish repo App(app_name, False, False).unpublish() def autostart(app_name, value): # Set if the application should be autostarted on boot value = value.lower() in ('1', 'on', 'enable', 'true') App(app_name, False).set_autostart(value) def start_autostarted(): # Start all applications (resp. their containers) which are set to be autoostarted on boot apps = [App(a) for a,d in repo_local.get_apps().items() if d['autostart']] for app in apps: app.start() def stop_all(): # Stop all applications (resp. their containers) apps = [App(a) for a,d in repo_local.get_apps().items()] for app in apps: app.stop() parser = argparse.ArgumentParser(description='SPOC application manager') parser.set_defaults(action=None) subparsers = parser.add_subparsers() parser_list = subparsers.add_parser('list') parser_list.set_defaults(action=listing) parser_list.add_argument('type', choices=('installed', 'online', 'updates', 'published', 'running', 'stopped'), default='installed', const='installed', nargs='?', help='Selected repository or application criteria') parser_install = subparsers.add_parser('install') parser_install.set_defaults(action=install) parser_install.add_argument('app', help='Name of the application to install') parser_update = subparsers.add_parser('update') parser_update.set_defaults(action=update) parser_update.add_argument('app', help='Name of the application to update') parser_uninstall = subparsers.add_parser('uninstall') parser_uninstall.set_defaults(action=uninstall) parser_uninstall.add_argument('app', help='Name of the application to uninstall') parser_start = subparsers.add_parser('start') parser_start.set_defaults(action=start) parser_start.add_argument('app', help='Name of the application to start') parser_stop = subparsers.add_parser('stop') parser_stop.set_defaults(action=stop) parser_stop.add_argument('app', help='Name of the application to stop') parser_status = subparsers.add_parser('status') parser_status.set_defaults(action=status) parser_status.add_argument('app', help='Name of the application to check') parser_publish = subparsers.add_parser('publish') parser_publish.set_defaults(action=publish) parser_publish.add_argument('-f', '--force', action='store_true', help='Force republish already published application') parser_publish.add_argument('filename', help='Path to metadata file of the application to publish') parser_unpublish = subparsers.add_parser('unpublish') parser_unpublish.set_defaults(action=unpublish) parser_unpublish.add_argument('app', help='Name of the application to unpublish') parser_autostart = subparsers.add_parser('autostart') parser_autostart.set_defaults(action=autostart) parser_autostart.add_argument('app', help='Name of the application to be automatically started') parser_autostart.add_argument('value', choices=('1', 'on', 'enable', 'true', '0', 'off', 'disable', 'false'), help='Set or unset the applications to be automatically started after the host boots up') parser_start_autostarted = subparsers.add_parser('start-autostarted') parser_start_autostarted.set_defaults(action=start_autostarted) parser_stop_all = subparsers.add_parser('stop-all') parser_stop_all.set_defaults(action=stop_all) args = parser.parse_args() if args.action is listing: listing(args.type) elif args.action is install: install(args.app) elif args.action is update: update(args.app) elif args.action is uninstall: uninstall(args.app) elif args.action is start: start(args.app) elif args.action is stop: stop(args.app) elif args.action is status: status(args.app) elif args.action is publish: publish(args.filename, args.force) elif args.action is unpublish: unpublish(args.app) elif args.action is autostart: autostart(args.app, args.value) elif args.action is start_autostarted: start_autostarted() elif args.action is stop_all: stop_all() else: parser.print_usage()