I’d like to set a “global” option from within a submodule, but the config I return is grafted into the “global” under the submodule “path” rather than at the root… any idea if it’s somehow possible?

Er… I guess I didn’t make a great job at explaining what I want to do… Some code will hopefully help.

In mymodule.nix I have:

{ lib, config, ... }: {

  options.myoption = lib.mkOption {
      type = lib.types.attrsOf (lib.types.submodule (
        import ./mysubmodule.nix
      ));
  };

}

and mysubmodule.nix is:

{ name, lib, config, ... }: {

options.mysubmoduleoption = {
  type = lib.types.str;
};

config = {
  # here I want to set a "global" option, say "systemd.mounts"
  # based on the value of "mymodule.name.mysubmoduleoption"
  # but it seems I can only set values under "mymodule.name" 
};

}
    • gompOP
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      1 year ago

      Your module only defines the option inside types.submodule - I’d (ideally, to better organize the code) want to also put the config section in the submodule.

      Ie. your code is structured similar to:

      options = {
          fileSystems = mkOption {
          type = types.attrsOf (types.submodule {
              options = {
                # bla bla
              };           
          };
          };
      };
      
      config = {
        # set options here
      };
      

      while what I would like to do is more like

      options = {
        fileSystems = mkOption {
          type = types.attrsOf (types.submodule {
            options = {
              # bla bla
            };
            config = {
              # set options here
            };
        };
      };
      

      The reason why I’m trying to do so is purely to restructure my code (which right now does has the config logic at the module, rather than submodule, level) in order to make it more readable/manageable, since it currently has jems like:

      config.services.restic.backups = builtins.listToAttrs (
        builtins.concatLists (lib.attrsets.mapAttrsToList (v-name: v-cfg: (
          builtins.concatLists (lib.attrsets.mapAttrsToList (s-name: s-cfg: (
            builtins.concatLists (lib.attrsets.mapAttrsToList (r-name: r-cfg: (
      

      I know I can restructure the code in other ways (eg. let .. in) - I just wanted to put the options definitions together with the code that uses them.

      • Atemu
        link
        fedilink
        arrow-up
        1
        ·
        1 year ago

        It doesn’t work like that. Submodules are for defining the type, so the only thing you get is interface (options), not implementation.

        I know I can restructure the code in other ways (eg. let .. in)

        Do that.

        Also be aware that some use-cases might be covered by library functions such as lib.flatMap or lib.pipe.

        • gompOP
          link
          fedilink
          arrow-up
          2
          ·
          1 year ago

          Submodules are for defining the type, so the only thing you get is interface (options), not implementation.

          You do get a functional config in submodules… try this (it doesn’t do anything so you can just import into any configuration.nix):

          { config, lib, pkgs, modulesPath, specialArgs, options, ... }: {
          
            options.mynamespace = lib.mkOption {
              type = lib.types.attrsOf (lib.types.submodule ({name, config, ...}:{
                options = {
                  option1 = lib.mkOption { type = lib.types.str; default = ""; };
                  option2 = lib.mkOption { type = lib.types.str; default = ""; };
                };
                config = {
                  option2 = "derived from value of option1: '${config.option1}'";
                };
              }));
            };
          
            config = {
          
              mynamespace.submodule1.option1 = "value of option1";
          
              fileSystems = builtins.trace (builtins.toJSON config.mynamespace) {};
          
            };
          
          }