forked from fediversity/fediversity
		
	Reviewed-on: Fediversity/Fediversity#489 Reviewed-by: kiara Grouwstra <kiara@procolix.eu> Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com> Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
		
			
				
	
	
		
			214 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{
 | 
						|
  inputs,
 | 
						|
  lib,
 | 
						|
  sources,
 | 
						|
  keys,
 | 
						|
  secrets,
 | 
						|
  ...
 | 
						|
}:
 | 
						|
 | 
						|
let
 | 
						|
  inherit (builtins) readDir readFile fromJSON;
 | 
						|
  inherit (lib)
 | 
						|
    attrNames
 | 
						|
    mkOption
 | 
						|
    evalModules
 | 
						|
    filterAttrs
 | 
						|
    mapAttrs'
 | 
						|
    deepSeq
 | 
						|
    ;
 | 
						|
  inherit (lib.attrsets) genAttrs;
 | 
						|
 | 
						|
  commonResourceModule = {
 | 
						|
    # TODO(@fricklerhandwerk): this is terrible but IMO we should just ditch
 | 
						|
    # flake-parts and have our own data model for how the project is organised
 | 
						|
    # internally
 | 
						|
    _module.args = {
 | 
						|
      inherit
 | 
						|
        inputs
 | 
						|
        keys
 | 
						|
        secrets
 | 
						|
        sources
 | 
						|
        ;
 | 
						|
    };
 | 
						|
 | 
						|
    ## FIXME: It would be preferrable to have those `sources`-related imports in
 | 
						|
    ## the modules that use them. However, doing so triggers infinite recursions
 | 
						|
    ## because of the way we propagate `sources`. `sources` must be propagated by
 | 
						|
    ## means of `specialArgs`, but this requires a bigger change.
 | 
						|
    nixos.module.imports = [
 | 
						|
      "${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
 | 
						|
      "${sources.agenix}/modules/age.nix"
 | 
						|
      "${sources.disko}/module.nix"
 | 
						|
      "${sources.home-manager}/nixos"
 | 
						|
    ];
 | 
						|
 | 
						|
    imports = [
 | 
						|
      ./common/resource.nix
 | 
						|
    ];
 | 
						|
  };
 | 
						|
 | 
						|
  ## Given a list of machine names, make a deployment with those machines'
 | 
						|
  ## configurations as resources.
 | 
						|
  makeDeployment =
 | 
						|
    vmNames:
 | 
						|
    { providers, ... }:
 | 
						|
    {
 | 
						|
      providers.local = inputs.nixops4.modules.nixops4Provider.local;
 | 
						|
      resources = genAttrs vmNames (vmName: {
 | 
						|
        type = providers.local.exec;
 | 
						|
        imports = [
 | 
						|
          inputs.nixops4-nixos.modules.nixops4Resource.nixos
 | 
						|
          commonResourceModule
 | 
						|
          ../machines/dev/${vmName}
 | 
						|
        ];
 | 
						|
      });
 | 
						|
    };
 | 
						|
  makeDeployment' = vmName: makeDeployment [ vmName ];
 | 
						|
 | 
						|
  ## Given an attrset of test configurations (key = test machine name, value =
 | 
						|
  ## NixOS configuration module), make a deployment with those machines'
 | 
						|
  ## configurations as resources.
 | 
						|
  makeTestDeployment =
 | 
						|
    (import ../deployment)
 | 
						|
      {
 | 
						|
        inherit lib;
 | 
						|
        inherit (inputs) nixops4 nixops4-nixos;
 | 
						|
        fediversity = import ../services/fediversity;
 | 
						|
      }
 | 
						|
      {
 | 
						|
        garageConfigurationResource = {
 | 
						|
          imports = [
 | 
						|
            commonResourceModule
 | 
						|
            ../machines/operator/test01
 | 
						|
          ];
 | 
						|
        };
 | 
						|
        mastodonConfigurationResource = {
 | 
						|
          imports = [
 | 
						|
            commonResourceModule
 | 
						|
            ../machines/operator/test06 # somehow `test02` has a problem - use test06 instead
 | 
						|
          ];
 | 
						|
        };
 | 
						|
        peertubeConfigurationResource = {
 | 
						|
          imports = [
 | 
						|
            commonResourceModule
 | 
						|
            ../machines/operator/test05
 | 
						|
          ];
 | 
						|
        };
 | 
						|
        pixelfedConfigurationResource = {
 | 
						|
          imports = [
 | 
						|
            commonResourceModule
 | 
						|
            ../machines/operator/test04
 | 
						|
          ];
 | 
						|
        };
 | 
						|
      };
 | 
						|
 | 
						|
  nixops4ResourceNixosMockOptions = {
 | 
						|
    ## NOTE: We allow the use of a few options from
 | 
						|
    ## `nixops4-nixos.modules.nixops4Resource.nixos` such that we can
 | 
						|
    ## reuse modules that make use of them.
 | 
						|
    ##
 | 
						|
    ## REVIEW: We can probably do much better and cleaner. On the other hand,
 | 
						|
    ## this is only needed to expose NixOS configurations for provisioning
 | 
						|
    ## purposes, and eventually all of this should be handled by NixOps4.
 | 
						|
    options = {
 | 
						|
      nixos.module = mkOption { type = lib.types.deferredModule; }; # NOTE: not just `nixos` otherwise merging will go wrong
 | 
						|
      nixpkgs = mkOption { };
 | 
						|
      ssh = mkOption { };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  makeResourceConfig =
 | 
						|
    { vmName, isTestVm }:
 | 
						|
    (evalModules {
 | 
						|
      modules = [
 | 
						|
        nixops4ResourceNixosMockOptions
 | 
						|
        commonResourceModule
 | 
						|
        (if isTestVm then ../machines/operator/${vmName} else ../machines/dev/${vmName})
 | 
						|
      ];
 | 
						|
    }).config;
 | 
						|
 | 
						|
  ## Given a VM name, make a NixOS configuration for this machine.
 | 
						|
  makeConfiguration =
 | 
						|
    isTestVm: vmName:
 | 
						|
    import "${sources.nixpkgs}/nixos" {
 | 
						|
      configuration = (makeResourceConfig { inherit vmName isTestVm; }).nixos.module;
 | 
						|
      system = "x86_64-linux";
 | 
						|
    };
 | 
						|
 | 
						|
  makeVmOptions =
 | 
						|
    isTestVm: vmName:
 | 
						|
    let
 | 
						|
      config = (makeResourceConfig { inherit vmName isTestVm; }).fediversityVm;
 | 
						|
    in
 | 
						|
    if config.isFediversityVm then
 | 
						|
      {
 | 
						|
        inherit (config)
 | 
						|
          vmId
 | 
						|
          description
 | 
						|
          sockets
 | 
						|
          cores
 | 
						|
          memory
 | 
						|
          diskSize
 | 
						|
          hostPublicKey
 | 
						|
          unsafeHostPrivateKey
 | 
						|
          ;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      null;
 | 
						|
 | 
						|
  listSubdirectories = path: attrNames (filterAttrs (_: type: type == "directory") (readDir path));
 | 
						|
 | 
						|
  machines = listSubdirectories ../machines/dev;
 | 
						|
  testMachines = listSubdirectories ../machines/operator;
 | 
						|
 | 
						|
  nixosConfigurations =
 | 
						|
    genAttrs machines (makeConfiguration false)
 | 
						|
    // genAttrs testMachines (makeConfiguration true);
 | 
						|
  vmOptions =
 | 
						|
    filterAttrs (_: value: value != null) # Filter out non-Fediversity VMs
 | 
						|
      (genAttrs machines (makeVmOptions false) // genAttrs testMachines (makeVmOptions true));
 | 
						|
 | 
						|
in
 | 
						|
{
 | 
						|
  _class = "flake";
 | 
						|
 | 
						|
  ## - Each normal or test machine gets a NixOS configuration.
 | 
						|
  ## - Each normal or test machine gets a VM options entry.
 | 
						|
  ## - Each normal machine gets a deployment.
 | 
						|
  ## - We add a “default” deployment with all normal machines.
 | 
						|
  ## - We add a “test” deployment with all test machines.
 | 
						|
  nixops4Deployments = genAttrs machines makeDeployment' // {
 | 
						|
    default = makeDeployment machines;
 | 
						|
    test = makeTestDeployment (
 | 
						|
      fromJSON (
 | 
						|
        let
 | 
						|
          env = builtins.getEnv "DEPLOYMENT";
 | 
						|
        in
 | 
						|
        if env != "" then
 | 
						|
          env
 | 
						|
        else
 | 
						|
          builtins.trace "env var DEPLOYMENT not set, falling back to ../deployment/configuration.sample.json!" (readFile ../deployment/configuration.sample.json)
 | 
						|
      )
 | 
						|
    );
 | 
						|
  };
 | 
						|
  flake = { inherit nixosConfigurations vmOptions; };
 | 
						|
 | 
						|
  perSystem =
 | 
						|
    { pkgs, ... }:
 | 
						|
    {
 | 
						|
      checks =
 | 
						|
        mapAttrs' (name: nixosConfiguration: {
 | 
						|
          name = "nixosConfigurations-${name}";
 | 
						|
          value = nixosConfiguration.config.system.build.toplevel;
 | 
						|
        }) nixosConfigurations
 | 
						|
        // mapAttrs' (name: vmOptions: {
 | 
						|
          name = "vmOptions-${name}";
 | 
						|
          ## Check that VM options builds/evaluates correctly. `deepSeq e1
 | 
						|
          ## e2` evaluates `e1` strictly in depth before returning `e2`. We
 | 
						|
          ## use this trick because checks need to be derivations, which VM
 | 
						|
          ## options are not.
 | 
						|
          value = deepSeq vmOptions pkgs.hello;
 | 
						|
        }) vmOptions;
 | 
						|
    };
 | 
						|
}
 |