mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-13 04:06:33 +00:00
Add API option to disable fallback DNS (#3586)
* Add API option to disable fallback DNS * DNS unsupported evaluation and fallback in sentry
This commit is contained in:
parent
0440437369
commit
8bb4596d04
@ -10,6 +10,7 @@ ATTR_DATA_DISK = "data_disk"
|
|||||||
ATTR_DEVICE = "device"
|
ATTR_DEVICE = "device"
|
||||||
ATTR_DT_SYNCHRONIZED = "dt_synchronized"
|
ATTR_DT_SYNCHRONIZED = "dt_synchronized"
|
||||||
ATTR_DT_UTC = "dt_utc"
|
ATTR_DT_UTC = "dt_utc"
|
||||||
|
ATTR_FALLBACK = "fallback"
|
||||||
ATTR_LLMNR = "llmnr"
|
ATTR_LLMNR = "llmnr"
|
||||||
ATTR_LLMNR_HOSTNAME = "llmnr_hostname"
|
ATTR_LLMNR_HOSTNAME = "llmnr_hostname"
|
||||||
ATTR_MDNS = "mdns"
|
ATTR_MDNS = "mdns"
|
||||||
|
@ -26,13 +26,18 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..validate import dns_server_list, version_tag
|
from ..validate import dns_server_list, version_tag
|
||||||
from .const import ATTR_LLMNR, ATTR_MDNS
|
from .const import ATTR_FALLBACK, ATTR_LLMNR, ATTR_MDNS
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_SERVERS): dns_server_list})
|
SCHEMA_OPTIONS = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional(ATTR_SERVERS): dns_server_list,
|
||||||
|
vol.Optional(ATTR_FALLBACK): vol.Boolean(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
|
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
|
||||||
|
|
||||||
@ -52,15 +57,24 @@ class APICoreDNS(CoreSysAttributes):
|
|||||||
ATTR_LOCALS: self.sys_plugins.dns.locals,
|
ATTR_LOCALS: self.sys_plugins.dns.locals,
|
||||||
ATTR_MDNS: self.sys_plugins.dns.mdns,
|
ATTR_MDNS: self.sys_plugins.dns.mdns,
|
||||||
ATTR_LLMNR: self.sys_plugins.dns.llmnr,
|
ATTR_LLMNR: self.sys_plugins.dns.llmnr,
|
||||||
|
ATTR_FALLBACK: self.sys_plugins.dns.fallback,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def options(self, request: web.Request) -> None:
|
async def options(self, request: web.Request) -> None:
|
||||||
"""Set DNS options."""
|
"""Set DNS options."""
|
||||||
body = await api_validate(SCHEMA_OPTIONS, request)
|
body = await api_validate(SCHEMA_OPTIONS, request)
|
||||||
|
restart_required = False
|
||||||
|
|
||||||
if ATTR_SERVERS in body:
|
if ATTR_SERVERS in body:
|
||||||
self.sys_plugins.dns.servers = body[ATTR_SERVERS]
|
self.sys_plugins.dns.servers = body[ATTR_SERVERS]
|
||||||
|
restart_required = True
|
||||||
|
|
||||||
|
if ATTR_FALLBACK in body:
|
||||||
|
self.sys_plugins.dns.fallback = body[ATTR_FALLBACK]
|
||||||
|
restart_required = True
|
||||||
|
|
||||||
|
if restart_required:
|
||||||
self.sys_create_task(self.sys_plugins.dns.restart())
|
self.sys_create_task(self.sys_plugins.dns.restart())
|
||||||
|
|
||||||
self.sys_plugins.dns.save_data()
|
self.sys_plugins.dns.save_data()
|
||||||
|
@ -79,6 +79,9 @@ def filter_data(coresys: CoreSys, event: dict, hint: dict) -> dict:
|
|||||||
],
|
],
|
||||||
"unhealthy": coresys.resolution.unhealthy,
|
"unhealthy": coresys.resolution.unhealthy,
|
||||||
},
|
},
|
||||||
|
"misc": {
|
||||||
|
"fallback_dns": coresys.plugins.dns.fallback,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,3 +8,5 @@ FILE_HASSIO_CLI = Path(SUPERVISOR_DATA, "cli.json")
|
|||||||
FILE_HASSIO_DNS = Path(SUPERVISOR_DATA, "dns.json")
|
FILE_HASSIO_DNS = Path(SUPERVISOR_DATA, "dns.json")
|
||||||
FILE_HASSIO_OBSERVER = Path(SUPERVISOR_DATA, "observer.json")
|
FILE_HASSIO_OBSERVER = Path(SUPERVISOR_DATA, "observer.json")
|
||||||
FILE_HASSIO_MULTICAST = Path(SUPERVISOR_DATA, "multicast.json")
|
FILE_HASSIO_MULTICAST = Path(SUPERVISOR_DATA, "multicast.json")
|
||||||
|
|
||||||
|
ATTR_FALLBACK = "fallback"
|
||||||
|
@ -30,7 +30,7 @@ from ..resolution.const import ContextType, IssueType, SuggestionType
|
|||||||
from ..utils.json import write_json_file
|
from ..utils.json import write_json_file
|
||||||
from ..validate import dns_url
|
from ..validate import dns_url
|
||||||
from .base import PluginBase
|
from .base import PluginBase
|
||||||
from .const import FILE_HASSIO_DNS
|
from .const import ATTR_FALLBACK, FILE_HASSIO_DNS
|
||||||
from .validate import SCHEMA_DNS_CONFIG
|
from .validate import SCHEMA_DNS_CONFIG
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -116,6 +116,16 @@ class PluginDns(PluginBase):
|
|||||||
MulticastProtocolEnabled.RESOLVE,
|
MulticastProtocolEnabled.RESOLVE,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fallback(self) -> bool:
|
||||||
|
"""Fallback DNS enabled."""
|
||||||
|
return self._data[ATTR_FALLBACK]
|
||||||
|
|
||||||
|
@fallback.setter
|
||||||
|
def fallback(self, value: bool) -> None:
|
||||||
|
"""Set fallback DNS enabled."""
|
||||||
|
self._data[ATTR_FALLBACK] = value
|
||||||
|
|
||||||
async def load(self) -> None:
|
async def load(self) -> None:
|
||||||
"""Load DNS setup."""
|
"""Load DNS setup."""
|
||||||
# Initialize CoreDNS Template
|
# Initialize CoreDNS Template
|
||||||
@ -241,6 +251,7 @@ class PluginDns(PluginBase):
|
|||||||
"""Reset DNS and hosts."""
|
"""Reset DNS and hosts."""
|
||||||
# Reset manually defined DNS
|
# Reset manually defined DNS
|
||||||
self.servers.clear()
|
self.servers.clear()
|
||||||
|
self.fallback = True
|
||||||
self.save_data()
|
self.save_data()
|
||||||
|
|
||||||
# Resets hosts
|
# Resets hosts
|
||||||
@ -285,9 +296,10 @@ class PluginDns(PluginBase):
|
|||||||
|
|
||||||
# Print some usefully debug data
|
# Print some usefully debug data
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"config-dns = %s, local-dns = %s , backup-dns = CloudFlare DoT / debug: %s",
|
"config-dns = %s, local-dns = %s , backup-dns = %s / debug: %s",
|
||||||
dns_servers,
|
dns_servers,
|
||||||
dns_locals,
|
dns_locals,
|
||||||
|
"CloudFlare DoT" if self.fallback else "DISABLED",
|
||||||
debug,
|
debug,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -298,6 +310,7 @@ class PluginDns(PluginBase):
|
|||||||
{
|
{
|
||||||
"servers": dns_servers,
|
"servers": dns_servers,
|
||||||
"locals": dns_locals,
|
"locals": dns_locals,
|
||||||
|
"fallback": self.fallback,
|
||||||
"debug": debug,
|
"debug": debug,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -2,14 +2,18 @@
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from supervisor.plugins.const import ATTR_FALLBACK
|
||||||
|
|
||||||
from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_SERVERS, ATTR_VERSION
|
from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_SERVERS, ATTR_VERSION
|
||||||
from ..validate import dns_server_list, docker_image, token, version_tag
|
from ..validate import dns_server_list, docker_image, token, version_tag
|
||||||
|
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_DNS_CONFIG = vol.Schema(
|
SCHEMA_DNS_CONFIG = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(ATTR_VERSION): version_tag,
|
vol.Optional(ATTR_VERSION): version_tag,
|
||||||
vol.Optional(ATTR_IMAGE): docker_image,
|
vol.Optional(ATTR_IMAGE): docker_image,
|
||||||
vol.Optional(ATTR_SERVERS, default=list): dns_server_list,
|
vol.Optional(ATTR_SERVERS, default=list): dns_server_list,
|
||||||
|
vol.Optional(ATTR_FALLBACK, default=True): vol.Boolean(),
|
||||||
},
|
},
|
||||||
extra=vol.REMOVE_EXTRA,
|
extra=vol.REMOVE_EXTRA,
|
||||||
)
|
)
|
||||||
|
@ -34,6 +34,7 @@ class UnsupportedReason(str, Enum):
|
|||||||
APPARMOR = "apparmor"
|
APPARMOR = "apparmor"
|
||||||
CONTENT_TRUST = "content_trust"
|
CONTENT_TRUST = "content_trust"
|
||||||
DBUS = "dbus"
|
DBUS = "dbus"
|
||||||
|
DNS_SERVER = "dns_server"
|
||||||
DOCKER_CONFIGURATION = "docker_configuration"
|
DOCKER_CONFIGURATION = "docker_configuration"
|
||||||
DOCKER_VERSION = "docker_version"
|
DOCKER_VERSION = "docker_version"
|
||||||
JOB_CONDITIONS = "job_conditions"
|
JOB_CONDITIONS = "job_conditions"
|
||||||
|
40
supervisor/resolution/evaluations/dns_server.py
Normal file
40
supervisor/resolution/evaluations/dns_server.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
"""Evaluation class for DNS server."""
|
||||||
|
|
||||||
|
from ...const import CoreState
|
||||||
|
from ...coresys import CoreSys
|
||||||
|
from ..const import ContextType, UnsupportedReason
|
||||||
|
from .base import EvaluateBase
|
||||||
|
|
||||||
|
|
||||||
|
def setup(coresys: CoreSys) -> EvaluateBase:
|
||||||
|
"""Initialize evaluation-setup function."""
|
||||||
|
return EvaluateDNSServer(coresys)
|
||||||
|
|
||||||
|
|
||||||
|
class EvaluateDNSServer(EvaluateBase):
|
||||||
|
"""Evaluate job conditions."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reason(self) -> UnsupportedReason:
|
||||||
|
"""Return a UnsupportedReason enum."""
|
||||||
|
return UnsupportedReason.DNS_SERVER
|
||||||
|
|
||||||
|
@property
|
||||||
|
def on_failure(self) -> str:
|
||||||
|
"""Return a string that is printed when self.evaluate is False."""
|
||||||
|
return "Found unsupported DNS server and fallback is disabled."
|
||||||
|
|
||||||
|
@property
|
||||||
|
def states(self) -> list[CoreState]:
|
||||||
|
"""Return a list of valid states when this evaluation can run."""
|
||||||
|
return [CoreState.RUNNING]
|
||||||
|
|
||||||
|
async def evaluate(self) -> None:
|
||||||
|
"""Run evaluation."""
|
||||||
|
return not self.sys_plugins.dns.fallback and 0 < len(
|
||||||
|
[
|
||||||
|
issue
|
||||||
|
for issue in self.sys_resolution.issues
|
||||||
|
if issue.context == ContextType.DNS_SERVER
|
||||||
|
]
|
||||||
|
)
|
@ -36,3 +36,25 @@ async def test_llmnr_mdns_info(api_client, coresys: CoreSys):
|
|||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
assert result["data"]["llmnr"] is True
|
assert result["data"]["llmnr"] is True
|
||||||
assert result["data"]["mdns"] is True
|
assert result["data"]["mdns"] is True
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options(api_client, coresys: CoreSys):
|
||||||
|
"""Test options api."""
|
||||||
|
assert coresys.plugins.dns.servers == []
|
||||||
|
assert coresys.plugins.dns.fallback is True
|
||||||
|
|
||||||
|
with patch.object(type(coresys.plugins.dns), "restart") as restart:
|
||||||
|
await api_client.post(
|
||||||
|
"/dns/options", json={"servers": ["dns://8.8.8.8"], "fallback": False}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert coresys.plugins.dns.servers == ["dns://8.8.8.8"]
|
||||||
|
assert coresys.plugins.dns.fallback is False
|
||||||
|
restart.assert_called_once()
|
||||||
|
|
||||||
|
restart.reset_mock()
|
||||||
|
await api_client.post("/dns/options", json={"fallback": True})
|
||||||
|
|
||||||
|
assert coresys.plugins.dns.servers == ["dns://8.8.8.8"]
|
||||||
|
assert coresys.plugins.dns.fallback is True
|
||||||
|
restart.assert_called_once()
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
"""Test DNS plugin."""
|
"""Test DNS plugin."""
|
||||||
|
from ipaddress import IPv4Address
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import AsyncMock, Mock, patch
|
from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from supervisor.const import LogLevel
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.docker.interface import DockerInterface
|
from supervisor.docker.interface import DockerInterface
|
||||||
|
from supervisor.plugins.dns import HostEntry
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="docker_interface")
|
@pytest.fixture(name="docker_interface")
|
||||||
async def fixture_docker_interface() -> tuple[AsyncMock, AsyncMock]:
|
async def fixture_docker_interface() -> tuple[AsyncMock, AsyncMock]:
|
||||||
"""Mock docker interface methods."""
|
"""Mock docker interface methods."""
|
||||||
# with patch("supervisor.docker.interface.DockerInterface.run"), patch("supervisor.docker.interface.DockerInterface.restart")
|
|
||||||
with patch.object(DockerInterface, "run") as run, patch.object(
|
with patch.object(DockerInterface, "run") as run, patch.object(
|
||||||
DockerInterface, "restart"
|
DockerInterface, "restart"
|
||||||
) as restart:
|
) as restart:
|
||||||
@ -25,31 +27,98 @@ async def fixture_write_json() -> Mock:
|
|||||||
yield write_json_file
|
yield write_json_file
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("start", [True, False])
|
|
||||||
async def test_config_write(
|
async def test_config_write(
|
||||||
coresys: CoreSys,
|
coresys: CoreSys,
|
||||||
docker_interface: tuple[AsyncMock, AsyncMock],
|
docker_interface: tuple[AsyncMock, AsyncMock],
|
||||||
write_json: Mock,
|
write_json: Mock,
|
||||||
start: bool,
|
|
||||||
):
|
):
|
||||||
"""Test config write on DNS start and restart."""
|
"""Test config write on DNS start and restart."""
|
||||||
assert coresys.plugins.dns.locals == ["dns://192.168.30.1"]
|
assert coresys.plugins.dns.locals == ["dns://192.168.30.1"]
|
||||||
coresys.plugins.dns.servers = ["dns://1.1.1.1", "dns://8.8.8.8"]
|
coresys.plugins.dns.servers = ["dns://1.1.1.1", "dns://8.8.8.8"]
|
||||||
|
|
||||||
if start:
|
await coresys.plugins.dns.start()
|
||||||
await coresys.plugins.dns.start()
|
docker_interface[0].assert_called_once()
|
||||||
docker_interface[0].assert_called_once()
|
docker_interface[1].assert_not_called()
|
||||||
docker_interface[1].assert_not_called()
|
|
||||||
else:
|
|
||||||
await coresys.plugins.dns.restart()
|
|
||||||
docker_interface[0].assert_not_called()
|
|
||||||
docker_interface[1].assert_called_once()
|
|
||||||
|
|
||||||
write_json.assert_called_once_with(
|
write_json.assert_called_once_with(
|
||||||
Path("/data/dns/coredns.json"),
|
Path("/data/dns/coredns.json"),
|
||||||
{
|
{
|
||||||
"servers": ["dns://1.1.1.1", "dns://8.8.8.8"],
|
"servers": ["dns://1.1.1.1", "dns://8.8.8.8"],
|
||||||
"locals": ["dns://192.168.30.1"],
|
"locals": ["dns://192.168.30.1"],
|
||||||
|
"fallback": True,
|
||||||
"debug": False,
|
"debug": False,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
docker_interface[0].reset_mock()
|
||||||
|
write_json.reset_mock()
|
||||||
|
coresys.plugins.dns.servers = ["dns://8.8.8.8"]
|
||||||
|
coresys.plugins.dns.fallback = False
|
||||||
|
coresys.config.logging = LogLevel.DEBUG
|
||||||
|
|
||||||
|
await coresys.plugins.dns.restart()
|
||||||
|
docker_interface[0].assert_not_called()
|
||||||
|
docker_interface[1].assert_called_once()
|
||||||
|
|
||||||
|
write_json.assert_called_once_with(
|
||||||
|
Path("/data/dns/coredns.json"),
|
||||||
|
{
|
||||||
|
"servers": ["dns://8.8.8.8"],
|
||||||
|
"locals": ["dns://192.168.30.1"],
|
||||||
|
"fallback": False,
|
||||||
|
"debug": True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reset(coresys: CoreSys):
|
||||||
|
"""Test reset returns dns plugin to defaults."""
|
||||||
|
coresys.plugins.dns.servers = ["dns://1.1.1.1", "dns://8.8.8.8"]
|
||||||
|
coresys.plugins.dns.fallback = False
|
||||||
|
coresys.plugins.dns._loop = True # pylint: disable=protected-access
|
||||||
|
assert len(coresys.addons.installed) == 0
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
type(coresys.plugins.dns.hosts), "unlink"
|
||||||
|
) as unlink, patch.object(type(coresys.plugins.dns), "write_hosts") as write_hosts:
|
||||||
|
await coresys.plugins.dns.reset()
|
||||||
|
|
||||||
|
assert coresys.plugins.dns.servers == []
|
||||||
|
assert coresys.plugins.dns.fallback is True
|
||||||
|
assert coresys.plugins.dns._loop is False # pylint: disable=protected-access
|
||||||
|
unlink.assert_called_once()
|
||||||
|
write_hosts.assert_called_once()
|
||||||
|
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
assert coresys.plugins.dns._hosts == [
|
||||||
|
HostEntry(
|
||||||
|
ip_address=IPv4Address("127.0.0.1"),
|
||||||
|
names=["localhost", "localhost.local.hass.io"],
|
||||||
|
),
|
||||||
|
HostEntry(
|
||||||
|
ip_address=IPv4Address("172.30.32.2"),
|
||||||
|
names=[
|
||||||
|
"hassio",
|
||||||
|
"hassio.local.hass.io",
|
||||||
|
"supervisor",
|
||||||
|
"supervisor.local.hass.io",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
HostEntry(
|
||||||
|
ip_address=IPv4Address("172.30.32.1"),
|
||||||
|
names=[
|
||||||
|
"homeassistant",
|
||||||
|
"homeassistant.local.hass.io",
|
||||||
|
"home-assistant",
|
||||||
|
"home-assistant.local.hass.io",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
HostEntry(
|
||||||
|
ip_address=IPv4Address("172.30.32.3"),
|
||||||
|
names=["dns", "dns.local.hass.io"],
|
||||||
|
),
|
||||||
|
HostEntry(
|
||||||
|
ip_address=IPv4Address("172.30.32.6"),
|
||||||
|
names=["observer", "observer.local.hass.io"],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
59
tests/resolution/evaluation/test_evaluate_dns_server.py
Normal file
59
tests/resolution/evaluation/test_evaluate_dns_server.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""Test DNS server evaluation."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from supervisor.const import CoreState
|
||||||
|
from supervisor.coresys import CoreSys
|
||||||
|
from supervisor.resolution.const import ContextType, IssueType
|
||||||
|
from supervisor.resolution.evaluations.dns_server import EvaluateDNSServer
|
||||||
|
|
||||||
|
|
||||||
|
async def test_evaluation(coresys: CoreSys):
|
||||||
|
"""Test evaluation."""
|
||||||
|
dns_server = EvaluateDNSServer(coresys)
|
||||||
|
coresys.core.state = CoreState.RUNNING
|
||||||
|
|
||||||
|
assert dns_server.reason not in coresys.resolution.unsupported
|
||||||
|
assert coresys.plugins.dns.fallback is True
|
||||||
|
assert len(coresys.resolution.issues) == 0
|
||||||
|
|
||||||
|
await dns_server()
|
||||||
|
assert dns_server.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
coresys.plugins.dns.fallback = False
|
||||||
|
await dns_server()
|
||||||
|
assert dns_server.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
coresys.plugins.dns.fallback = True
|
||||||
|
coresys.resolution.create_issue(
|
||||||
|
IssueType.DNS_SERVER_FAILED,
|
||||||
|
ContextType.DNS_SERVER,
|
||||||
|
reference="dns://192.168.30.1",
|
||||||
|
)
|
||||||
|
await dns_server()
|
||||||
|
assert dns_server.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
coresys.plugins.dns.fallback = False
|
||||||
|
await dns_server()
|
||||||
|
assert dns_server.reason in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
|
||||||
|
async def test_did_run(coresys: CoreSys):
|
||||||
|
"""Test that the evaluation ran as expected."""
|
||||||
|
dns_server = EvaluateDNSServer(coresys)
|
||||||
|
should_run = [CoreState.RUNNING]
|
||||||
|
should_not_run = [state for state in CoreState if state not in should_run]
|
||||||
|
assert len(should_run) != 0
|
||||||
|
assert len(should_not_run) != 0
|
||||||
|
|
||||||
|
with patch.object(EvaluateDNSServer, "evaluate", return_value=None) as evaluate:
|
||||||
|
for state in should_run:
|
||||||
|
coresys.core.state = state
|
||||||
|
await dns_server()
|
||||||
|
evaluate.assert_called_once()
|
||||||
|
evaluate.reset_mock()
|
||||||
|
|
||||||
|
for state in should_not_run:
|
||||||
|
coresys.core.state = state
|
||||||
|
await dns_server()
|
||||||
|
evaluate.assert_not_called()
|
||||||
|
evaluate.reset_mock()
|
Loading…
x
Reference in New Issue
Block a user