使用`import`和lib.mkOption给出的参数

时间:2017-07-17 12:44:10

标签: nix nixos

我有什么

在nixos模块中使用带有硬编码路径的mmm效果很好,这里有一个例子:

nixcloud-反向proxy.nix

{ config, pkgs, lib, ... } @ args:
{
   config = { ... };
   options = { 
     services.nixcloud-reverse-proxy = {
       configDir = mkOption {
       type = types.path;
       default = ./. + "/reverse-proxy-config-tests/";
       description = ''An absolute path to reverse proxy configurations. This is used for nixcloud.io deployment mainly, where we rebuild the reverse proxy configuration based on many individual configurations.'';
  };  
     };

   imports = 
    let
      # walk through all configs in the mmm and merge them
      mmm = ./. + "/reverse-proxy-config-tests/";
      filesToLoad = attrNames (filterAttrs (k: v: v == "regular") (builtins.readDir mmm));
      configsFromPath = map (el: (mmm + ("/" + el) )) filesToLoad;
    in configsFromPath;
}

问题

我希望将mmm替换为config.services.nixcloud-reverse-proxy.configDir,但这会导致:

nixos-rebuild build
building Nix...
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/lib/modules.nix:60:71
(use ‘--show-trace’ to show detailed location information)
building the system configuration...
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/lib/modules.nix:60:71
(use ‘--show-trace’ to show detailed location information)

3 个答案:

答案 0 :(得分:1)

简而言之,没办法。

事实上,您无法在imports内定义config条款:

{ config, ... }: {
  options = { ... };
  config = {
    imports = [ ... ];   # <--- error !!!
    ...
  };
}

是关于NixOS模块系统如何工作的说明。其中一个问题是 - 您无法根据其他配置选项动态分支或以其他方式控制所包含模块的数量。这就是为什么许多模块定义module.enable选项的原因,允许这样做。

因此,回到您的问题,imports子句不能依赖config.services.nixcloud-reverse-proxy.configDir,因为config变量要求所有imports已合并。使用当前模块系统几乎无法修复。或许可以通过使用另一个变量(不是config)来克服这个问题,但这是你想要的吗?

答案 1 :(得分:0)

我终于找到了可能的解决方法:

builtins.getEnv可用于传递'变量'。这不如lib.mkOption好,但与lib.mkOption{ myPath ? "/reverse-proxy-config-tests/ } : { ... }不同,它不会创建每次无限递归错误。

这意味着,在我做之前:nix-build -A reverse-proxy我需要导出环境变量以传入我的自定义nix文件所在的路径,该路径类似于--args但不限于{{1}并且还应该与nix-build

一起使用

答案 2 :(得分:0)

如此处所示:https://github.com/NixOS/nixpkgs/issues/30190

我现在已经考虑了很长一段时间了,paul&amp;我刚刚发现了这个解决方案:

可能的解决方案4

我们在default.nix内创建reverse-proxy/reverse-proxy-config-tests2,其中包含:

{  config, pkgs, lib, ... }:
with lib;

{

  # import config files (nixcloud.io specific for reverse proxy configuration)  
  # use the nix module system to have type validation and inherit meaningful default values for options which are not set explicitly
  config = {
  };

  imports =
  let
    cDir = builtins.toPath (./config);

    filesToLoad = attrNames (filterAttrs (k: v: v == "regular") (builtins.readDir cDir));
    configsFromPath = map (el: (cDir + ("/" + el) )) filesToLoad;
    toModule = x: ({ config, pkgs, lib, ... }: {
      options = {};
      config.nixcloud.reverse-proxy.extraMappings = x;
    });
  in
    fold (el: c: c ++ [(toModule (import el))]) [  ] configsFromPath;
}

并称之为:

  machine = { pkgs, lib, ... }: {
    nix.nixPath = [ "nixpkgs=${<nixpkgs>}" "nixos-config=/etc/nixos/configuration.nix" ];
    nix.binaryCaches = lib.mkForce [];
    nixcloud.reverse-proxy.enable = true;
    imports = [ ../reverse-proxy/reverse-proxy-config-tests2  ];

    # Needed so that we have all dependencies available for building the
    # container config within the VM.
    virtualisation.pathsInNixDB = let
      emptyClosure = (import <nixpkgs/nixos/lib/eval-config.nix> {
        modules = lib.singleton { boot.isContainer = true; };
      }).config.system.build.toplevel;
    in [ pkgs.stdenv emptyClosure ];
  };

问题

更新default.nix现在是有状态的,因为需要将default.nix的代码更新复制到我们即将加载的配置的目录中。

说,我们选择此解决方案,因为它不需要环境变量,让我们动态更改包含路径,只需要主imports [ ]中的另一个configuration.nix