spoc/tests/test_app.py

247 lines
9.0 KiB
Python

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')
with open(os.path.join(TEST_DATA_DIR, 'repository.json'), encoding='utf-8') as f:
MOCK_REPODATA = json.load(f)
MOCK_ENV = 'RAILS_ENV=test\n' \
'POSTGRES_PASSWORD=asdf=1234\n' \
'SOMEKEY=someval\n'
MOCK_ENV_DATA = {
'RAILS_ENV': 'test',
'POSTGRES_PASSWORD': 'asdf=1234',
'SOMEKEY': 'someval',
}
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')
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):
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')
@patch('spoc.app.App.read_env_vars', return_value=MOCK_ENV_DATA)
@patch('spoc.app.App.write_env_vars')
@patch('spoc.app.App.create_pod')
@patch('spoc.app.App.create_containers')
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):
instance = app.App('someapp')
instance.update()
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()
expected_env_data.update(MOCK_ENV_DATA)
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'])
@patch('spoc.autostart.set_app')
@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')
def test_uninstall(remove_volumes, get_existing_volumes, remove_env_vars, remove_pod, autostart):
instance = app.App('someapp')
instance.uninstall()
autostart.assert_called_with('someapp', False)
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')
env_open.assert_called_once_with(env_file, encoding='utf-8')
assert env_vars == MOCK_ENV_DATA
@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')
env_open.assert_called_once_with(env_file, encoding='utf-8')
assert not env_vars
@patch('os.makedirs')
@patch('builtins.open', new_callable=mock_open)
def test_write_env_vars(env_open, makedirs):
instance = app.App('someapp')
instance.write_env_vars(MOCK_ENV_DATA)
makedirs.assert_called_once_with(config.DATA_DIR, exist_ok=True)
env_file = os.path.join(config.DATA_DIR, 'someapp.env')
env_open.assert_called_once_with(env_file, 'w', encoding='utf-8')
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')
instance.return_value.update.assert_called_once_with()
@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()