Addons can access systemd journal logs (#2722)

* Added journald access to addons

* Name change to journald and added tests
This commit is contained in:
mdegat01 2021-03-17 07:26:23 -04:00 committed by GitHub
parent 9e1f899274
commit 667672a20b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 0 deletions

View File

@ -32,6 +32,7 @@ from ..const import (
ATTR_IMAGE,
ATTR_INGRESS,
ATTR_INIT,
ATTR_JOURNALD,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
@ -550,6 +551,11 @@ class AddonModel(CoreSysAttributes, ABC):
return None
return UiOptions(self.coresys)(raw_schema)
@property
def with_journald(self) -> bool:
"""Return True if the add-on accesses the system journal."""
return self.data[ATTR_JOURNALD]
def __eq__(self, other):
"""Compaired add-on objects."""
if not isinstance(other, AddonModel):

View File

@ -45,6 +45,7 @@ from ..const import (
ATTR_INGRESS_PORT,
ATTR_INGRESS_TOKEN,
ATTR_INIT,
ATTR_JOURNALD,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
@ -299,6 +300,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_TIMEOUT, default=10): vol.All(
vol.Coerce(int), vol.Range(min=10, max=300)
),
vol.Optional(ATTR_JOURNALD, default=False): vol.Boolean(),
},
extra=vol.REMOVE_EXTRA,
)

View File

@ -27,6 +27,7 @@ MACHINE_ID = Path("/etc/machine-id")
SOCKET_DBUS = Path("/run/dbus/system_bus_socket")
SOCKET_DOCKER = Path("/run/docker.sock")
RUN_SUPERVISOR_STATE = Path("/run/supervisor")
SYSTEMD_JOURNAL = Path("/var/logs/journal")
DOCKER_NETWORK = "hassio"
DOCKER_NETWORK_MASK = ip_network("172.30.32.0/23")
@ -279,6 +280,7 @@ ATTR_SUPERVISOR_INTERNET = "supervisor_internet"
ATTR_SUPPORTED = "supported"
ATTR_SUPPORTED_ARCH = "supported_arch"
ATTR_SYSTEM = "system"
ATTR_JOURNALD = "journald"
ATTR_TIMEOUT = "timeout"
ATTR_TIMEZONE = "timezone"
ATTR_TITLE = "title"

View File

@ -26,6 +26,7 @@ from ..const import (
MAP_SSL,
SECURITY_DISABLE,
SECURITY_PROFILE,
SYSTEMD_JOURNAL,
)
from ..coresys import CoreSys
from ..exceptions import CoreDNSError, DockerError, DockerNotFound, HardwareNotFound
@ -413,6 +414,17 @@ class DockerAddon(DockerInterface):
}
)
# System Journal access
if self.addon.with_journald:
volumes.update(
{
str(SYSTEMD_JOURNAL): {
"bind": str(SYSTEMD_JOURNAL),
"mode": "ro",
}
}
)
return volumes
def _run(self) -> None:

1
tests/docker/__init__.py Normal file
View File

@ -0,0 +1 @@
"""Docker tests."""

119
tests/docker/test_addon.py Normal file
View File

@ -0,0 +1,119 @@
"""Test docker addon setup."""
from typing import Dict
from unittest.mock import MagicMock, PropertyMock, patch
import pytest
from supervisor.addons import validate as vd
from supervisor.addons.addon import Addon
from supervisor.addons.model import Data
from supervisor.const import SYSTEMD_JOURNAL
from supervisor.coresys import CoreSys
from supervisor.docker.addon import DockerAddon
from ..common import load_json_fixture
@pytest.fixture(name="addonsdata_system")
def fixture_addonsdata_system() -> Dict[str, Data]:
"""Mock AddonsData.system."""
with patch(
"supervisor.addons.data.AddonsData.system", new_callable=PropertyMock
) as mock:
yield mock
@pytest.fixture(name="addonsdata_user", autouse=True)
def fixture_addonsdata_user() -> Dict[str, Data]:
"""Mock AddonsData.user."""
with patch(
"supervisor.addons.data.AddonsData.user", new_callable=PropertyMock
) as mock:
mock.return_value = MagicMock()
yield mock
@pytest.fixture(name="os_environ", autouse=True)
def fixture_os_environ():
"""Mock os.environ."""
with patch("supervisor.config.os.environ") as mock:
yield mock
def get_docker_addon(
coresys: CoreSys, addonsdata_system: Dict[str, Data], config_file: str
):
"""Make and return docker addon object."""
config = vd.SCHEMA_ADDON_CONFIG(load_json_fixture(config_file))
slug = config.get("slug")
addonsdata_system.return_value = {slug: config}
addon = Addon(coresys, config.get("slug"))
docker_addon = DockerAddon(coresys, addon)
return docker_addon
def test_base_volumes_included(coresys: CoreSys, addonsdata_system: Dict[str, Data]):
"""Dev and data volumes always included."""
docker_addon = get_docker_addon(
coresys, addonsdata_system, "basic-addon-config.json"
)
volumes = docker_addon.volumes
# Dev added as ro
assert "/dev" in volumes
assert volumes["/dev"]["bind"] == "/dev"
assert volumes["/dev"]["mode"] == "ro"
# Data added as rw
data_path = str(docker_addon.addon.path_extern_data)
assert data_path in volumes
assert volumes[data_path]["bind"] == "/data"
assert volumes[data_path]["mode"] == "rw"
def test_addon_map_folder_defaults(
coresys: CoreSys, addonsdata_system: Dict[str, Data]
):
"""Validate defaults for mapped folders in addons."""
docker_addon = get_docker_addon(
coresys, addonsdata_system, "basic-addon-config.json"
)
volumes = docker_addon.volumes
# Config added and is marked rw
config_path = str(docker_addon.sys_config.path_extern_homeassistant)
assert config_path in volumes
assert volumes[config_path]["bind"] == "/config"
assert volumes[config_path]["mode"] == "rw"
# SSL added and defaults to ro
ssl_path = str(docker_addon.sys_config.path_extern_ssl)
assert ssl_path in volumes
assert volumes[ssl_path]["bind"] == "/ssl"
assert volumes[ssl_path]["mode"] == "ro"
# Share not mapped
assert str(docker_addon.sys_config.path_extern_share) not in volumes
def test_journald_addon(coresys: CoreSys, addonsdata_system: Dict[str, Data]):
"""Validate volume for journald option."""
docker_addon = get_docker_addon(
coresys, addonsdata_system, "journald-addon-config.json"
)
volumes = docker_addon.volumes
assert str(SYSTEMD_JOURNAL) in volumes
assert volumes.get(str(SYSTEMD_JOURNAL)).get("bind") == str(SYSTEMD_JOURNAL)
assert volumes.get(str(SYSTEMD_JOURNAL)).get("mode") == "ro"
def test_not_journald_addon(coresys: CoreSys, addonsdata_system: Dict[str, Data]):
"""Validate journald option defaults off."""
docker_addon = get_docker_addon(
coresys, addonsdata_system, "basic-addon-config.json"
)
volumes = docker_addon.volumes
assert str(SYSTEMD_JOURNAL) not in volumes

View File

@ -0,0 +1,13 @@
{
"name": "Journald Add-on",
"version": "1.0.1",
"slug": "journald_addon",
"description": "This is a Test Add-on that uses journald",
"arch": ["amd64"],
"url": "https://www.home-assistant.io/",
"startup": "application",
"boot": "auto",
"journald": true,
"options": {},
"schema": {}
}