diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix index 5b1c07c92da3..75a16ef8b556 100644 --- a/nixos/tests/home-assistant.nix +++ b/nixos/tests/home-assistant.nix @@ -10,6 +10,7 @@ in { nodes.hass = { pkgs, ... }: { environment.systemPackages = with pkgs; [ mosquitto ]; + services.mosquitto = { enable = true; listeners = [ { @@ -21,14 +22,18 @@ in { }; } ]; }; + services.home-assistant = { - inherit configDir; enable = true; + inherit configDir; + + # tests loading components by overriding the package package = (pkgs.home-assistant.override { extraComponents = [ "zha" ]; }).overrideAttrs (oldAttrs: { doInstallCheck = false; }); + config = { homeassistant = { name = "Home"; @@ -37,34 +42,56 @@ in { longitude = "0.0"; elevation = 0; }; + + # 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 = {}; + + # configure an mqtt broker connection + # https://www.home-assistant.io/integrations/mqtt mqtt = { broker = "127.0.0.1"; username = mqttUsername; password = mqttPassword; }; - binary_sensor = [{ + + # create a mqtt sensor that syncs state with its mqtt topic + # https://www.home-assistant.io/integrations/sensor.mqtt/ + binary_sensor = [ { platform = "mqtt"; state_topic = "home-assistant/test"; payload_on = "let_there_be_light"; payload_off = "off"; - }]; + } ]; + + # 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/ wake_on_lan = {}; - switch = [{ + switch = [ { platform = "wake_on_lan"; mac = "00:11:22:33:44:55"; host = "127.0.0.1"; - }]; - # tests component-based capability assignment (CAP_NET_BIND_SERVICE) + } ]; + + # 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; }; + + # show mqtt interaction in the log + # https://www.home-assistant.io/integrations/logger/ logger = { default = "info"; logs."homeassistant.components.mqtt" = "debug"; }; }; + + # configure the sample lovelace dashboard lovelaceConfig = { title = "My Awesome Home"; views = [{ @@ -82,33 +109,38 @@ in { testScript = '' start_all() + hass.wait_for_unit("home-assistant.service") + with subtest("Check that YAML configuration file is in place"): hass.succeed("test -L ${configDir}/configuration.yaml") - with subtest("lovelace config is copied because lovelaceConfigWritable = true"): + + 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"): + hass.wait_until_succeeds("journalctl -u home-assistant.service | grep -q 'Home Assistant initialized in'") hass.wait_for_open_port(8123) hass.succeed("curl --fail http://localhost:8123/lovelace") + with subtest("Toggle a binary sensor using MQTT"): hass.wait_for_open_port(1883) hass.succeed( "mosquitto_pub -V mqttv5 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -m let_there_be_light" ) + 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("Print log to ease debugging"): output_log = hass.succeed("cat ${configDir}/home-assistant.log") print("\n### home-assistant.log ###\n") print(output_log + "\n") - # wait for home-assistant to fully boot - hass.sleep(30) - hass.wait_for_unit("home-assistant.service") - with subtest("Check that no errors were logged"): assert "ERROR" not in output_log @@ -117,7 +149,7 @@ in { assert "let_there_be_light" in output_log with subtest("Check systemd unit hardening"): - hass.log(hass.succeed("systemctl show home-assistant.service")) + hass.log(hass.succeed("systemctl cat home-assistant.service")) hass.log(hass.succeed("systemd-analyze security home-assistant.service")) ''; })