mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-29 00:53:57 +00:00
4f0dadbf38
After final improvements to the official formatter implementation, this commit now performs the first treewide reformat of Nix files using it. This is part of the implementation of RFC 166. Only "inactive" files are reformatted, meaning only files that aren't being touched by any PR with activity in the past 2 months. This is to avoid conflicts for PRs that might soon be merged. Later we can do a full treewide reformat to get the rest, which should not cause as many conflicts. A CI check has already been running for some time to ensure that new and already-formatted files are formatted, so the files being reformatted here should also stay formatted. This commit was automatically created and can be verified using nix-builda08b3a4d19
.tar.gz \ --argstr baseRevb32a094368
result/bin/apply-formatting $NIXPKGS_PATH
266 lines
9.5 KiB
Nix
266 lines
9.5 KiB
Nix
{
|
|
lib,
|
|
...
|
|
}:
|
|
|
|
let
|
|
configDir = "/var/lib/foobar";
|
|
in
|
|
{
|
|
name = "home-assistant";
|
|
meta.maintainers = lib.teams.home-assistant.members;
|
|
|
|
nodes.hass =
|
|
{ pkgs, ... }:
|
|
{
|
|
services.postgresql = {
|
|
enable = true;
|
|
ensureDatabases = [ "hass" ];
|
|
ensureUsers = [
|
|
{
|
|
name = "hass";
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
};
|
|
|
|
services.home-assistant = {
|
|
enable = true;
|
|
inherit configDir;
|
|
|
|
# provide dependencies through package overrides
|
|
package = (
|
|
pkgs.home-assistant.override {
|
|
extraPackages =
|
|
ps: with ps; [
|
|
colorama
|
|
];
|
|
extraComponents = [
|
|
# test char-tty device allow propagation into the service
|
|
"zha"
|
|
];
|
|
}
|
|
);
|
|
|
|
# provide component dependencies explicitly from the module
|
|
extraComponents = [
|
|
"mqtt"
|
|
];
|
|
|
|
# provide package for postgresql support
|
|
extraPackages =
|
|
python3Packages: with python3Packages; [
|
|
psycopg2
|
|
];
|
|
|
|
# test loading custom components
|
|
customComponents = with pkgs.home-assistant-custom-components; [
|
|
prometheus_sensor
|
|
# tests loading multiple components from a single package
|
|
spook
|
|
];
|
|
|
|
# test loading lovelace modules
|
|
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
|
|
mini-graph-card
|
|
];
|
|
|
|
config = {
|
|
homeassistant = {
|
|
name = "Home";
|
|
time_zone = "UTC";
|
|
latitude = "0.0";
|
|
longitude = "0.0";
|
|
elevation = 0;
|
|
};
|
|
|
|
# configure the recorder component to use the postgresql db
|
|
recorder.db_url = "postgresql://@/hass";
|
|
|
|
# we can't load default_config, because the updater requires
|
|
# network access and would cause an error, so load frontend
|
|
# here explicitly.
|
|
# https://www.home-assistant.io/integrations/frontend/
|
|
frontend = { };
|
|
|
|
# include some popular integrations, that absolutely shouldn't break
|
|
knx = { };
|
|
shelly = { };
|
|
zha = { };
|
|
|
|
# set up a wake-on-lan switch to test capset capability required
|
|
# for the ping suid wrapper
|
|
# https://www.home-assistant.io/integrations/wake_on_lan/
|
|
switch = [
|
|
{
|
|
platform = "wake_on_lan";
|
|
mac = "00:11:22:33:44:55";
|
|
host = "127.0.0.1";
|
|
}
|
|
];
|
|
|
|
# test component-based capability assignment (CAP_NET_BIND_SERVICE)
|
|
# https://www.home-assistant.io/integrations/emulated_hue/
|
|
emulated_hue = {
|
|
host_ip = "127.0.0.1";
|
|
listen_port = 80;
|
|
};
|
|
|
|
# https://www.home-assistant.io/integrations/logger/
|
|
logger = {
|
|
default = "info";
|
|
};
|
|
};
|
|
|
|
# configure the sample lovelace dashboard
|
|
lovelaceConfig = {
|
|
title = "My Awesome Home";
|
|
views = [
|
|
{
|
|
title = "Example";
|
|
cards = [
|
|
{
|
|
type = "markdown";
|
|
title = "Lovelace";
|
|
content = "Welcome to your **Lovelace UI**.";
|
|
}
|
|
];
|
|
}
|
|
];
|
|
};
|
|
lovelaceConfigWritable = true;
|
|
};
|
|
|
|
# Cause a configuration change inside `configuration.yml` and verify that the process is being reloaded.
|
|
specialisation.differentName = {
|
|
inheritParentConfig = true;
|
|
configuration.services.home-assistant.config.homeassistant.name = lib.mkForce "Test Home";
|
|
};
|
|
|
|
# Cause a configuration change that requires a service restart as we added a new runtime dependency
|
|
specialisation.newFeature = {
|
|
inheritParentConfig = true;
|
|
configuration.services.home-assistant.config.prometheus = { };
|
|
};
|
|
|
|
specialisation.removeCustomThings = {
|
|
inheritParentConfig = true;
|
|
configuration.services.home-assistant = {
|
|
customComponents = lib.mkForce [ ];
|
|
customLovelaceModules = lib.mkForce [ ];
|
|
};
|
|
};
|
|
};
|
|
|
|
testScript =
|
|
{ nodes, ... }:
|
|
let
|
|
system = nodes.hass.system.build.toplevel;
|
|
in
|
|
''
|
|
import json
|
|
|
|
start_all()
|
|
|
|
|
|
def get_journal_cursor() -> str:
|
|
exit, out = hass.execute("journalctl -u home-assistant.service -n1 -o json-pretty --output-fields=__CURSOR")
|
|
assert exit == 0
|
|
return json.loads(out)["__CURSOR"]
|
|
|
|
|
|
def get_journal_since(cursor) -> str:
|
|
exit, out = hass.execute(f"journalctl --after-cursor='{cursor}' -u home-assistant.service")
|
|
assert exit == 0
|
|
return out
|
|
|
|
|
|
def get_unit_property(property) -> str:
|
|
exit, out = hass.execute(f"systemctl show --property={property} home-assistant.service")
|
|
assert exit == 0
|
|
return out
|
|
|
|
|
|
def wait_for_homeassistant(cursor):
|
|
hass.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u home-assistant.service | grep -q 'Home Assistant initialized in'")
|
|
|
|
|
|
hass.wait_for_unit("home-assistant.service")
|
|
cursor = get_journal_cursor()
|
|
|
|
with subtest("Check that YAML configuration file is in place"):
|
|
hass.succeed("test -L ${configDir}/configuration.yaml")
|
|
|
|
with subtest("Check the lovelace config is copied because lovelaceConfigWritable = true"):
|
|
hass.succeed("test -f ${configDir}/ui-lovelace.yaml")
|
|
|
|
with subtest("Check that Home Assistant's web interface and API can be reached"):
|
|
wait_for_homeassistant(cursor)
|
|
hass.wait_for_open_port(8123)
|
|
hass.succeed("curl --fail http://localhost:8123/lovelace")
|
|
|
|
with subtest("Check that custom components get installed"):
|
|
hass.succeed("test -f ${configDir}/custom_components/prometheus_sensor/manifest.json")
|
|
for integration in ("prometheus_sensor", "spook", "spook_inverse"):
|
|
hass.wait_until_succeeds(f"journalctl -u home-assistant.service | grep -q 'We found a custom integration {integration} which has not been tested by Home Assistant'")
|
|
|
|
with subtest("Check that lovelace modules are referenced and fetchable"):
|
|
hass.succeed("grep -q 'mini-graph-card-bundle.js' '${configDir}/configuration.yaml'")
|
|
hass.succeed("curl --fail http://localhost:8123/local/nixos-lovelace-modules/mini-graph-card-bundle.js")
|
|
|
|
with subtest("Check that optional dependencies are in the PYTHONPATH"):
|
|
env = get_unit_property("Environment")
|
|
python_path = env.split("PYTHONPATH=")[1].split()[0]
|
|
for package in ["colorama", "paho-mqtt", "psycopg2"]:
|
|
assert package in python_path, f"{package} not in PYTHONPATH"
|
|
|
|
with subtest("Check that declaratively configured components get setup"):
|
|
journal = get_journal_since(cursor)
|
|
for domain in ["emulated_hue", "wake_on_lan"]:
|
|
assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
|
|
|
|
with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
|
|
hass.wait_for_open_port(80)
|
|
hass.succeed("curl --fail http://localhost:80/description.xml")
|
|
|
|
with subtest("Check extra components are considered in systemd unit hardening"):
|
|
hass.succeed("systemctl show -p DeviceAllow home-assistant.service | grep -q char-ttyUSB")
|
|
|
|
with subtest("Check service restart from SIGHUP"):
|
|
pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
|
|
cursor = get_journal_cursor()
|
|
hass.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
|
|
wait_for_homeassistant(cursor)
|
|
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
|
|
assert pid != new_pid, "The PID of the process must change after sending SIGHUP"
|
|
|
|
with subtest("Check service restarts when dependencies change"):
|
|
pid = new_pid
|
|
cursor = get_journal_cursor()
|
|
hass.succeed("${system}/specialisation/newFeature/bin/switch-to-configuration test")
|
|
wait_for_homeassistant(cursor)
|
|
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
|
|
assert pid != new_pid, "The PID of the process must change when its PYTHONPATH changess"
|
|
|
|
with subtest("Check that new components get setup after restart"):
|
|
journal = get_journal_since(cursor)
|
|
for domain in ["prometheus"]:
|
|
assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
|
|
|
|
with subtest("Check custom components and custom lovelace modules get removed"):
|
|
cursor = get_journal_cursor()
|
|
hass.succeed("${system}/specialisation/removeCustomThings/bin/switch-to-configuration test")
|
|
hass.fail("grep -q 'mini-graph-card-bundle.js' '${configDir}/ui-lovelace.yaml'")
|
|
for integration in ("prometheus_sensor", "spook", "spook_inverse"):
|
|
hass.fail(f"test -f ${configDir}/custom_components/{integration}/manifest.json")
|
|
wait_for_homeassistant(cursor)
|
|
|
|
with subtest("Check that no errors were logged"):
|
|
hass.fail("journalctl -u home-assistant -o cat | grep -q ERROR")
|
|
|
|
with subtest("Check systemd unit hardening"):
|
|
hass.log(hass.succeed("systemctl cat home-assistant.service"))
|
|
hass.log(hass.succeed("systemd-analyze security home-assistant.service"))
|
|
'';
|
|
}
|