Add support for installation from definition file
This commit is contained in:
parent
d2e17c8d49
commit
c2cd5b12a0
@ -40,20 +40,20 @@ def list_updates():
|
|||||||
return dict(sorted(apps.items()))
|
return dict(sorted(apps.items()))
|
||||||
|
|
||||||
@locked()
|
@locked()
|
||||||
def install(app_name):
|
def install(app_name, from_file=None):
|
||||||
if app_name in podman.get_apps():
|
if app_name in podman.get_apps():
|
||||||
raise AppAlreadyInstalledError(app_name)
|
raise AppAlreadyInstalledError(app_name)
|
||||||
if app_name not in repo.get_apps():
|
if not from_file and app_name not in repo.get_apps():
|
||||||
raise AppNotInRepoError(app_name)
|
raise AppNotInRepoError(app_name)
|
||||||
app.install(app_name)
|
app.install(app_name, from_file=from_file)
|
||||||
|
|
||||||
@locked()
|
@locked()
|
||||||
def update(app_name):
|
def update(app_name, from_file=None):
|
||||||
if app_name not in podman.get_apps():
|
if app_name not in podman.get_apps():
|
||||||
raise AppNotInstalledError(app_name)
|
raise AppNotInstalledError(app_name)
|
||||||
if app_name not in list_updates():
|
if not from_file and app_name not in list_updates():
|
||||||
raise AppNotUpdateableError(app_name)
|
raise AppNotUpdateableError(app_name)
|
||||||
app.update(app_name)
|
app.update(app_name, from_file=from_file)
|
||||||
|
|
||||||
@locked()
|
@locked()
|
||||||
def uninstall(app_name):
|
def uninstall(app_name):
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
from . import autostart
|
from . import autostart
|
||||||
from . import config
|
from . import config
|
||||||
@ -11,8 +12,14 @@ class App:
|
|||||||
self.app_name = app_name
|
self.app_name = app_name
|
||||||
self.env_file = os.path.join(config.DATA_DIR, f'{app_name}.env')
|
self.env_file = os.path.join(config.DATA_DIR, f'{app_name}.env')
|
||||||
|
|
||||||
def install(self, is_update=False):
|
def get_definition(self, from_file=None):
|
||||||
definition = repo.get_apps()[self.app_name]
|
if from_file:
|
||||||
|
with open(from_file, encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
return repo.get_apps()[self.app_name]
|
||||||
|
|
||||||
|
def install(self, is_update=False, from_file=None):
|
||||||
|
definition = self.get_definition(from_file)
|
||||||
version = definition['version']
|
version = definition['version']
|
||||||
containers = definition['containers']
|
containers = definition['containers']
|
||||||
|
|
||||||
@ -44,8 +51,8 @@ class App:
|
|||||||
self.create_pod(version)
|
self.create_pod(version)
|
||||||
self.create_containers(containers)
|
self.create_containers(containers)
|
||||||
|
|
||||||
def update(self):
|
def update(self, from_file=None):
|
||||||
self.install(is_update=True)
|
self.install(is_update=True, from_file=from_file)
|
||||||
|
|
||||||
def uninstall(self):
|
def uninstall(self):
|
||||||
autostart.set_app(self.app_name, False)
|
autostart.set_app(self.app_name, False)
|
||||||
@ -124,11 +131,11 @@ class App:
|
|||||||
podman.create_container(self.app_name, name, image, env_file=self.env_file,
|
podman.create_container(self.app_name, name, image, env_file=self.env_file,
|
||||||
volumes=volumes, requires=requires, hosts=hosts)
|
volumes=volumes, requires=requires, hosts=hosts)
|
||||||
|
|
||||||
def install(app_name):
|
def install(app_name, from_file=None):
|
||||||
App(app_name).install()
|
App(app_name).install(from_file=from_file)
|
||||||
|
|
||||||
def update(app_name):
|
def update(app_name, from_file=None):
|
||||||
App(app_name).update()
|
App(app_name).update(from_file=from_file)
|
||||||
|
|
||||||
def uninstall(app_name):
|
def uninstall(app_name):
|
||||||
App(app_name).uninstall()
|
App(app_name).uninstall()
|
||||||
|
@ -42,11 +42,11 @@ def listing(list_type):
|
|||||||
for app_name, app_version in apps.items():
|
for app_name, app_version in apps.items():
|
||||||
print(app_name, app_version)
|
print(app_name, app_version)
|
||||||
|
|
||||||
def install(app_name):
|
def install(app_name, from_file):
|
||||||
spoc.install(app_name)
|
spoc.install(app_name, from_file)
|
||||||
|
|
||||||
def update(app_name):
|
def update(app_name, from_file):
|
||||||
spoc.update(app_name)
|
spoc.update(app_name, from_file)
|
||||||
|
|
||||||
def uninstall(app_name):
|
def uninstall(app_name):
|
||||||
spoc.uninstall(app_name)
|
spoc.uninstall(app_name)
|
||||||
@ -93,10 +93,16 @@ def parse_args(args=None):
|
|||||||
parser_install = subparsers.add_parser('install')
|
parser_install = subparsers.add_parser('install')
|
||||||
parser_install.set_defaults(action=install)
|
parser_install.set_defaults(action=install)
|
||||||
parser_install.add_argument('app', help='Name of the application to install')
|
parser_install.add_argument('app', help='Name of the application to install')
|
||||||
|
parser_install.add_argument('--from-file',
|
||||||
|
help='Filename containing the application definition ' \
|
||||||
|
'to be used instead of online repository')
|
||||||
|
|
||||||
parser_update = subparsers.add_parser('update')
|
parser_update = subparsers.add_parser('update')
|
||||||
parser_update.set_defaults(action=update)
|
parser_update.set_defaults(action=update)
|
||||||
parser_update.add_argument('app', help='Name of the application to update')
|
parser_update.add_argument('app', help='Name of the application to update')
|
||||||
|
parser_update.add_argument('--from-file',
|
||||||
|
help='Filename containing the application definition ' \
|
||||||
|
'to be used instead of online repository')
|
||||||
|
|
||||||
parser_uninstall = subparsers.add_parser('uninstall')
|
parser_uninstall = subparsers.add_parser('uninstall')
|
||||||
parser_uninstall.set_defaults(action=uninstall)
|
parser_uninstall.set_defaults(action=uninstall)
|
||||||
@ -143,9 +149,9 @@ def main(): # pylint: disable=too-many-branches
|
|||||||
if args.action is listing:
|
if args.action is listing:
|
||||||
listing(args.type)
|
listing(args.type)
|
||||||
elif args.action is install:
|
elif args.action is install:
|
||||||
install(args.app)
|
install(args.app, args.from_file)
|
||||||
elif args.action is update:
|
elif args.action is update:
|
||||||
update(args.app)
|
update(args.app, args.from_file)
|
||||||
elif args.action is uninstall:
|
elif args.action is uninstall:
|
||||||
uninstall(args.app)
|
uninstall(args.app)
|
||||||
elif args.action is start:
|
elif args.action is start:
|
||||||
|
@ -28,6 +28,26 @@ def test_init():
|
|||||||
assert instance.env_file == os.path.join(config.DATA_DIR, 'someapp.env')
|
assert instance.env_file == os.path.join(config.DATA_DIR, 'someapp.env')
|
||||||
|
|
||||||
@patch('spoc.repo.get_apps', return_value=MOCK_REPODATA)
|
@patch('spoc.repo.get_apps', return_value=MOCK_REPODATA)
|
||||||
|
def test_get_definition(repo_get_apps):
|
||||||
|
instance = app.App('someapp')
|
||||||
|
definition = instance.get_definition()
|
||||||
|
|
||||||
|
assert definition == MOCK_REPODATA['someapp']
|
||||||
|
|
||||||
|
repo_get_apps.assert_called_once()
|
||||||
|
|
||||||
|
@patch('spoc.repo.get_apps')
|
||||||
|
@patch('builtins.open', new_callable=mock_open, read_data=json.dumps(MOCK_REPODATA['someapp']))
|
||||||
|
def test_get_definition_from_file(file_open, repo_get_apps):
|
||||||
|
instance = app.App('someapp')
|
||||||
|
definition = instance.get_definition('somefile')
|
||||||
|
|
||||||
|
assert definition == MOCK_REPODATA['someapp']
|
||||||
|
|
||||||
|
file_open.assert_called_once_with('somefile', encoding='utf-8')
|
||||||
|
repo_get_apps.assert_not_called()
|
||||||
|
|
||||||
|
@patch('spoc.app.App.get_definition', return_value=MOCK_REPODATA['someapp'])
|
||||||
@patch('spoc.app.App.get_existing_volumes', return_value=set('somevol'))
|
@patch('spoc.app.App.get_existing_volumes', return_value=set('somevol'))
|
||||||
@patch('spoc.app.App.remove_volumes')
|
@patch('spoc.app.App.remove_volumes')
|
||||||
@patch('spoc.app.App.create_volumes')
|
@patch('spoc.app.App.create_volumes')
|
||||||
@ -37,11 +57,11 @@ def test_init():
|
|||||||
@patch('spoc.app.App.create_containers')
|
@patch('spoc.app.App.create_containers')
|
||||||
def test_install(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
def test_install(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
||||||
read_env_vars, create_volumes, remove_volumes,
|
read_env_vars, create_volumes, remove_volumes,
|
||||||
get_existing_volumes, repo_get_apps):
|
get_existing_volumes, get_definition):
|
||||||
instance = app.App('someapp')
|
instance = app.App('someapp')
|
||||||
instance.install()
|
instance.install()
|
||||||
|
|
||||||
repo_get_apps.assert_called_once()
|
get_definition.assert_called_once()
|
||||||
get_existing_volumes.assert_called_once()
|
get_existing_volumes.assert_called_once()
|
||||||
remove_volumes.assert_called_once_with(set('somevol'))
|
remove_volumes.assert_called_once_with(set('somevol'))
|
||||||
create_volumes.assert_called_once_with(set(('migrate', 'storage', 'uploads', 'postgres-data')))
|
create_volumes.assert_called_once_with(set(('migrate', 'storage', 'uploads', 'postgres-data')))
|
||||||
@ -50,7 +70,7 @@ def test_install(create_containers, create_pod, write_env_vars, #pylint: disable
|
|||||||
create_pod.assert_called_once_with('0.23.5-210416')
|
create_pod.assert_called_once_with('0.23.5-210416')
|
||||||
create_containers.assert_called_once_with(MOCK_REPODATA['someapp']['containers'])
|
create_containers.assert_called_once_with(MOCK_REPODATA['someapp']['containers'])
|
||||||
|
|
||||||
@patch('spoc.repo.get_apps', return_value=MOCK_REPODATA)
|
@patch('spoc.app.App.get_definition', return_value=MOCK_REPODATA['someapp'])
|
||||||
@patch('spoc.app.App.get_existing_volumes', return_value=set(('somevol', 'migrate', 'storage')))
|
@patch('spoc.app.App.get_existing_volumes', return_value=set(('somevol', 'migrate', 'storage')))
|
||||||
@patch('spoc.app.App.remove_volumes')
|
@patch('spoc.app.App.remove_volumes')
|
||||||
@patch('spoc.app.App.create_volumes')
|
@patch('spoc.app.App.create_volumes')
|
||||||
@ -60,11 +80,11 @@ def test_install(create_containers, create_pod, write_env_vars, #pylint: disable
|
|||||||
@patch('spoc.app.App.create_containers')
|
@patch('spoc.app.App.create_containers')
|
||||||
def test_update(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
def test_update(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
||||||
read_env_vars, create_volumes, remove_volumes,
|
read_env_vars, create_volumes, remove_volumes,
|
||||||
get_existing_volumes, repo_get_apps):
|
get_existing_volumes, get_definition):
|
||||||
instance = app.App('someapp')
|
instance = app.App('someapp')
|
||||||
instance.update()
|
instance.update(from_file='somefile')
|
||||||
|
|
||||||
repo_get_apps.assert_called_once()
|
get_definition.assert_called_once()
|
||||||
get_existing_volumes.assert_called_once()
|
get_existing_volumes.assert_called_once()
|
||||||
remove_volumes.assert_called_once_with(set(('somevol',)))
|
remove_volumes.assert_called_once_with(set(('somevol',)))
|
||||||
create_volumes.assert_called_once_with(set(('uploads', 'postgres-data')))
|
create_volumes.assert_called_once_with(set(('uploads', 'postgres-data')))
|
||||||
@ -229,14 +249,14 @@ def test_module_install(instance):
|
|||||||
app.install('someapp')
|
app.install('someapp')
|
||||||
|
|
||||||
instance.assert_called_once_with('someapp')
|
instance.assert_called_once_with('someapp')
|
||||||
instance.return_value.install.assert_called_once()
|
instance.return_value.install.assert_called_once_with(from_file=None)
|
||||||
|
|
||||||
@patch('spoc.app.App')
|
@patch('spoc.app.App')
|
||||||
def test_module_update(instance):
|
def test_module_update(instance):
|
||||||
app.update('someapp')
|
app.update('someapp', from_file='somefile')
|
||||||
|
|
||||||
instance.assert_called_once_with('someapp')
|
instance.assert_called_once_with('someapp')
|
||||||
instance.return_value.update.assert_called_once_with()
|
instance.return_value.update.assert_called_once_with(from_file='somefile')
|
||||||
|
|
||||||
@patch('spoc.app.App')
|
@patch('spoc.app.App')
|
||||||
def test_module_uninstall(instance):
|
def test_module_uninstall(instance):
|
||||||
|
@ -97,15 +97,15 @@ def test_listing_invalid(list_updates, list_online, list_installed, capsys):
|
|||||||
|
|
||||||
@patch('spoc.install')
|
@patch('spoc.install')
|
||||||
def test_install(install):
|
def test_install(install):
|
||||||
spoc_cli.install('someapp')
|
spoc_cli.install('someapp', 'somefile')
|
||||||
|
|
||||||
install.assert_called_once_with('someapp')
|
install.assert_called_once_with('someapp', 'somefile')
|
||||||
|
|
||||||
@patch('spoc.update')
|
@patch('spoc.update')
|
||||||
def test_update(update):
|
def test_update(update):
|
||||||
spoc_cli.update('someapp')
|
spoc_cli.update('someapp', None)
|
||||||
|
|
||||||
update.assert_called_once_with('someapp')
|
update.assert_called_once_with('someapp', None)
|
||||||
|
|
||||||
@patch('spoc.uninstall')
|
@patch('spoc.uninstall')
|
||||||
def test_uninstall(uninstall):
|
def test_uninstall(uninstall):
|
||||||
@ -212,14 +212,14 @@ def test_main_listing_online(listing):
|
|||||||
def test_main_install(install):
|
def test_main_install(install):
|
||||||
spoc_cli.main()
|
spoc_cli.main()
|
||||||
|
|
||||||
install.assert_called_once_with('someapp')
|
install.assert_called_once_with('someapp', None)
|
||||||
|
|
||||||
@patch('sys.argv', ['foo', 'update', 'someapp'])
|
@patch('sys.argv', ['foo', 'update', '--from-file', 'somefile', 'someapp'])
|
||||||
@patch('spoc_cli.update')
|
@patch('spoc_cli.update')
|
||||||
def test_main_update(update):
|
def test_main_update(update):
|
||||||
spoc_cli.main()
|
spoc_cli.main()
|
||||||
|
|
||||||
update.assert_called_once_with('someapp')
|
update.assert_called_once_with('someapp', 'somefile')
|
||||||
|
|
||||||
@patch('sys.argv', ['foo', 'uninstall', 'someapp'])
|
@patch('sys.argv', ['foo', 'uninstall', 'someapp'])
|
||||||
@patch('spoc_cli.uninstall')
|
@patch('spoc_cli.uninstall')
|
||||||
|
@ -66,11 +66,20 @@ def test_list_updates(podman_get_apps, repo_get_apps):
|
|||||||
@patch('spoc.app.install')
|
@patch('spoc.app.install')
|
||||||
def test_install(app_install, podman_get_apps, repo_get_apps):
|
def test_install(app_install, podman_get_apps, repo_get_apps):
|
||||||
spoc.install.__wrapped__('someapp')
|
spoc.install.__wrapped__('someapp')
|
||||||
#spoc.install('someapp')
|
|
||||||
|
|
||||||
podman_get_apps.assert_called_once()
|
podman_get_apps.assert_called_once()
|
||||||
repo_get_apps.assert_called_once()
|
repo_get_apps.assert_called_once()
|
||||||
app_install.assert_called_once_with('someapp')
|
app_install.assert_called_once_with('someapp', from_file=None)
|
||||||
|
|
||||||
|
@patch('spoc.repo.get_apps')
|
||||||
|
@patch('spoc.podman.get_apps', return_value={})
|
||||||
|
@patch('spoc.app.install')
|
||||||
|
def test_install_from_file(app_install, podman_get_apps, repo_get_apps):
|
||||||
|
spoc.install.__wrapped__('someapp', 'somefile')
|
||||||
|
|
||||||
|
podman_get_apps.assert_called_once()
|
||||||
|
repo_get_apps.assert_not_called()
|
||||||
|
app_install.assert_called_once_with('someapp', from_file='somefile')
|
||||||
|
|
||||||
@patch('spoc.repo.get_apps', return_value={'someapp': {'version': '0.1'}})
|
@patch('spoc.repo.get_apps', return_value={'someapp': {'version': '0.1'}})
|
||||||
@patch('spoc.podman.get_apps', return_value={'someapp': '0.1'})
|
@patch('spoc.podman.get_apps', return_value={'someapp': '0.1'})
|
||||||
@ -102,7 +111,7 @@ def test_update(app_update, podman_get_apps, list_updates):
|
|||||||
|
|
||||||
podman_get_apps.assert_called_once()
|
podman_get_apps.assert_called_once()
|
||||||
list_updates.assert_called_once()
|
list_updates.assert_called_once()
|
||||||
app_update.assert_called_once_with('someapp')
|
app_update.assert_called_once_with('someapp', from_file=None)
|
||||||
|
|
||||||
@patch('spoc.list_updates', return_value={})
|
@patch('spoc.list_updates', return_value={})
|
||||||
@patch('spoc.podman.get_apps', return_value={})
|
@patch('spoc.podman.get_apps', return_value={})
|
||||||
|
Loading…
Reference in New Issue
Block a user