Implement App basics and publish/unpublish

This commit is contained in:
Disassembler 2020-02-19 23:13:46 +01:00
parent 8a39528773
commit e71514c6f9
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
2 changed files with 84 additions and 23 deletions

View File

@ -3,12 +3,26 @@
import argparse import argparse
import os import os
from pkg_resources import parse_version
from spoc import publisher from spoc import repo_local
from spoc import repo_online
from spoc import repo_publish
from spoc.app import App
from spoc.cli import readable_size from spoc.cli import readable_size
def listing(): def listing(list_type):
raise NotImplementedException() 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() 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()
for app in apps:
print(app)
def install(): def install():
raise NotImplementedException() raise NotImplementedException()
@ -28,23 +42,20 @@ def stop():
def status(): def status():
raise NotImplementedException() raise NotImplementedException()
def publish(composefile, do_publish): 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 # Check if publishing is needed and attempt to publish the application
app_name = os.path.basename(os.path.dirname(filepath)) if force or app_name not in repo_publish.get_apps():
if not do_publish: app = App(app_name, False)
try: print(f'Publishing application {app_name} from file {os.path.abspath(filename)}')
publisher.get_app(app_name) app.unpublish()
except KeyError: size, dlsize = app.publish(filename)
do_publish = True print(f'Application {app_name} compressed from {readable_size(size)} to {readable_size(dlsize)} and published successfully')
if do_publish:
print(f'Publishing application "{app_name}"')
package = publisher.publish_app(app_name)['package']
print(f'Application "{app_name}" compressed from {readable_size(package["size"])} to {readable_size(package["dlsize"])}')
else: else:
print(f'Application "{app_name}" already published, skipping publishing') print(f'Application {app_name} already published, skipping publish task')
def unpublish(): def unpublish(app_name):
raise NotImplementedException() App(app_name, False).unpublish()
parser = argparse.ArgumentParser(description='SPOC application manager') parser = argparse.ArgumentParser(description='SPOC application manager')
parser.set_defaults(action=None) parser.set_defaults(action=None)
@ -52,7 +63,7 @@ subparsers = parser.add_subparsers()
parser_list = subparsers.add_parser('list') parser_list = subparsers.add_parser('list')
parser_list.set_defaults(action=listing) parser_list.set_defaults(action=listing)
parser_list.add_argument('type', choices=('installed', 'online', 'upgrades', 'published'), default='installed', const='installed', nargs='?') parser_list.add_argument('type', choices=('installed', 'online', 'updates', 'published'), default='installed', const='installed', nargs='?')
parser_install = subparsers.add_parser('install') parser_install = subparsers.add_parser('install')
parser_install.set_defaults(action=install) parser_install.set_defaults(action=install)
@ -81,7 +92,7 @@ parser_status.add_argument('app')
parser_publish = subparsers.add_parser('publish') parser_publish = subparsers.add_parser('publish')
parser_publish.set_defaults(action=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('-f', '--force', action='store_true', help='Force republish already published application')
parser_publish.add_argument('file') parser_publish.add_argument('filename')
parser_unpublish = subparsers.add_parser('unpublish') parser_unpublish = subparsers.add_parser('unpublish')
parser_unpublish.set_defaults(action=unpublish) parser_unpublish.set_defaults(action=unpublish)
@ -104,9 +115,8 @@ elif args.action is stop:
elif args.action is status: elif args.action is status:
status(args.app) status(args.app)
elif args.action is publish: elif args.action is publish:
publish(args.file, args.force) publish(args.filename, args.force)
elif args.action is unpublish: elif args.action is unpublish:
unpublish(args.app) unpublish(args.app)
else: else:
parser.print_usage() parser.print_usage()

View File

@ -1,6 +1,57 @@
# -*- coding: utf-8 -*-
import json
import os
import tarfile
from . import repo_local
from . import repo_publish
from .config import PUB_APPS_DIR
from .container import Container
class App: class App:
def __init__(self): def __init__(self, name, load_from_repo=True):
self.name - None self.name = name
self.version = None self.version = None
self.meta = {} self.meta = {}
self.containers = [] self.containers = []
if load_from_repo:
self.set_definition(repo_local.get_app(name))
def set_definition(self, definition):
self.version = definition['version']
self.meta = definition['meta']
self.containers = [Container(container) for container in definition['containers']]
def get_definition(self):
return {
'version': self.version,
'meta': self.meta.copy(),
'containers': [container.name for container in self.containers]
}
def publish(self, filename):
builddir = os.path.dirname(filename)
os.makedirs(PUB_APPS_DIR, 0o700, True)
files = repo_publish.TarSizeCounter()
archive_path = os.path.join(PUB_APPS_DIR, f'{self.name}.tar.xz')
with tarfile.open(archive_path, 'w:xz') as tar:
for content in ('install', 'install.sh', 'update', 'update.sh', 'uninstall', 'uninstall.sh'):
content_path = os.path.join(builddir, content)
if os.path.exists(content_path):
tar.add(content_path, os.path.join(self.name, content), filter=files.add_file)
with open(filename) as f:
definition = json.load(f)
definition['size'] = files.size
definition['dlsize'] = os.path.getsize(archive_path)
definition['hash'] = repo_publish.sign_file(archive_path).hex()
repo_publish.register_app(self.name, definition)
return (definition['size'], definition['dlsize'])
def unpublish(self):
repo_publish.unregister_app(self.name)
archive_path = os.path.join(PUB_APPS_DIR, f'{self.name}.tar.xz')
try:
os.unlink(archive_path)
except FileNotFoundError:
pass