1import ./make-test-python.nix ({ pkgs, lib, ... }:
2
3let
4 configDir = "/var/lib/foobar";
5 mqttUsername = "homeassistant";
6 mqttPassword = "secret";
7in {
8 name = "home-assistant";
9 meta.maintainers = lib.teams.home-assistant.members;
10
11 nodes.hass = { pkgs, ... }: {
12 environment.systemPackages = with pkgs; [ mosquitto ];
13 services.mosquitto = {
14 enable = true;
15 listeners = [ {
16 users = {
17 "${mqttUsername}" = {
18 acl = [ "readwrite #" ];
19 password = mqttPassword;
20 };
21 };
22 } ];
23 };
24 services.home-assistant = {
25 inherit configDir;
26 enable = true;
27 config = {
28 homeassistant = {
29 name = "Home";
30 time_zone = "UTC";
31 latitude = "0.0";
32 longitude = "0.0";
33 elevation = 0;
34 };
35 frontend = {};
36 mqtt = {
37 broker = "127.0.0.1";
38 username = mqttUsername;
39 password = mqttPassword;
40 };
41 binary_sensor = [{
42 platform = "mqtt";
43 state_topic = "home-assistant/test";
44 payload_on = "let_there_be_light";
45 payload_off = "off";
46 }];
47 # tests component-based capability assignment (CAP_NET_BIND_SERVICE)
48 emulated_hue = {
49 host_ip = "127.0.0.1";
50 listen_port = 80;
51 };
52 logger = {
53 default = "info";
54 logs."homeassistant.components.mqtt" = "debug";
55 };
56 };
57 lovelaceConfig = {
58 title = "My Awesome Home";
59 views = [{
60 title = "Example";
61 cards = [{
62 type = "markdown";
63 title = "Lovelace";
64 content = "Welcome to your **Lovelace UI**.";
65 }];
66 }];
67 };
68 lovelaceConfigWritable = true;
69 };
70 };
71
72 testScript = ''
73 start_all()
74 hass.wait_for_unit("home-assistant.service")
75 with subtest("Check that YAML configuration file is in place"):
76 hass.succeed("test -L ${configDir}/configuration.yaml")
77 with subtest("lovelace config is copied because lovelaceConfigWritable = true"):
78 hass.succeed("test -f ${configDir}/ui-lovelace.yaml")
79 with subtest("Check that Home Assistant's web interface and API can be reached"):
80 hass.wait_for_open_port(8123)
81 hass.succeed("curl --fail http://localhost:8123/lovelace")
82 with subtest("Toggle a binary sensor using MQTT"):
83 hass.wait_for_open_port(1883)
84 hass.succeed(
85 "mosquitto_pub -V mqttv5 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -m let_there_be_light"
86 )
87 with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
88 hass.wait_for_open_port(80)
89 hass.succeed("curl --fail http://localhost:80/description.xml")
90 with subtest("Print log to ease debugging"):
91 output_log = hass.succeed("cat ${configDir}/home-assistant.log")
92 print("\n### home-assistant.log ###\n")
93 print(output_log + "\n")
94
95 with subtest("Check that no errors were logged"):
96 assert "ERROR" not in output_log
97
98 # example line: 2020-06-20 10:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on home-assistant/test: b'let_there_be_light'
99 with subtest("Check we received the mosquitto message"):
100 assert "let_there_be_light" in output_log
101
102 with subtest("Check systemd unit hardening"):
103 hass.log(hass.succeed("systemctl show home-assistant.service"))
104 hass.log(hass.succeed("systemd-analyze security home-assistant.service"))
105 '';
106})