2021-07-06 18:06:54 +02:00
|
|
|
import json
|
|
|
|
import os
|
|
|
|
from unittest.mock import patch, call, mock_open
|
|
|
|
|
|
|
|
from spoc import app
|
|
|
|
from spoc import config
|
|
|
|
|
|
|
|
|
|
|
|
TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), 'test_data')
|
2021-12-20 22:21:58 +01:00
|
|
|
with open(os.path.join(TEST_DATA_DIR, 'repository.json'), encoding='utf-8') as f:
|
2021-07-06 18:06:54 +02:00
|
|
|
MOCK_REPODATA = json.load(f)
|
|
|
|
|
2021-07-11 00:58:28 +02:00
|
|
|
MOCK_ENV = 'RAILS_ENV=test\n' \
|
|
|
|
'POSTGRES_PASSWORD=asdf=1234\n' \
|
|
|
|
'SOMEKEY=someval\n'
|
2021-07-06 18:06:54 +02:00
|
|
|
|
2021-07-11 00:58:28 +02:00
|
|
|
MOCK_ENV_DATA = {
|
|
|
|
'RAILS_ENV': 'test',
|
|
|
|
'POSTGRES_PASSWORD': 'asdf=1234',
|
|
|
|
'SOMEKEY': 'someval',
|
|
|
|
}
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_init():
|
|
|
|
instance = app.App('someapp')
|
|
|
|
|
|
|
|
assert instance.app_name == 'someapp'
|
|
|
|
assert instance.env_file == os.path.join(config.DATA_DIR, 'someapp.env')
|
|
|
|
|
|
|
|
@patch('spoc.repo.get_apps', return_value=MOCK_REPODATA)
|
|
|
|
@patch('spoc.app.App.get_existing_volumes', return_value=set('somevol'))
|
|
|
|
@patch('spoc.app.App.remove_volumes')
|
|
|
|
@patch('spoc.app.App.create_volumes')
|
|
|
|
@patch('spoc.app.App.read_env_vars')
|
|
|
|
@patch('spoc.app.App.write_env_vars')
|
|
|
|
@patch('spoc.app.App.create_pod')
|
|
|
|
@patch('spoc.app.App.create_containers')
|
2021-12-20 22:21:58 +01:00
|
|
|
def test_install(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
|
|
|
read_env_vars, create_volumes, remove_volumes,
|
|
|
|
get_existing_volumes, repo_get_apps):
|
2021-07-06 18:06:54 +02:00
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.install()
|
|
|
|
|
|
|
|
repo_get_apps.assert_called_once()
|
|
|
|
get_existing_volumes.assert_called_once()
|
|
|
|
remove_volumes.assert_called_once_with(set('somevol'))
|
|
|
|
create_volumes.assert_called_once_with(set(('migrate', 'storage', 'uploads', 'postgres-data')))
|
|
|
|
read_env_vars.assert_not_called()
|
|
|
|
write_env_vars.assert_called_once_with(MOCK_REPODATA['someapp']['environment'])
|
|
|
|
create_pod.assert_called_once_with('0.23.5-210416')
|
|
|
|
create_containers.assert_called_once_with(MOCK_REPODATA['someapp']['containers'])
|
|
|
|
|
|
|
|
@patch('spoc.repo.get_apps', return_value=MOCK_REPODATA)
|
|
|
|
@patch('spoc.app.App.get_existing_volumes', return_value=set(('somevol', 'migrate', 'storage')))
|
|
|
|
@patch('spoc.app.App.remove_volumes')
|
|
|
|
@patch('spoc.app.App.create_volumes')
|
2021-07-11 00:58:28 +02:00
|
|
|
@patch('spoc.app.App.read_env_vars', return_value=MOCK_ENV_DATA)
|
2021-07-06 18:06:54 +02:00
|
|
|
@patch('spoc.app.App.write_env_vars')
|
|
|
|
@patch('spoc.app.App.create_pod')
|
|
|
|
@patch('spoc.app.App.create_containers')
|
2021-12-20 22:21:58 +01:00
|
|
|
def test_update(create_containers, create_pod, write_env_vars, #pylint: disable=too-many-arguments
|
|
|
|
read_env_vars, create_volumes, remove_volumes,
|
|
|
|
get_existing_volumes, repo_get_apps):
|
2021-07-06 18:06:54 +02:00
|
|
|
instance = app.App('someapp')
|
2021-12-20 22:21:58 +01:00
|
|
|
instance.update()
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
repo_get_apps.assert_called_once()
|
|
|
|
get_existing_volumes.assert_called_once()
|
|
|
|
remove_volumes.assert_called_once_with(set(('somevol',)))
|
|
|
|
create_volumes.assert_called_once_with(set(('uploads', 'postgres-data')))
|
|
|
|
read_env_vars.assert_called_once()
|
|
|
|
expected_env_data = MOCK_REPODATA['someapp']['environment'].copy()
|
2021-07-11 00:58:28 +02:00
|
|
|
expected_env_data.update(MOCK_ENV_DATA)
|
2021-07-06 18:06:54 +02:00
|
|
|
del expected_env_data['SOMEKEY']
|
|
|
|
write_env_vars.assert_called_once_with(expected_env_data)
|
|
|
|
create_pod.assert_called_once_with('0.23.5-210416')
|
|
|
|
create_containers.assert_called_once_with(MOCK_REPODATA['someapp']['containers'])
|
|
|
|
|
2021-07-11 00:58:28 +02:00
|
|
|
@patch('spoc.autostart.set_app')
|
2021-07-06 18:06:54 +02:00
|
|
|
@patch('spoc.app.App.remove_pod')
|
|
|
|
@patch('spoc.app.App.remove_env_vars')
|
|
|
|
@patch('spoc.app.App.get_existing_volumes', return_value=set(('somevol', 'anothervol')))
|
|
|
|
@patch('spoc.app.App.remove_volumes')
|
2021-07-11 00:58:28 +02:00
|
|
|
def test_uninstall(remove_volumes, get_existing_volumes, remove_env_vars, remove_pod, autostart):
|
2021-07-06 18:06:54 +02:00
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.uninstall()
|
|
|
|
|
2021-07-11 00:58:28 +02:00
|
|
|
autostart.assert_called_with('someapp', False)
|
2021-07-06 18:06:54 +02:00
|
|
|
remove_pod.assert_called_once()
|
|
|
|
remove_env_vars.assert_called_once()
|
|
|
|
get_existing_volumes.assert_called_once()
|
|
|
|
remove_volumes.assert_called_once_with(set(('somevol', 'anothervol')))
|
|
|
|
|
|
|
|
@patch('spoc.podman.remove_pod')
|
|
|
|
@patch('spoc.podman.create_pod')
|
|
|
|
def test_create_pod(create_pod, remove_pod):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.create_pod('0.1')
|
|
|
|
|
|
|
|
remove_pod.assert_called_once_with('someapp')
|
|
|
|
create_pod.assert_called_once_with('someapp', '0.1')
|
|
|
|
|
|
|
|
@patch('spoc.podman.remove_pod')
|
|
|
|
def test_remove_pod(remove_pod):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.remove_pod()
|
|
|
|
|
|
|
|
remove_pod.assert_called_once_with('someapp')
|
|
|
|
|
|
|
|
@patch('builtins.open', new_callable=mock_open, read_data=MOCK_ENV)
|
|
|
|
def test_read_env_vars(env_open):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
env_vars = instance.read_env_vars()
|
|
|
|
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
2021-12-20 22:21:58 +01:00
|
|
|
env_open.assert_called_once_with(env_file, encoding='utf-8')
|
2021-07-11 00:58:28 +02:00
|
|
|
assert env_vars == MOCK_ENV_DATA
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
@patch('builtins.open', side_effect=FileNotFoundError('someapp.env'))
|
|
|
|
def test_read_env_vars_filenotfound(env_open):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
env_vars = instance.read_env_vars()
|
|
|
|
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
2021-12-20 22:21:58 +01:00
|
|
|
env_open.assert_called_once_with(env_file, encoding='utf-8')
|
|
|
|
assert not env_vars
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
@patch('os.makedirs')
|
|
|
|
@patch('builtins.open', new_callable=mock_open)
|
|
|
|
def test_write_env_vars(env_open, makedirs):
|
|
|
|
instance = app.App('someapp')
|
2021-07-11 00:58:28 +02:00
|
|
|
instance.write_env_vars(MOCK_ENV_DATA)
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
makedirs.assert_called_once_with(config.DATA_DIR, exist_ok=True)
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
2021-12-20 22:21:58 +01:00
|
|
|
env_open.assert_called_once_with(env_file, 'w', encoding='utf-8')
|
2021-07-06 18:06:54 +02:00
|
|
|
expected_writes = [call(line) for line in MOCK_ENV.splitlines(True)]
|
|
|
|
env_open().write.assert_has_calls(expected_writes, any_order=True)
|
|
|
|
|
|
|
|
@patch('os.unlink')
|
|
|
|
def test_remove_env_vars(unlink):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.remove_env_vars()
|
|
|
|
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
|
|
|
unlink.assert_called_once_with(env_file)
|
|
|
|
|
|
|
|
@patch('os.unlink', side_effect=FileNotFoundError('someapp.env'))
|
|
|
|
def test_remove_env_vars_filenotfound(unlink):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.remove_env_vars()
|
|
|
|
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
|
|
|
unlink.assert_called_once_with(env_file)
|
|
|
|
|
|
|
|
@patch('spoc.podman.get_volumes_for_app', return_value={'someapp-vol1', 'someapp-vol2'})
|
|
|
|
def test_get_existing_volumes(get_volume_names):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
volumes = instance.get_existing_volumes()
|
|
|
|
|
|
|
|
get_volume_names.assert_called_once_with('someapp')
|
|
|
|
assert volumes == {'vol1', 'vol2'}
|
|
|
|
|
|
|
|
@patch('spoc.app.App.create_volume')
|
|
|
|
def test_create_volumes(create_volume):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.create_volumes({'vol1', 'vol2'})
|
|
|
|
|
|
|
|
create_volume.assert_has_calls([
|
|
|
|
call('vol1'),
|
|
|
|
call('vol2'),
|
|
|
|
], any_order=True)
|
|
|
|
|
|
|
|
@patch('spoc.app.App.remove_volume')
|
|
|
|
def test_remove_volumes(remove_volume):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.remove_volumes({'vol1', 'vol2'})
|
|
|
|
|
|
|
|
remove_volume.assert_has_calls([
|
|
|
|
call('vol1'),
|
|
|
|
call('vol2'),
|
|
|
|
], any_order=True)
|
|
|
|
|
|
|
|
@patch('spoc.podman.create_volume')
|
|
|
|
def test_create_volume(create_volume):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.create_volume('vol1')
|
|
|
|
|
|
|
|
create_volume.assert_called_once_with('someapp', 'someapp-vol1')
|
|
|
|
|
|
|
|
@patch('spoc.podman.remove_volume')
|
|
|
|
def test_remove_volume(remove_volume):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
instance.remove_volume('vol1')
|
|
|
|
|
|
|
|
remove_volume.assert_called_once_with('someapp-vol1')
|
|
|
|
|
|
|
|
@patch('spoc.app.App.create_container')
|
|
|
|
def test_create_containers(create_container):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
definitions = MOCK_REPODATA['someapp']['containers']
|
|
|
|
instance.create_containers(definitions)
|
|
|
|
|
|
|
|
# Ordered by dependency
|
|
|
|
create_container.assert_has_calls([
|
|
|
|
call('postgres', definitions['postgres'], {'someapp', 'postgres'}),
|
|
|
|
call('someapp', definitions['someapp'], {'someapp', 'postgres'}),
|
|
|
|
])
|
|
|
|
|
|
|
|
@patch('spoc.podman.create_container')
|
|
|
|
def test_create_container(create_container):
|
|
|
|
instance = app.App('someapp')
|
|
|
|
definition = MOCK_REPODATA['someapp']['containers']['someapp']
|
|
|
|
instance.create_container('someapp', definition, {'someapp', 'postgres'})
|
|
|
|
|
|
|
|
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
|
|
|
|
volumes = {'someapp-migrate': '/srv/app/db/migrate',
|
|
|
|
'someapp-storage': '/srv/app/storage',
|
|
|
|
'someapp-uploads': '/srv/app/public/uploads'}
|
|
|
|
create_container.assert_called_once_with('someapp', 'someapp-someapp',
|
|
|
|
'example.com/someapp:0.23.6-210515',
|
|
|
|
env_file=env_file,
|
|
|
|
volumes=volumes,
|
|
|
|
requires={'someapp-postgres'},
|
|
|
|
hosts={'someapp', 'postgres'})
|
|
|
|
|
|
|
|
@patch('spoc.app.App')
|
|
|
|
def test_module_install(instance):
|
|
|
|
app.install('someapp')
|
|
|
|
|
|
|
|
instance.assert_called_once_with('someapp')
|
|
|
|
instance.return_value.install.assert_called_once()
|
|
|
|
|
|
|
|
@patch('spoc.app.App')
|
|
|
|
def test_module_update(instance):
|
|
|
|
app.update('someapp')
|
|
|
|
|
|
|
|
instance.assert_called_once_with('someapp')
|
2021-12-20 22:21:58 +01:00
|
|
|
instance.return_value.update.assert_called_once_with()
|
2021-07-06 18:06:54 +02:00
|
|
|
|
|
|
|
@patch('spoc.app.App')
|
|
|
|
def test_module_uninstall(instance):
|
|
|
|
app.uninstall('someapp')
|
|
|
|
|
|
|
|
instance.assert_called_once_with('someapp')
|
|
|
|
instance.return_value.uninstall.assert_called_once()
|