0

question

i've been working on a webserver abstraction but using lib.mapAttrsToList always returns a infinite recursion error:

# nixos-rebuild build
building Nix...
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/lib/modules.nix:59:71
(use ‘--show-trace’ to show detailed location information)
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/lib/modules.nix:59: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:59:71
(use ‘--show-trace’ to show detailed location information)

i've added all the other versions of the code, none return the infinite recursion error which is what i don't understand.

so here is my code:

configuration.nix

 imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
       /home/joachim/Desktop/projects/nixcloud/nixcloud-webservices-abstraction/nextcloud.nix
    ];

  services.nextcloud = {
    enable=true;
    networks = {
      net1 = { name = "foo"; };
      net2 = { name = "bar"; };
    };

nixcloud.nix

{ config, options, lib, pkgs, ... }:

with lib; 

let
  mergeListToAttrs = fold (c: el: recursiveUpdate el c) {};
  cfg = config.services.nextcloud;
in

{
 options = {
    services.nextcloud = {
      networks = mkOption {
        default = {};
#         type = types.loaOf types.submodule;
        options = {
          name = mkOption {
            default = "";
            type = types.str;
          };
        };
      };
      enable = mkOption {
        default = true;
        type=types.bool;
        description = ''
          Whether to enable the cntlm, which start a local proxy.
        '';
      };
    };
  };

# example 1 - works
#   config = { 
#     systemd.services = {
#       bar = {
#           wantedBy      = [ "multi-user.target" ];
#           after         = [ "" ];
#       };
#       foo = {
#           wantedBy      = [ "multi-user.target" ];
#           after         = [ "" ];
#       };
#     };
#   };



# example 2 - works   
#   config = {
#     systemd.services = lib.flip lib.mapAttrs cfg.networks (network: data:
#       {
#           wantedBy      = [ "multi-user.target" ];
#           after         = [ "network.target" ];
#           serviceConfig = {
#             ExecStart = "";
#             ExecReload  = "";
#             Restart = "always";
#             RestartSec = "10s";
#             StartLimitInterval = "1min";
#         };
#       }
#     );
#   };


# example 3 - works       
#   config = {
#     systemd.services = flip mapAttrs' cfg.networks (network: data: nameValuePair
#       ("tinc.${network}")
#       ({
#             wantedBy      = [ "multi-user.target" ];
#             after         = [ "network.target" ];
#             serviceConfig = {
#               ExecStart = "";
#               ExecReload  = "";
#               Restart = "always";
#               RestartSec = "10s";
#               StartLimitInterval = "1min";
#             };
#         })
#       );
#   };

# example 4 - works    
#     config = 
#       mergeListToAttrs (
#         [
#           { systemd.services.a = {
#             wantedBy      = [ "multi-user.target" ];
#             after         = [ "network.target" ];
#             serviceConfig = {
#               ExecStart = "";
#               ExecReload  = "";
#               Restart = "always";
#               RestartSec = "10s";
#               StartLimitInterval = "1min";
#             };
#           };
#           }
#           {
#           systemd.services.b = {
#             wantedBy      = [ "multi-user.target" ];
#             after         = [ "network.target" ];
#             serviceConfig = {
#               ExecStart = "";
#               ExecReload  = "";
#               Restart = "always";
#               RestartSec = "10s";
#               StartLimitInterval = "1min";
#             };
#           };
#           }
#         ]); 

# example 5 - fails!
# XXXXXXXX the failing function XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    config = 
      mergeListToAttrs (
        lib.flip lib.mapAttrsToList cfg.networks (wsName: wsConfig: {
          systemd.services.${wsName} = {
            wantedBy      = [ "multi-user.target" ];
            after         = [ "network.target" ];
            serviceConfig = {
              ExecStart = "";
              ExecReload  = "";
              Restart = "always";
              RestartSec = "10s";
              StartLimitInterval = "1min";
            };
          };
        })
      ); 

}
qknight
  • 866
  • 10
  • 23
  • 1
    As far as I can see the only difference is the `mergeListToAttrs` function; what happens if you replace it, e.g. by `head`? – Profpatsch Feb 10 '17 at 08:34

1 Answers1

0

according to aszlig the problem is that example 5 changes and reads from the config at the same time. the solution is to not do that but either use hardcoded 'right-hand values' as in example 4 or assign systemd.services = with a right-hand value.

qknight
  • 866
  • 10
  • 23