Populate App definition members dynamically
This commit is contained in:
parent
2de52c525b
commit
7cf9a10b46
@ -14,6 +14,8 @@ from .config import APPS_DIR, ONLINE_APPS_URL, PUB_APPS_DIR, TMP_APPS_DIR, LAYER
|
|||||||
from .container import Container
|
from .container import Container
|
||||||
from .image import Image
|
from .image import Image
|
||||||
|
|
||||||
|
DEFINITION_MEMBERS = {'version', 'meta', 'autostart', 'containers'}
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
def __init__(self, name, define_containers=True, load_from_repo=True):
|
def __init__(self, name, define_containers=True, load_from_repo=True):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -26,20 +28,25 @@ class App:
|
|||||||
self.set_definition(repo_local.get_app(name), define_containers)
|
self.set_definition(repo_local.get_app(name), define_containers)
|
||||||
|
|
||||||
def set_definition(self, definition, define_containers):
|
def set_definition(self, definition, define_containers):
|
||||||
self.version = definition['version']
|
# Set attributes given by definition
|
||||||
self.meta = definition['meta']
|
for key in DEFINITION_MEMBERS.intersection(definition):
|
||||||
self.autostart = definition['autostart']
|
setattr(self, key, definition[key])
|
||||||
|
# Populate containers property with actual container objects
|
||||||
self.containers = [Container(container, define_containers) for container in definition['containers']]
|
self.containers = [Container(container, define_containers) for container in definition['containers']]
|
||||||
|
|
||||||
def get_definition(self):
|
def get_definition(self):
|
||||||
return {
|
# Return shallow copy of image definition as dictionary
|
||||||
'version': self.version,
|
definition = {}
|
||||||
'meta': self.meta.copy(),
|
for key in DEFINITION_MEMBERS:
|
||||||
'autostart': self.autostart,
|
value = getattr(self, key)
|
||||||
'containers': [container.name for container in self.containers]
|
if value:
|
||||||
}
|
definition[key] = copy.copy(value)
|
||||||
|
# Overwrite containers key with list of container names
|
||||||
|
definition['containers'] = [container.name for container in self.containers]
|
||||||
|
return definition
|
||||||
|
|
||||||
def download(self, observer):
|
def download(self, observer):
|
||||||
|
# Download the archive with application scripts and install data
|
||||||
os.makedirs(TMP_APPS_DIR, 0o700, True)
|
os.makedirs(TMP_APPS_DIR, 0o700, True)
|
||||||
archive_url = urllib.parse.urljoin(ONLINE_APPS_URL, f'{self.name}.tar.xz')
|
archive_url = urllib.parse.urljoin(ONLINE_APPS_URL, f'{self.name}.tar.xz')
|
||||||
archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz')
|
||||||
@ -48,6 +55,7 @@ class App:
|
|||||||
repo_online.download_archive(archive_url, archive_path, definition['hash'], observer)
|
repo_online.download_archive(archive_url, archive_path, definition['hash'], observer)
|
||||||
|
|
||||||
def unpack_downloaded(self, observer):
|
def unpack_downloaded(self, observer):
|
||||||
|
# Unpack downloaded archive with application scripts and install data
|
||||||
archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz')
|
||||||
definition = repo_online.get_app(self.name)
|
definition = repo_online.get_app(self.name)
|
||||||
observer.units_total = definition['size']
|
observer.units_total = definition['size']
|
||||||
@ -66,6 +74,7 @@ class App:
|
|||||||
subprocess.run(script_path, cwd=cwd, env=env, check=True)
|
subprocess.run(script_path, cwd=cwd, env=env, check=True)
|
||||||
|
|
||||||
def create_container(self, name, definition):
|
def create_container(self, name, definition):
|
||||||
|
# Create container and enhance its definition (typically mounts) based on application requirements
|
||||||
container = Container(name, False)
|
container = Container(name, False)
|
||||||
container.set_definition(Image(definition['image']).get_definition())
|
container.set_definition(Image(definition['image']).get_definition())
|
||||||
if 'depends' in definition:
|
if 'depends' in definition:
|
||||||
@ -78,6 +87,7 @@ class App:
|
|||||||
self.containers.append(container)
|
self.containers.append(container)
|
||||||
|
|
||||||
def install(self):
|
def install(self):
|
||||||
|
# Install the application
|
||||||
definition = repo_online.get_app(self.name)
|
definition = repo_online.get_app(self.name)
|
||||||
self.version = definition['version']
|
self.version = definition['version']
|
||||||
self.meta = definition['meta']
|
self.meta = definition['meta']
|
||||||
@ -121,17 +131,26 @@ class App:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
# Start all application containers
|
||||||
for container in self.containers:
|
for container in self.containers:
|
||||||
container.start()
|
container.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
# Stop all application containers
|
||||||
for container in self.containers:
|
for container in self.containers:
|
||||||
container.stop()
|
container.stop()
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
|
# Return status fo all application containers
|
||||||
return {container.name:container.get_state() for container in sorted(self.containers)}
|
return {container.name:container.get_state() for container in sorted(self.containers)}
|
||||||
|
|
||||||
|
def set_autostart(self, autostart):
|
||||||
|
# Configure if the application should be automatically started after boot
|
||||||
|
self.autostart = autostart
|
||||||
|
repo_local.register_app(self.name, self.get_definition())
|
||||||
|
|
||||||
def publish(self, filename):
|
def publish(self, filename):
|
||||||
|
# Create application archive and register to publish repository
|
||||||
builddir = os.path.dirname(filename)
|
builddir = os.path.dirname(filename)
|
||||||
os.makedirs(PUB_APPS_DIR, 0o755, True)
|
os.makedirs(PUB_APPS_DIR, 0o755, True)
|
||||||
files = repo_publish.TarSizeCounter()
|
files = repo_publish.TarSizeCounter()
|
||||||
@ -150,13 +169,10 @@ class App:
|
|||||||
return (definition['size'], definition['dlsize'])
|
return (definition['size'], definition['dlsize'])
|
||||||
|
|
||||||
def unpublish(self):
|
def unpublish(self):
|
||||||
|
# Remove the application from publish repository
|
||||||
repo_publish.unregister_app(self.name)
|
repo_publish.unregister_app(self.name)
|
||||||
archive_path = os.path.join(PUB_APPS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(PUB_APPS_DIR, f'{self.name}.tar.xz')
|
||||||
try:
|
try:
|
||||||
os.unlink(archive_path)
|
os.unlink(archive_path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_autostart(self, autostart):
|
|
||||||
self.autostart = autostart
|
|
||||||
repo_local.register_app(self.name, self.get_definition())
|
|
||||||
|
@ -53,6 +53,7 @@ class Container:
|
|||||||
self.set_definition(repo_local.get_container(name))
|
self.set_definition(repo_local.get_container(name))
|
||||||
|
|
||||||
def set_definition(self, definition):
|
def set_definition(self, definition):
|
||||||
|
# Set attributes given by definition
|
||||||
for key in DEFINITION_MEMBERS.intersection(definition):
|
for key in DEFINITION_MEMBERS.intersection(definition):
|
||||||
setattr(self, key, definition[key])
|
setattr(self, key, definition[key])
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ class Image:
|
|||||||
self.set_definition(repo_local.get_image(name))
|
self.set_definition(repo_local.get_image(name))
|
||||||
|
|
||||||
def set_definition(self, definition):
|
def set_definition(self, definition):
|
||||||
|
# Set attributes given by definition
|
||||||
for key in DEFINITION_MEMBERS.intersection(definition):
|
for key in DEFINITION_MEMBERS.intersection(definition):
|
||||||
setattr(self, key, definition[key])
|
setattr(self, key, definition[key])
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ class Image:
|
|||||||
repo_local.register_image(self.name, self.get_definition())
|
repo_local.register_image(self.name, self.get_definition())
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
# Remove the layer from local repository and filesystem
|
||||||
repo_local.unregister_image(self.name)
|
repo_local.unregister_image(self.name)
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(self.layer_path)
|
shutil.rmtree(self.layer_path)
|
||||||
@ -57,6 +59,7 @@ class Image:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def download(self, observer):
|
def download(self, observer):
|
||||||
|
# Download the archive with layer data
|
||||||
os.makedirs(TMP_LAYERS_DIR, 0o700, True)
|
os.makedirs(TMP_LAYERS_DIR, 0o700, True)
|
||||||
archive_url = urllib.parse.urljoin(ONLINE_LAYERS_URL, f'{self.name}.tar.xz')
|
archive_url = urllib.parse.urljoin(ONLINE_LAYERS_URL, f'{self.name}.tar.xz')
|
||||||
archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz')
|
||||||
@ -65,6 +68,7 @@ class Image:
|
|||||||
repo_online.download_archive(archive_url, archive_path, definition['hash'], observer)
|
repo_online.download_archive(archive_url, archive_path, definition['hash'], observer)
|
||||||
|
|
||||||
def unpack_downloaded(self, observer):
|
def unpack_downloaded(self, observer):
|
||||||
|
# Unpack downloaded archive with layer data
|
||||||
archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz')
|
||||||
definition = repo_online.get_image(self.name)
|
definition = repo_online.get_image(self.name)
|
||||||
observer.units_total = definition['size']
|
observer.units_total = definition['size']
|
||||||
@ -73,6 +77,7 @@ class Image:
|
|||||||
repo_local.register_image(self.name, definition)
|
repo_local.register_image(self.name, definition)
|
||||||
|
|
||||||
def publish(self):
|
def publish(self):
|
||||||
|
# Create layer archive and register to publish repository
|
||||||
os.makedirs(PUB_LAYERS_DIR, 0o755, True)
|
os.makedirs(PUB_LAYERS_DIR, 0o755, True)
|
||||||
files = repo_publish.TarSizeCounter()
|
files = repo_publish.TarSizeCounter()
|
||||||
archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz')
|
||||||
@ -86,6 +91,7 @@ class Image:
|
|||||||
return (definition['size'], definition['dlsize'])
|
return (definition['size'], definition['dlsize'])
|
||||||
|
|
||||||
def unpublish(self):
|
def unpublish(self):
|
||||||
|
# Remove the layer from publish repository
|
||||||
repo_publish.unregister_image(self.name)
|
repo_publish.unregister_image(self.name)
|
||||||
archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz')
|
archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz')
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user