mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
apache: Add component to host an app on a site's root
Tests: - Unit tests work. - Functional tests on bepasty work. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
0fa1dcf902
commit
d76a371f57
@ -6,5 +6,8 @@ Webserver
|
|||||||
.. autoclass:: plinth.modules.apache.components.Webserver
|
.. autoclass:: plinth.modules.apache.components.Webserver
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: plinth.modules.apache.components.WebserverRoot
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: plinth.modules.apache.components.Uwsgi
|
.. autoclass:: plinth.modules.apache.components.Uwsgi
|
||||||
:members:
|
:members:
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import subprocess
|
|||||||
|
|
||||||
from django.utils.translation import gettext_noop
|
from django.utils.translation import gettext_noop
|
||||||
|
|
||||||
from plinth import action_utils, app
|
from plinth import action_utils, app, kvstore
|
||||||
from plinth.diagnostic_check import (DiagnosticCheck,
|
from plinth.diagnostic_check import (DiagnosticCheck,
|
||||||
DiagnosticCheckParameters, Result)
|
DiagnosticCheckParameters, Result)
|
||||||
from plinth.privileged import service as service_privileged
|
from plinth.privileged import service as service_privileged
|
||||||
@ -17,8 +17,9 @@ from . import privileged
|
|||||||
class Webserver(app.LeaderComponent):
|
class Webserver(app.LeaderComponent):
|
||||||
"""Component to enable/disable Apache configuration."""
|
"""Component to enable/disable Apache configuration."""
|
||||||
|
|
||||||
def __init__(self, component_id, web_name, kind='config', urls=None,
|
def __init__(self, component_id: str, web_name: str, kind: str = 'config',
|
||||||
expect_redirects=False, last_updated_version=None):
|
urls: list[str] | None = None, expect_redirects: bool = False,
|
||||||
|
last_updated_version: int | None = None):
|
||||||
"""Initialize the web server component.
|
"""Initialize the web server component.
|
||||||
|
|
||||||
component_id should be a unique ID across all components of an app and
|
component_id should be a unique ID across all components of an app and
|
||||||
@ -35,6 +36,9 @@ class Webserver(app.LeaderComponent):
|
|||||||
urls is a list of URLs over which a HTTP services will be available due
|
urls is a list of URLs over which a HTTP services will be available due
|
||||||
to this component. This list is only used for running diagnostics.
|
to this component. This list is only used for running diagnostics.
|
||||||
|
|
||||||
|
expect_redirects is a boolean that allows redirects when trying to
|
||||||
|
access the URLs during diagnosis of the component.
|
||||||
|
|
||||||
last_updated_version is the app version in which the web server
|
last_updated_version is the app version in which the web server
|
||||||
configuration/site/module file was updated. Using this, web server will
|
configuration/site/module file was updated. Using this, web server will
|
||||||
be automatically reloaded or restarted as necessary during app upgrade.
|
be automatically reloaded or restarted as necessary during app upgrade.
|
||||||
@ -47,15 +51,15 @@ class Webserver(app.LeaderComponent):
|
|||||||
self.expect_redirects = expect_redirects
|
self.expect_redirects = expect_redirects
|
||||||
self.last_updated_version = last_updated_version or 0
|
self.last_updated_version = last_updated_version or 0
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self) -> bool:
|
||||||
"""Return whether the Apache configuration is enabled."""
|
"""Return whether the Apache configuration is enabled."""
|
||||||
return action_utils.webserver_is_enabled(self.web_name, kind=self.kind)
|
return action_utils.webserver_is_enabled(self.web_name, kind=self.kind)
|
||||||
|
|
||||||
def enable(self):
|
def enable(self) -> None:
|
||||||
"""Enable the Apache configuration."""
|
"""Enable the Apache configuration."""
|
||||||
privileged.enable(self.web_name, self.kind)
|
privileged.enable(self.web_name, self.kind)
|
||||||
|
|
||||||
def disable(self):
|
def disable(self) -> None:
|
||||||
"""Disable the Apache configuration."""
|
"""Disable the Apache configuration."""
|
||||||
privileged.disable(self.web_name, self.kind)
|
privileged.disable(self.web_name, self.kind)
|
||||||
|
|
||||||
@ -63,7 +67,6 @@ class Webserver(app.LeaderComponent):
|
|||||||
"""Check if the web path is accessible by clients.
|
"""Check if the web path is accessible by clients.
|
||||||
|
|
||||||
See :py:meth:`plinth.app.Component.diagnose`.
|
See :py:meth:`plinth.app.Component.diagnose`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
results = []
|
results = []
|
||||||
for url in self.urls:
|
for url in self.urls:
|
||||||
@ -79,7 +82,7 @@ class Webserver(app.LeaderComponent):
|
|||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def setup(self, old_version):
|
def setup(self, old_version: int):
|
||||||
"""Restart/reload web server if configuration files changed."""
|
"""Restart/reload web server if configuration files changed."""
|
||||||
if not old_version:
|
if not old_version:
|
||||||
# App is being freshly setup. After setup, app will be enabled
|
# App is being freshly setup. After setup, app will be enabled
|
||||||
@ -102,10 +105,115 @@ class Webserver(app.LeaderComponent):
|
|||||||
service_privileged.reload('apache2')
|
service_privileged.reload('apache2')
|
||||||
|
|
||||||
|
|
||||||
|
class WebserverRoot(app.FollowerComponent):
|
||||||
|
"""Component to enable/disable Apache configuration for domain root.
|
||||||
|
|
||||||
|
Each domain has a unique virtual host configuration in Apache. This file
|
||||||
|
includes an option configuration file that can dropped in by FreedomBox. If
|
||||||
|
an app wants to be hosted on a dedicated domain, it can provide a
|
||||||
|
configuration file that is meant to be in the <VirtualHost> section. Using
|
||||||
|
this component, the include file fragment for a selected domain can be
|
||||||
|
linked to app's configuration file. Then, for the selected domain, the
|
||||||
|
app's configuration becomes the domain's root configuration.
|
||||||
|
|
||||||
|
This components uses key/value store to remember the selected domain. When
|
||||||
|
the domain changes, the change must be notified using domain_set().
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, component_id: str, web_name: str,
|
||||||
|
expect_redirects: bool = False,
|
||||||
|
last_updated_version: int | None = None):
|
||||||
|
"""Initialize the web server component for domain root.
|
||||||
|
|
||||||
|
component_id should be a unique ID across all components of an app and
|
||||||
|
across all components.
|
||||||
|
|
||||||
|
web_name is the primary part of the configuration file path which must
|
||||||
|
be enabled/disabled by this component. The file's path should be
|
||||||
|
/etc/apache2/includes/<web_name>.conf.
|
||||||
|
|
||||||
|
expect_redirects is a boolean that allows redirects when trying to
|
||||||
|
access the domain URL during diagnosis of the component.
|
||||||
|
|
||||||
|
last_updated_version is the app version in which the web server
|
||||||
|
configuration/site/module file was updated. Using this, web server will
|
||||||
|
be automatically reloaded or restarted as necessary during app upgrade.
|
||||||
|
"""
|
||||||
|
super().__init__(component_id)
|
||||||
|
|
||||||
|
self.web_name = web_name
|
||||||
|
self.expect_redirects = expect_redirects
|
||||||
|
self.last_updated_version = last_updated_version or 0
|
||||||
|
|
||||||
|
def enable(self) -> None:
|
||||||
|
"""Link the Apache site root configuration to app configuration."""
|
||||||
|
domain = self.domain_get()
|
||||||
|
if domain:
|
||||||
|
privileged.link_root(domain, self.web_name)
|
||||||
|
|
||||||
|
def disable(self) -> None:
|
||||||
|
"""Unlink the Apache site root configuration from app configuration."""
|
||||||
|
domain = self.domain_get()
|
||||||
|
if domain:
|
||||||
|
privileged.unlink_root(domain)
|
||||||
|
|
||||||
|
def _key_get(self) -> str:
|
||||||
|
"""Return the key used to store the domain in kvstore."""
|
||||||
|
return f'{self.component_id}_domain'
|
||||||
|
|
||||||
|
def domain_get(self) -> str | None:
|
||||||
|
"""Return the currently configured domain name."""
|
||||||
|
return kvstore.get_default(self._key_get(), None)
|
||||||
|
|
||||||
|
def domain_set(self, domain: str | None):
|
||||||
|
"""Set the domain to use with the app."""
|
||||||
|
self.disable()
|
||||||
|
kvstore.set(self._key_get(), domain)
|
||||||
|
if self.app.is_enabled():
|
||||||
|
self.enable()
|
||||||
|
|
||||||
|
def diagnose(self) -> list[DiagnosticCheck]:
|
||||||
|
"""Check if the site root path is accessible by clients.
|
||||||
|
|
||||||
|
See :py:meth:`plinth.app.Component.diagnose`.
|
||||||
|
"""
|
||||||
|
results = []
|
||||||
|
domain = self.domain_get()
|
||||||
|
if domain:
|
||||||
|
results.append(
|
||||||
|
diagnose_url(f'https://{domain}', check_certificate=False,
|
||||||
|
component_id=self.component_id))
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def setup(self, old_version: int):
|
||||||
|
"""Restart/reload web server if configuration files changed."""
|
||||||
|
if not old_version:
|
||||||
|
# App is being freshly setup. After setup, app will be enabled
|
||||||
|
# which will result in reload/restart of web server.
|
||||||
|
return
|
||||||
|
|
||||||
|
if old_version >= self.last_updated_version:
|
||||||
|
# Already using the latest configuration. Web server reload/restart
|
||||||
|
# is not necessary.
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.app.is_enabled():
|
||||||
|
# App is currently disabled, web server will reloaded/restarted
|
||||||
|
# when the app is enabled.
|
||||||
|
return
|
||||||
|
|
||||||
|
service_privileged.reload('apache2')
|
||||||
|
|
||||||
|
def uninstall(self):
|
||||||
|
"""Remove the domain configured."""
|
||||||
|
kvstore.delete(self._key_get(), ignore_missing=True)
|
||||||
|
|
||||||
|
|
||||||
class Uwsgi(app.LeaderComponent):
|
class Uwsgi(app.LeaderComponent):
|
||||||
"""Component to enable/disable uWSGI configuration."""
|
"""Component to enable/disable uWSGI configuration."""
|
||||||
|
|
||||||
def __init__(self, component_id, uwsgi_name):
|
def __init__(self, component_id: str, uwsgi_name: str):
|
||||||
"""Initialize the uWSGI component.
|
"""Initialize the uWSGI component.
|
||||||
|
|
||||||
component_id should be a unique ID across all components of an app and
|
component_id should be a unique ID across all components of an app and
|
||||||
@ -119,20 +227,20 @@ class Uwsgi(app.LeaderComponent):
|
|||||||
|
|
||||||
self.uwsgi_name = uwsgi_name
|
self.uwsgi_name = uwsgi_name
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self) -> bool:
|
||||||
"""Return whether the uWSGI configuration is enabled."""
|
"""Return whether the uWSGI configuration is enabled."""
|
||||||
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
||||||
and action_utils.service_is_enabled('uwsgi')
|
and action_utils.service_is_enabled('uwsgi')
|
||||||
|
|
||||||
def enable(self):
|
def enable(self) -> None:
|
||||||
"""Enable the uWSGI configuration."""
|
"""Enable the uWSGI configuration."""
|
||||||
privileged.uwsgi_enable(self.uwsgi_name)
|
privileged.uwsgi_enable(self.uwsgi_name)
|
||||||
|
|
||||||
def disable(self):
|
def disable(self) -> None:
|
||||||
"""Disable the uWSGI configuration."""
|
"""Disable the uWSGI configuration."""
|
||||||
privileged.uwsgi_disable(self.uwsgi_name)
|
privileged.uwsgi_disable(self.uwsgi_name)
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self) -> bool:
|
||||||
"""Return whether the uWSGI daemon is running with configuration."""
|
"""Return whether the uWSGI daemon is running with configuration."""
|
||||||
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
||||||
and action_utils.service_is_running('uwsgi')
|
and action_utils.service_is_running('uwsgi')
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
@ -173,6 +174,36 @@ def _assert_kind(kind: str):
|
|||||||
raise ValueError('Invalid value for parameter kind')
|
raise ValueError('Invalid value for parameter kind')
|
||||||
|
|
||||||
|
|
||||||
|
@privileged
|
||||||
|
def link_root(domain: str, name: str):
|
||||||
|
"""Link the Apache site root configuration to app configuration."""
|
||||||
|
if '/' in domain or '/' in name:
|
||||||
|
raise ValueError('Invalid domain or name')
|
||||||
|
|
||||||
|
target_config = f'{name}.conf'
|
||||||
|
|
||||||
|
include_root = pathlib.Path('/etc/apache2/includes/')
|
||||||
|
config = include_root / f'{domain}-include-freedombox.conf'
|
||||||
|
config.unlink(missing_ok=True)
|
||||||
|
config.symlink_to(target_config)
|
||||||
|
action_utils.service_reload('apache2')
|
||||||
|
|
||||||
|
|
||||||
|
@privileged
|
||||||
|
def unlink_root(domain: str):
|
||||||
|
"""Unlink the Apache site root configuration from app configuration."""
|
||||||
|
if '/' in domain:
|
||||||
|
raise ValueError('Invalid domain')
|
||||||
|
|
||||||
|
include_root = pathlib.Path('/etc/apache2/includes/')
|
||||||
|
config = include_root / f'{domain}-include-freedombox.conf'
|
||||||
|
if not config.is_symlink():
|
||||||
|
return # Does not exist or not a symlink
|
||||||
|
|
||||||
|
config.unlink()
|
||||||
|
action_utils.service_reload('apache2')
|
||||||
|
|
||||||
|
|
||||||
@privileged
|
@privileged
|
||||||
def uwsgi_enable(name: str):
|
def uwsgi_enable(name: str):
|
||||||
"""Enable uWSGI configuration and reload."""
|
"""Enable uWSGI configuration and reload."""
|
||||||
|
|||||||
@ -4,14 +4,14 @@ Test module for webserver components.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from unittest.mock import call, patch
|
from unittest.mock import Mock, PropertyMock, call, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from plinth import app
|
from plinth import app, kvstore
|
||||||
from plinth.diagnostic_check import DiagnosticCheck, Result
|
from plinth.diagnostic_check import DiagnosticCheck, Result
|
||||||
from plinth.modules.apache.components import (Uwsgi, Webserver, check_url,
|
from plinth.modules.apache.components import (Uwsgi, Webserver, WebserverRoot,
|
||||||
diagnose_url,
|
check_url, diagnose_url,
|
||||||
diagnose_url_on_all)
|
diagnose_url_on_all)
|
||||||
|
|
||||||
|
|
||||||
@ -164,6 +164,168 @@ def test_webserver_setup(service_reload, service_restart):
|
|||||||
service_reload.assert_not_called()
|
service_reload.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_webserver_root_init():
|
||||||
|
"""Test that webserver root component can be initialized."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
WebserverRoot(None, None)
|
||||||
|
|
||||||
|
webserver = WebserverRoot('test-webserverroot', 'test-config',
|
||||||
|
expect_redirects=True, last_updated_version=10)
|
||||||
|
assert webserver.component_id == 'test-webserverroot'
|
||||||
|
assert webserver.web_name == 'test-config'
|
||||||
|
assert webserver.expect_redirects
|
||||||
|
assert webserver.last_updated_version == 10
|
||||||
|
|
||||||
|
webserver = WebserverRoot('test-webserverroot', None)
|
||||||
|
assert not webserver.expect_redirects
|
||||||
|
assert webserver.last_updated_version == 0
|
||||||
|
|
||||||
|
|
||||||
|
@patch('plinth.modules.apache.privileged.link_root')
|
||||||
|
def test_webserver_root_enable(link_root):
|
||||||
|
"""Test that enabling webserver root works."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
|
||||||
|
with patch('plinth.modules.apache.components.WebserverRoot.domain_get'
|
||||||
|
) as get:
|
||||||
|
get.return_value = None
|
||||||
|
webserver.enable()
|
||||||
|
link_root.assert_not_called()
|
||||||
|
|
||||||
|
get.return_value = 'x-domain'
|
||||||
|
webserver.enable()
|
||||||
|
link_root.assert_has_calls([call('x-domain', 'test-config')])
|
||||||
|
|
||||||
|
|
||||||
|
@patch('plinth.modules.apache.privileged.unlink_root')
|
||||||
|
def test_webserver_root_disable(unlink_root):
|
||||||
|
"""Test that disabling webserver root works."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
|
||||||
|
with patch('plinth.modules.apache.components.WebserverRoot.domain_get'
|
||||||
|
) as get:
|
||||||
|
get.return_value = None
|
||||||
|
webserver.disable()
|
||||||
|
unlink_root.assert_not_called()
|
||||||
|
|
||||||
|
get.return_value = 'x-domain'
|
||||||
|
webserver.disable()
|
||||||
|
unlink_root.assert_has_calls([call('x-domain')])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_webserver_root_domain_get():
|
||||||
|
"""Test retrieving webserver root's domain."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
|
||||||
|
assert webserver.domain_get() is None
|
||||||
|
kvstore.set('test-webserver_domain', 'test-domain')
|
||||||
|
assert webserver.domain_get() == 'test-domain'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@patch('plinth.modules.apache.privileged.unlink_root')
|
||||||
|
@patch('plinth.modules.apache.privileged.link_root')
|
||||||
|
@patch('plinth.app.Component.app', new_callable=PropertyMock)
|
||||||
|
def test_webserver_root_domain_set(component_app, link_root, unlink_root):
|
||||||
|
"""Test setting webserver root's domain."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
assert webserver.domain_get() is None
|
||||||
|
|
||||||
|
app = Mock()
|
||||||
|
component_app.return_value = app
|
||||||
|
app.is_enabled.return_value = True
|
||||||
|
webserver.domain_set('test-domain')
|
||||||
|
assert unlink_root.mock_calls == []
|
||||||
|
assert webserver.domain_get() == 'test-domain'
|
||||||
|
assert link_root.mock_calls == [call('test-domain', 'test-config')]
|
||||||
|
link_root.reset_mock()
|
||||||
|
|
||||||
|
app.is_enabled.return_value = False
|
||||||
|
assert not webserver.app.is_enabled()
|
||||||
|
webserver.domain_set('test-domain2')
|
||||||
|
assert unlink_root.mock_calls == [call('test-domain')]
|
||||||
|
assert webserver.domain_get() == 'test-domain2'
|
||||||
|
assert link_root.mock_calls == []
|
||||||
|
|
||||||
|
webserver.domain_set(None)
|
||||||
|
assert webserver.domain_get() is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@patch('plinth.modules.apache.components.WebserverRoot.disable')
|
||||||
|
@patch('plinth.modules.apache.components.WebserverRoot.enable')
|
||||||
|
@patch('plinth.modules.apache.components.diagnose_url')
|
||||||
|
@patch('plinth.app.Component.app', new_callable=PropertyMock)
|
||||||
|
def test_webserver_root_diagnose(component_app, diagnose_url, enable, disable):
|
||||||
|
"""Test running diagnostics on webserver root component."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
assert webserver.diagnose() == []
|
||||||
|
|
||||||
|
webserver.domain_set('test-domain')
|
||||||
|
result = DiagnosticCheck('test-all-id', 'test-result', 'success', {},
|
||||||
|
'message')
|
||||||
|
diagnose_url.return_value = result
|
||||||
|
assert webserver.diagnose() == [result]
|
||||||
|
|
||||||
|
|
||||||
|
@patch('plinth.privileged.service.reload')
|
||||||
|
def test_webserver_root_setup(service_reload):
|
||||||
|
"""Test that component reloads web server during app upgrades."""
|
||||||
|
|
||||||
|
class AppTest(app.App):
|
||||||
|
app_id = 'testapp'
|
||||||
|
enabled = False
|
||||||
|
|
||||||
|
def is_enabled(self):
|
||||||
|
return self.enabled
|
||||||
|
|
||||||
|
app1 = AppTest()
|
||||||
|
|
||||||
|
# Don't fail when last_updated_version is not provided.
|
||||||
|
webserver1 = WebserverRoot('test-webserverroot1', 'test-config')
|
||||||
|
assert webserver1.last_updated_version == 0
|
||||||
|
webserver1.setup(old_version=10)
|
||||||
|
service_reload.assert_not_called()
|
||||||
|
|
||||||
|
webserver1 = WebserverRoot('test-webserverroot1', 'test-config',
|
||||||
|
last_updated_version=5)
|
||||||
|
for version in (0, 5, 6):
|
||||||
|
webserver1.setup(old_version=version)
|
||||||
|
service_reload.assert_not_called()
|
||||||
|
|
||||||
|
app1.enabled = False
|
||||||
|
webserver2 = WebserverRoot('test-webserver2', 'test-config',
|
||||||
|
last_updated_version=5)
|
||||||
|
app1.add(webserver2)
|
||||||
|
webserver2.setup(old_version=3)
|
||||||
|
service_reload.assert_not_called()
|
||||||
|
|
||||||
|
app1.enabled = True
|
||||||
|
webserver3 = WebserverRoot('test-webserver3', 'test-config',
|
||||||
|
last_updated_version=5)
|
||||||
|
app1.add(webserver3)
|
||||||
|
webserver3.setup(old_version=3)
|
||||||
|
service_reload.assert_has_calls([call('apache2')])
|
||||||
|
service_reload.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@patch('plinth.modules.apache.components.WebserverRoot.disable')
|
||||||
|
@patch('plinth.modules.apache.components.WebserverRoot.enable')
|
||||||
|
@patch('plinth.app.Component.app', new_callable=PropertyMock)
|
||||||
|
def test_webserver_root_uninstall(component_app, enable, disable):
|
||||||
|
"""Test that component removes the DB key during uninstall."""
|
||||||
|
webserver = WebserverRoot('test-webserver', 'test-config')
|
||||||
|
webserver.uninstall()
|
||||||
|
assert kvstore.get_default('test-webserver_domain', 'x-value') == 'x-value'
|
||||||
|
|
||||||
|
webserver.domain_set('test-domain')
|
||||||
|
assert kvstore.get('test-webserver_domain') == 'test-domain'
|
||||||
|
webserver.uninstall()
|
||||||
|
assert kvstore.get_default('test-webserver_domain', 'x-value') == 'x-value'
|
||||||
|
|
||||||
|
|
||||||
def test_uwsgi_init():
|
def test_uwsgi_init():
|
||||||
"""Test that uWSGI component can be initialized."""
|
"""Test that uWSGI component can be initialized."""
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user