diff --git a/lib/maintainers.nix b/lib/maintainers.nix index 36ff2d154d85..b892f29a8e6e 100644 --- a/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -231,6 +231,7 @@ fadenb = "Tristan Helmich "; falsifian = "James Cook "; fare = "Francois-Rene Rideau "; + f-breidenstein = "Felix Breidenstein "; fgaz = "Francesco Gazzetta "; FireyFly = "Jonas Höglund "; flokli = "Florian Klink "; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 415be580e974..28ed10a5ece6 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -302,6 +302,7 @@ kodi = 283; restya-board = 284; mighttpd2 = 285; + hass = 286; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -572,6 +573,7 @@ kodi = 283; restya-board = 284; mighttpd2 = 285; + hass = 286; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 1942cca23d6e..2ec8b28c3fc4 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -315,6 +315,7 @@ ./services/misc/gogs.nix ./services/misc/gollum.nix ./services/misc/gpsd.nix + ./services/misc/home-assistant.nix ./services/misc/ihaskell.nix ./services/misc/irkerd.nix ./services/misc/jackett.nix diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix new file mode 100644 index 000000000000..bc463d3e670c --- /dev/null +++ b/nixos/modules/services/misc/home-assistant.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.home-assistant; + + configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config); +in { + meta.maintainers = with maintainers; [ dotlambda ]; + + options.services.home-assistant = { + enable = mkEnableOption "Home Assistant"; + + configDir = mkOption { + default = "/var/lib/hass"; + type = types.path; + description = "The config directory, where your configuration.yaml is located."; + }; + + config = mkOption { + default = null; + type = with types; nullOr attrs; + example = literalExample '' + { + homeassistant = { + name = "Home"; + time_zone = "UTC"; + }; + frontend = { }; + http = { }; + } + ''; + description = '' + Your configuration.yaml as a Nix attribute set. + Beware that setting this option will delete your previous configuration.yaml. + ''; + }; + + package = mkOption { + default = pkgs.home-assistant; + defaultText = "pkgs.home-assistant"; + type = types.package; + example = literalExample '' + pkgs.home-assistant.override { + extraPackages = ps: with ps; [ colorlog ]; + } + ''; + description = '' + Home Assistant package to use. + Most Home Assistant components require additional dependencies, + which are best specified by overriding pkgs.home-assistant. + You can find the dependencies by searching for failed imports in your log or by looking at this list: + + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.home-assistant = { + description = "Home Assistant"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + preStart = lib.optionalString (cfg.config != null) '' + rm -f ${cfg.configDir}/configuration.yaml + ln -s ${configFile} ${cfg.configDir}/configuration.yaml + ''; + serviceConfig = { + ExecStart = '' + ${cfg.package}/bin/hass --config "${cfg.configDir}" + ''; + User = "hass"; + Group = "hass"; + Restart = "on-failure"; + ProtectSystem = "strict"; + ReadWritePaths = "${cfg.configDir}"; + PrivateTmp = true; + }; + }; + + users.extraUsers.hass = { + home = cfg.configDir; + createHome = true; + group = "hass"; + uid = config.ids.uids.hass; + }; + + users.extraGroups.hass.gid = config.ids.gids.hass; + }; +} diff --git a/nixos/release.nix b/nixos/release.nix index 972c89c1a411..a396eaac9a3e 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -267,6 +267,7 @@ in rec { tests.graphite = callTest tests/graphite.nix {}; tests.hardened = callTest tests/hardened.nix { }; tests.hibernate = callTest tests/hibernate.nix {}; + tests.home-assistant = callTest tests/home-assistant.nix { }; tests.hound = callTest tests/hound.nix {}; tests.i3wm = callTest tests/i3wm.nix {}; tests.initrd-network-ssh = callTest tests/initrd-network-ssh {}; diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix new file mode 100644 index 000000000000..0e2fee8e808d --- /dev/null +++ b/nixos/tests/home-assistant.nix @@ -0,0 +1,41 @@ +import ./make-test.nix ({ pkgs, ... }: + +let + configDir = "/var/lib/foobar"; + +in { + name = "home-assistant"; + + nodes = { + hass = + { config, pkgs, ... }: + { + services.home-assistant = { + inherit configDir; + enable = true; + config = { + homeassistant = { + name = "Home"; + time_zone = "UTC"; + }; + frontend = { }; + http = { }; + }; + }; + }; + }; + + testScript = '' + startAll; + $hass->waitForUnit("home-assistant.service"); + + # Since config is specified using a Nix attribute set, + # configuration.yaml is a link to the Nix store + $hass->succeed("test -L ${configDir}/configuration.yaml"); + + # Check that Home Assistant's web interface and API can be reached + $hass->waitForOpenPort(8123); + $hass->succeed("curl --fail http://localhost:8123/states"); + $hass->succeed("curl --fail http://localhost:8123/api/ | grep 'API running'"); + ''; +}) diff --git a/pkgs/development/python-modules/aiohttp/cors.nix b/pkgs/development/python-modules/aiohttp/cors.nix index ab9595ec2b9c..9da239b524a6 100644 --- a/pkgs/development/python-modules/aiohttp/cors.nix +++ b/pkgs/development/python-modules/aiohttp/cors.nix @@ -3,7 +3,7 @@ buildPythonPackage rec { pname = "aiohttp-cors"; version = "0.6.0"; - name = "${pname}-${version}"; + src = fetchPypi { inherit pname version; sha256 = "1r0mb4dw0dc1lpi54dk5vxqs06nyhvagp76lyrvk7rd94z5mjkd4"; diff --git a/pkgs/development/python-modules/aiohttp/default.nix b/pkgs/development/python-modules/aiohttp/default.nix index f1eb7a64d79e..17737c33986a 100644 --- a/pkgs/development/python-modules/aiohttp/default.nix +++ b/pkgs/development/python-modules/aiohttp/default.nix @@ -14,7 +14,6 @@ buildPythonPackage rec { pname = "aiohttp"; version = "2.3.9"; - name = "${pname}-${version}"; src = fetchPypi { inherit pname version; @@ -33,4 +32,4 @@ buildPythonPackage rec { license = with lib.licenses; [ asl20 ]; homepage = https://github.com/KeepSafe/aiohttp/; }; -} \ No newline at end of file +} diff --git a/pkgs/development/python-modules/astral/default.nix b/pkgs/development/python-modules/astral/default.nix new file mode 100644 index 000000000000..76dba87f9648 --- /dev/null +++ b/pkgs/development/python-modules/astral/default.nix @@ -0,0 +1,26 @@ +{ stdenv, buildPythonPackage, fetchPypi, pytz, pytest }: + +buildPythonPackage rec { + pname = "astral"; + version = "1.4"; + + src = fetchPypi { + inherit pname version; + extension = "zip"; + sha256 = "1zm1ypc6w279gh7lbgsfbzfxk2x4gihlq3rfh59hj70hmhjwiwp7"; + }; + + propagatedBuildInputs = [ pytz ]; + + checkInputs = [ pytest ]; + checkPhase = '' + py.test -k "not test_GoogleLocator" + ''; + + meta = with stdenv.lib; { + description = "Calculations for the position of the sun and the moon"; + homepage = https://github.com/sffjunkie/astral/; + license = licenses.asl20; + maintainers = with maintainers; [ flokli ]; + }; +} diff --git a/pkgs/development/python-modules/pytest-aiohttp/default.nix b/pkgs/development/python-modules/pytest-aiohttp/default.nix new file mode 100644 index 000000000000..afdc085aa9f5 --- /dev/null +++ b/pkgs/development/python-modules/pytest-aiohttp/default.nix @@ -0,0 +1,20 @@ +{ stdenv, buildPythonPackage, fetchPypi, pytest, aiohttp }: + +buildPythonPackage rec { + pname = "pytest-aiohttp"; + version = "0.3.0"; + + src = fetchPypi { + inherit pname version; + sha256 = "0kx4mbs9bflycd8x9af0idcjhdgnzri3nw1qb0vpfyb3751qaaf9"; + }; + + propagatedBuildInputs = [ pytest aiohttp ]; + + meta = with stdenv.lib; { + homepage = https://github.com/aio-libs/pytest-aiohttp/; + description = "Pytest plugin for aiohttp support"; + license = licenses.asl20; + maintainers = with maintainers; [ dotlambda ]; + }; +} diff --git a/pkgs/servers/home-assistant/default.nix b/pkgs/servers/home-assistant/default.nix new file mode 100644 index 000000000000..9ec314e5c737 --- /dev/null +++ b/pkgs/servers/home-assistant/default.nix @@ -0,0 +1,72 @@ +{ stdenv, fetchFromGitHub, python3 +, extraPackages ? ps: [] +, skipPip ? true }: + +let + + py = python3.override { + packageOverrides = self: super: { + yarl = super.yarl.overridePythonAttrs (oldAttrs: rec { + version = "0.18.0"; + src = oldAttrs.src.override { + inherit version; + sha256 = "11j8symkxh0ngvpddqpj85qmk6p70p20jca3alxc181gk3vx785s"; + }; + }); + aiohttp = super.aiohttp.overridePythonAttrs (oldAttrs: rec { + version = "2.3.7"; + src = oldAttrs.src.override { + inherit version; + sha256 = "0fzfpx5ny7559xrxaawnylq20dvrkjiag0ypcd13frwwivrlsagy"; + }; + }); + hass-frontend = super.callPackage ./frontend.nix { }; + }; + }; + + # Ensure that we are using a consistent package set + extraBuildInputs = extraPackages py.pkgs; + +in with py.pkgs; buildPythonApplication rec { + pname = "homeassistant"; + version = "0.62.1"; + + diabled = !isPy3k; + + # PyPI tarball is missing tests/ directory + src = fetchFromGitHub { + owner = "home-assistant"; + repo = "home-assistant"; + rev = version; + sha256 = "0151prwk2ci6bih0mdmc3r328nrvazn9jwk0w26wmd4cpvnb5h26"; + }; + + propagatedBuildInputs = [ + # From setup.py + requests pyyaml pytz pip jinja2 voluptuous typing aiohttp yarl async-timeout chardet astral certifi + # From the components that are part of the default configuration.yaml + sqlalchemy aiohttp-cors hass-frontend user-agents distro mutagen xmltodict netdisco + ] ++ extraBuildInputs; + + checkInputs = [ + pytest requests-mock pydispatcher pytest-aiohttp + ]; + + checkPhase = '' + # The components' dependencies are not included, so they cannot be tested + py.test --ignore tests/components + # Some basic components should be tested however + py.test \ + tests/components/{group,http} \ + tests/components/test_{api,configurator,demo,discovery,frontend,init,introduction,logger,script,shell_command,system_log,websocket_api}.py + ''; + + makeWrapperArgs = [] ++ stdenv.lib.optional skipPip [ "--add-flags --skip-pip" ]; + + meta = with stdenv.lib; { + homepage = https://home-assistant.io/; + description = "Open-source home automation platform running on Python 3"; + license = licenses.asl20; + maintainers = with maintainers; [ f-breidenstein dotlambda ]; + }; +} diff --git a/pkgs/servers/home-assistant/frontend.nix b/pkgs/servers/home-assistant/frontend.nix new file mode 100644 index 000000000000..6e1a789012f3 --- /dev/null +++ b/pkgs/servers/home-assistant/frontend.nix @@ -0,0 +1,11 @@ +{ stdenv, fetchPypi, buildPythonPackage }: + +buildPythonPackage rec { + pname = "home-assistant-frontend"; + version = "20180130.0"; + + src = fetchPypi { + inherit pname version; + sha256 = "0b9klisl7hh30rml8qlrp9gpz33z9b825pd1vxbck48k0s98z1zi"; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index d89ab305966f..74656290245b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -11976,6 +11976,8 @@ with pkgs; hiawatha = callPackage ../servers/http/hiawatha {}; + home-assistant = callPackage ../servers/home-assistant { }; + ircdHybrid = callPackage ../servers/irc/ircd-hybrid { }; jboss = callPackage ../servers/http/jboss { }; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 1820125b0a58..2fece6fdd76e 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -165,6 +165,8 @@ in { asn1crypto = callPackage ../development/python-modules/asn1crypto { }; + astral = callPackage ../development/python-modules/astral { }; + astropy = callPackage ../development/python-modules/astropy { }; augeas = callPackage ../development/python-modules/augeas { @@ -3215,6 +3217,8 @@ in { pytest-asyncio = callPackage ../development/python-modules/pytest-asyncio { }; + pytest-aiohttp = callPackage ../development/python-modules/pytest-aiohttp { }; + pytestcache = buildPythonPackage rec { name = "pytest-cache-1.0"; src = pkgs.fetchurl {