Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: implement modules and profiles #16

Draft
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

hoppla20
Copy link
Contributor

@hoppla20 hoppla20 commented Jul 28, 2023

Overview

This PR uses the haumea refactoring of PR #15 and implements the blockType, collector, and transformer (checks still missing) for nixosModules, nixosProfiles, darwinModules, darwinProfiles.

The example repo can be used to aid understanding these changes.

BlockTypes

Modules

The target blocktype to implement nixosModules and darwinModules is as follows:

moduleName: {
  lib,
  config,
  ...
} @ moduleInputs: let
  cfg = config.bee.modules.${moduleName};
in {
  options = {
    exampleOption = mkOption { };
  };

  config = {
    exampleConfig = "example";
  };
}

When the hive.collect function is used, the collector uses the hive.collect.renamer functions to determines the moduleName. The default renamer sets the modules to ${cellName}-${targetName}. Assuming the previous target was of the cell example with the name default (the block name is always "nixosModules" or "darwinModules"), the following module would be the result of the collect operation:

{
  lib,
  config,
  ...
} @ moduleInputs: let
  cfg = config.bee.modules.example-default;
in {
  options.bee.modules.example-default = {
    enable = mkOption {
      type = lib.types.bool;
      default = false;
    };

    exampleOption = mkOption { };
  };

  config = mkIf config.bee.modules.example-default.enable {
    exampleConfig = "example";
  };
}

As you can see in the resulting module, the collector automagically adds a 'switch' to enable and disable the module.

Profiles

Profiles are similar to modules with the difference that the shouldn't have options. Therefore the target block type for nixosProfiles and darwinProfiles assume that the target returns a function that expects moduleInputs as input and returns an config attribute set. For example:

{
  lib,
  config,
  ...
} @ moduleInputs: {
  services.openssh = {
    enable = true;
    openFirewall = config.networking.firewall.enable;
  };
}

The resulting nixos module (with cell = "example" and target = "default") would be:

{
  lib,
  config,
  ...
} @ moduleInputs: {
  options.bee._profiles.example-default.enable = lib.mkOption {
    type = lib.types.bool;
    default = lib.elem "example-default" config.bee.profiles;
  };
  
  config = lib.mkIf config.bee._profiles.example-default.enable {
    services.openssh = {
      enable = true;
      openFirewall = config.networking.firewall.enable;
    };
  };
}

Again, the collector automagically added a switch. In contrast to modules, profiles can be enabled using the bee.profiles option, which expects a list of strings.

Scope

This PR modifies the collector for nixosConfigurations in a way that nixosModules and nixosProfiles of the same cell are automatically loaded. However these modules and profiles still have to be configured and enabled using the bee.modules and bee.profiles config options. The behaviour for darwin is equivilent.

Modules and profiles of other cells of the same flake or other flakes can the loaded using the bee.extraModules and bee.extraProfiles options.

Example

A full example can be found in the example repository linked in the beginning. I have pinned the link to a commit, which should be fully working.

Tests

I have only tested this PR using the example repo. I am planning to extend this to a full VM setup, maybe including tests for darwin.

Further work

Suites

By implementing the bee.profiles as a list of lists, suites can then also be implemented as lists of strings.

Naming collision avoidance

One should be able to use the hive.collect function on an input instead of self and by overriding the hive.collect.renamer function, one should be able to change all module and profile names, including their references in profiles and suites.

Checks for modules and profiles

In the implementation of the PR i refactored the checkBeeAnd function to checks.bee. And instead of calling the transformation function using checkBeeAnd, the checks.bee function asserts that the bee modules has no alerts and is just another step in the pipe. With this setup one could also implement checks for modules and profiles, however I'm not yet sure how to implement this.

Update 1

Pass targetName function to profiles

Change to the profiles block type:

targetName: {
  lib,
  config,
  ...
} @ moduleInputs: {
  bee.modules.${targetName "default"}.enable = true;
  services.openssh = {
    enable = true;
    openFirewall = config.networking.firewall.enable;
  };
}

The targetName function is passed to the profile from the hive.collect function and its definition is targetName = hive.collect.renamer cell. Basically the targetName is a curried function with the cell paramter pre-applied. The resulting nixos module (with cell = "example" and target = "default") with the default renamer (renamer = cell: target: "${cell}-${target}") is:

{
  lib,
  config,
  ...
} @ moduleInputs: {
  options.bee._profiles.example-default.enable = lib.mkOption {
    type = lib.types.bool;
    default = lib.elem "example-default" config.bee.profiles;
  };
  
  config = lib.mkIf config.bee._profiles.example-default.enable {
    # bee.modules.${renamer cell target}.enable = true;
    bee.modules.examples-default.enable = true;
    services.openssh = {
      enable = true;
      openFirewall = config.networking.firewall.enable;
    };
  };
}

This allows profiles to reference modules in the same cell, without breaking when overriding the renamer attribute of hive.collect. The example repository demonstrates this.

@hoppla20 hoppla20 changed the title Implement modules and profiles feat: implement modules and profiles Jul 28, 2023
@hoppla20
Copy link
Contributor Author

I will provide more Info's tomorrow. It's 3 in the morning for me :)

@hoppla20 hoppla20 changed the title feat: implement modules and profiles WIP: implement modules and profiles Jul 28, 2023
@hoppla20 hoppla20 changed the title WIP: implement modules and profiles feat: implement modules and profiles Jul 28, 2023
@hoppla20 hoppla20 changed the title feat: implement modules and profiles WIP: implement modules and profiles Jul 28, 2023
@hoppla20
Copy link
Contributor Author

@blaggacao I have also addressed this comment #15 (comment) in the haumea PR (#15). The cellBlock parameter is used to determine wether a collector is available and is then passed to the collector, which uses it to match cells.

@hoppla20 hoppla20 marked this pull request as draft July 28, 2023 14:17
@hoppla20 hoppla20 closed this Jul 28, 2023
@hoppla20 hoppla20 reopened this Jul 28, 2023
@hoppla20 hoppla20 force-pushed the implement-modules-and-profiles branch from d07f12e to 45e4f5d Compare July 28, 2023 18:15
@hoppla20 hoppla20 force-pushed the implement-modules-and-profiles branch from c02dc60 to 59d1da6 Compare July 29, 2023 11:02
@hoppla20 hoppla20 force-pushed the implement-modules-and-profiles branch from fc960b5 to 8fcabbe Compare July 29, 2023 11:42
@hoppla20
Copy link
Contributor Author

hoppla20 commented Aug 27, 2023

I will probably abandon this PR, I'm currently working on a loader more akin to hive.findLoad, and hive.load. This is currently implemented an used here. If there is interest to upstream this loader (changing the namespacing from hoppla to bee of course), I would be happy to create a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant