From c6f143307c10ca4ecf448c523267bc37fa10299e Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:00:19 +0300 Subject: [PATCH 1/4] uwsgi: refactor, throw sensible error if plugin is not found --- pkgs/servers/uwsgi/default.nix | 46 ++++++++++++++++++--------------- pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/pkgs/servers/uwsgi/default.nix b/pkgs/servers/uwsgi/default.nix index abcbaa04b8c0..2d447d3c82a9 100644 --- a/pkgs/servers/uwsgi/default.nix +++ b/pkgs/servers/uwsgi/default.nix @@ -1,28 +1,35 @@ { stdenv, lib, fetchurl, pkgconfig, jansson -# plugins: list of strings, eg. [python2, python3] +# plugins: list of strings, eg. [ "python2" "python3" ] , plugins -, pam, withPAM ? stdenv.isLinux -, systemd, withSystemd ? stdenv.isLinux +, pam, withPAM ? false +, systemd, withSystemd ? false , python2, python3, ncurses }: -let pythonPlugin = pkg : { name = "python${if pkg ? isPy2 then "2" else "3"}"; - interpreter = pkg; +let pythonPlugin = pkg : lib.nameValuePair "python${if pkg ? isPy2 then "2" else "3"}" { + interpreter = pkg.interpreter; path = "plugins/python"; - deps = [ pkg ncurses ]; + inputs = [ pkg ncurses ]; install = '' install -Dm644 uwsgidecorators.py $out/${pkg.sitePackages}/uwsgidecorators.py ${pkg.executable} -m compileall $out/${pkg.sitePackages}/ ${pkg.executable} -O -m compileall $out/${pkg.sitePackages}/ ''; }; - available = [ (pythonPlugin python2) + + available = lib.listToAttrs [ + (pythonPlugin python2) (pythonPlugin python3) ]; - needed = builtins.filter (x: lib.any (y: x.name == y) plugins) available; -in -assert builtins.filter (x: lib.all (y: y.name != x) available) plugins == []; + getPlugin = name: + let all = lib.concatStringsSep ", " (lib.attrNames available); + in if lib.hasAttr name available + then lib.getAttr name available // { inherit name; } + else throw "Unknown UWSGI plugin ${name}, available : ${all}"; + + needed = builtins.map getPlugin plugins; +in stdenv.mkDerivation rec { name = "uwsgi-2.0.11.2"; @@ -34,17 +41,15 @@ stdenv.mkDerivation rec { nativeBuildInputs = [ python3 pkgconfig ]; - buildInputs = with stdenv.lib; - [ jansson ] - ++ optional withPAM pam - ++ optional withSystemd systemd - ++ lib.concatMap (x: x.deps) needed + buildInputs = [ jansson ] + ++ lib.optional withPAM pam + ++ lib.optional withSystemd systemd + ++ lib.concatMap (x: x.inputs) needed ; - basePlugins = with stdenv.lib; - concatStringsSep "," - ( optional withPAM "pam" - ++ optional withSystemd "systemd_logger" + basePlugins = lib.concatStringsSep "," + ( lib.optional withPAM "pam" + ++ lib.optional withSystemd "systemd_logger" ); passthru = { @@ -59,12 +64,11 @@ stdenv.mkDerivation rec { buildPhase = '' mkdir -p $pluginDir python3 uwsgiconfig.py --build nixos - ${lib.concatMapStringsSep ";" (x: "${x.interpreter.interpreter} uwsgiconfig.py --plugin ${x.path} nixos ${x.name}") needed} + ${lib.concatMapStringsSep ";" (x: "${x.interpreter} uwsgiconfig.py --plugin ${x.path} nixos ${x.name}") needed} ''; installPhase = '' install -Dm755 uwsgi $out/bin/uwsgi - #cp *_plugin.so $pluginDir || true ${lib.concatMapStringsSep "\n" (x: x.install) needed} ''; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 44c42e012a40..e915658b3505 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3477,6 +3477,8 @@ let uwsgi = callPackage ../servers/uwsgi { plugins = []; + withPAM = stdenv.isLinux; + withSystemd = stdenv.isLinux; }; vacuum = callPackage ../applications/networking/instant-messengers/vacuum {}; From d39d87bb812fcd63a551b207bb0c66022048aed9 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:00:31 +0300 Subject: [PATCH 2/4] uwsgi: disable built-in yaml support --- pkgs/servers/uwsgi/nixos.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/servers/uwsgi/nixos.ini b/pkgs/servers/uwsgi/nixos.ini index 454eb51893fc..51bc6da33f6c 100644 --- a/pkgs/servers/uwsgi/nixos.ini +++ b/pkgs/servers/uwsgi/nixos.ini @@ -2,4 +2,5 @@ plugin_dir = @pluginDir@ main_plugin = @basePlugins@ json = true +yaml = false inherit = base From e48c991131b4f75445e79b4da8871ae721339ae2 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:02:14 +0300 Subject: [PATCH 3/4] uwsgi service: refactor, throw more errors and drop simultaneous Python 2/3 in path --- nixos/modules/services/web-servers/uwsgi.nix | 112 +++++++++++++------ 1 file changed, 77 insertions(+), 35 deletions(-) diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix index 3e18a6f0e986..39f7047af2da 100644 --- a/nixos/modules/services/web-servers/uwsgi.nix +++ b/nixos/modules/services/web-servers/uwsgi.nix @@ -5,44 +5,86 @@ with lib; let cfg = config.services.uwsgi; - python2Pkgs = pkgs.python2Packages.override { - python = pkgs.uwsgi.python2; - self = python2Pkgs; - }; - - python3Pkgs = pkgs.python3Packages.override { - python = pkgs.uwsgi.python3; - self = python3Pkgs; - }; - - buildCfg = c: if builtins.typeOf c != "set" then builtins.readFile c else builtins.toJSON { - uwsgi = - if c.type == "normal" - then { - pythonpath = - (if c ? python2Packages - then builtins.map (x: "${x}/${pkgs.uwsgi.python2.sitePackages}") (c.python2Packages python2Pkgs) - else []) - ++ (if c ? python3Packages - then builtins.map (x: "${x}/${pkgs.uwsgi.python3.sitePackages}") (c.python3Packages python3Pkgs) - else []); - plugins = cfg.plugins; - } // removeAttrs c [ "type" "python2Packages" "python3Packages" ] - else if c.type == "emperor" - then { - emperor = if builtins.typeOf c.vassals != "set" then c.vassals - else pkgs.buildEnv { - name = "vassals"; - paths = mapAttrsToList (n: c: pkgs.writeTextDir "${n}.json" (buildCfg c)) c.vassals; - }; - } // removeAttrs c [ "type" "vassals" ] - else abort "type should be either 'normal' or 'emperor'"; - }; - uwsgi = pkgs.uwsgi.override { plugins = cfg.plugins; }; + buildCfg = name: c: + let + plugins = + if any (n: !any (m: m == n) cfg.plugins) (c.plugins or []) + then throw "`plugins` attribute in UWSGI configuration contains plugins not in config.services.uwsgi.plugins" + else c.plugins or cfg.plugins; + + hasPython = v: filter (n: n == "python${v}") plugins != []; + hasPython2 = hasPython "2"; + hasPython3 = hasPython "3"; + + python = + if hasPython2 && hasPython3 then + throw "`plugins` attribute in UWSGI configuration shouldn't contain both python2 and python3" + else if hasPython2 then uwsgi.python2 + else if hasPython3 then uwsgi.python3 + else null; + + pythonPackages = pkgs.pythonPackages.override { + inherit python; + self = pythonPackages; + }; + + json = builtins.toJSON { + uwsgi = + if c.type == "normal" + then { + inherit plugins; + } // removeAttrs c [ "type" "pythonPackages" ] + // optionalAttrs (python != null) { + pythonpath = "@PYTHONPATH@"; + env = (c.env or {}) // { + PATH = optionalString (c ? env.PATH) "${c.env.PATH}:" + "@PATH@"; + }; + } + else if c.type == "emperor" + then { + emperor = if builtins.typeOf c.vassals != "set" then c.vassals + else pkgs.buildEnv { + name = "vassals"; + paths = mapAttrsToList buildCfg c.vassals; + }; + } // removeAttrs c [ "type" "vassals" ] + else throw "`type` attribute in UWSGI configuration should be either 'normal' or 'emperor'"; + }; + + in + if python == null || c.type != "normal" + then pkgs.writeTextDir "${name}.json" json + else pkgs.stdenv.mkDerivation { + name = "uwsgi-config"; + inherit json; + passAsFile = [ "json" ]; + nativeBuildInputs = [ pythonPackages.wrapPython ]; + pythonInputs = (c.pythonPackages or (self: [])) pythonPackages; + + buildCommand = '' + mkdir $out + declare -A pythonPathsSeen=() + program_PYTHONPATH= + program_PATH= + if [ -n "$pythonInputs" ]; then + for i in $pythonInputs; do + _addToPythonPath $i + done + fi + # A hack to replace "@PYTHONPATH@" with a JSON list + if [ -n "$program_PYTHONPATH" ]; then + program_PYTHONPATH="\"''${program_PYTHONPATH//:/\",\"}\"" + fi + substitute $jsonPath $out/${name}.json \ + --replace '"@PYTHONPATH@"' "[$program_PYTHONPATH]" \ + --subst-var-by PATH "$program_PATH" + ''; + }; + in { options = { @@ -118,7 +160,7 @@ in { ''; serviceConfig = { Type = "notify"; - ExecStart = "${uwsgi}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${pkgs.writeText "uwsgi.json" (buildCfg cfg.instance)}"; + ExecStart = "${uwsgi}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${buildCfg "server" cfg.instance}/server.json"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; NotifyAccess = "main"; From b6c49abba028bea76ba85966beb1e4149d5865be Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:10:05 +0300 Subject: [PATCH 4/4] uwsgi service: update documentation --- nixos/modules/services/web-servers/uwsgi.nix | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix index 39f7047af2da..e6c25e6215c1 100644 --- a/nixos/modules/services/web-servers/uwsgi.nix +++ b/nixos/modules/services/web-servers/uwsgi.nix @@ -113,21 +113,24 @@ in { vassals = { moin = { type = "normal"; - python2Packages = self: with self; [ moinmoin ]; + pythonPackages = self: with self; [ moinmoin ]; socket = "${config.services.uwsgi.runDir}/uwsgi.sock"; }; }; } ''; description = '' - uWSGI configuration. This awaits either a path to file or a set which will be made into one. - If given a set, it awaits an attribute type which can be either normal - or emperor. + uWSGI configuration. It awaits an attribute type inside which can be either + normal or emperor. + + For normal mode you can specify pythonPackages as a function + from libraries set into a list of libraries. pythonpath will be set accordingly. - For normal mode you can specify python2Packages and - python3Packages as functions from libraries set into lists of libraries. For emperor mode, you should use vassals attribute which should be either a set of names and configurations or a path to a directory. + + Other attributes will be used in configuration file as-is. Notice that you can redefine + plugins setting here. ''; };