{ config, lib, confLib, ... }@args: with lib; let machine = { config, ...}: { options = { managed = mkOption { type = types.nullOr types.bool; default = null; apply = v: if !isNull v then v else if elem config.spin [ "nixos" "vpsadminos" ] then true else false; description = '' Determines whether the machine is managed using confctl or not By default, NixOS and vpsAdminOS machines are managed by confctl. ''; }; spin = mkOption { type = types.enum [ "openvz" "nixos" "vpsadminos" "other" ]; description = "OS type"; }; swpins = { channels = mkOption { type = types.listOf types.str; default = []; description = '' List of channels from to use on this machine ''; }; pins = mkOption { type = types.attrsOf (types.submodule swpinOptions.specModule); default = {}; description = '' List of swpins for this machine, which can supplement or override swpins from configured channels ''; }; }; addresses = mkOption { type = types.nullOr (types.submodule addresses); default = null; description = '' IP addresses ''; }; netboot = { enable = mkEnableOption "Include this system on pxe servers"; macs = mkOption { type = types.listOf types.str; default = []; description = '' List of MAC addresses for iPXE node auto-detection ''; }; }; host = mkOption { type = types.nullOr (types.submodule host); default = null; }; labels = mkOption { type = types.attrs; default = {}; description = '' Optional user-defined labels to classify the machine ''; }; tags = mkOption { type = types.listOf types.str; default = []; description = '' Optional user-defined tags to classify the machine ''; }; nix = { nixPath = mkOption { type = types.listOf types.str; default = []; description = '' List of extra paths added to environment variable NIX_PATH for nix-build ''; }; }; buildGenerations = { min = mkOption { type = types.nullOr types.int; default = null; description = '' The minimum number of build generations to be kept on the build machine. ''; }; max = mkOption { type = types.nullOr types.int; default = null; description = '' The maximum number of build generations to be kept on the build machine. ''; }; maxAge = mkOption { type = types.nullOr types.int; default = null; description = '' Delete build generations older than seconds from the build machine. Old generations are deleted even if is not reached. ''; }; }; hostGenerations = { min = mkOption { type = types.nullOr types.int; default = null; description = '' The minimum number of generations to be kept on the machine. ''; }; max = mkOption { type = types.nullOr types.int; default = null; description = '' The maximum number of generations to be kept on the machine. ''; }; maxAge = mkOption { type = types.nullOr types.int; default = null; description = '' Delete generations older than seconds from the machine. Old generations are deleted even if is not reached. ''; }; collectGarbage = mkOption { type = types.nullOr types.bool; default = null; description = "Run nix-collect-garbage"; }; }; healthChecks = { systemd = { enable = mkOption { type = types.bool; default = true; description = '' Enable systemd checks, enabled by default ''; }; systemProperties = mkOption { type = types.listOf (types.submodule systemdProperty); default = [ { property = "SystemState"; value = "running"; } ]; description = '' Check systemd manager properties reported by systemctl show ''; }; unitProperties = mkOption { type = types.attrsOf (types.listOf (types.submodule systemdProperty)); default = {}; example = literalExpression '' { "firewall.service" = [ { property = "ActiveState"; value = "active"; } ]; } ''; description = '' Check systemd unit properties reported by systemctl show ''; }; }; builderCommands = mkOption { type = types.listOf (types.submodule checkCommand); default = []; example = literalExpression '' [ { description = "ping"; command = [ "ping" "-c1" "{host.fqdn}" ]; } ] ''; description = '' Check commands run on the build machine ''; }; machineCommands = mkOption { type = types.listOf (types.submodule checkCommand); default = []; example = literalExpression '' [ { description = "curl"; command = [ "curl" "-s" "http://localhost:80" ]; } ] ''; description = '' Check commands run on the target machine Note that the commands have to be available on the machine. ''; }; }; }; }; swpinOptions = import ../../lib/swpins/options.nix { inherit lib; }; addresses = { config, ... }: { options = { primary = mkOption { type = types.nullOr (types.submodule (confLib.mkOptions.addresses 4)); default = if config.v4 != [] then head config.v4 else if config.v6 != [] then head config.v6 else null; description = '' Default address other machines should use to connect to this machine Defaults to the first IPv4 address if not set ''; }; v4 = mkOption { type = types.listOf (types.submodule (confLib.mkOptions.addresses 4)); default = []; description = '' List of IPv4 addresses this machine responds to ''; }; v6 = mkOption { type = types.listOf (types.submodule (confLib.mkOptions.addresses 6)); default = []; description = '' List of IPv6 addresses this machine responds to ''; }; }; }; host = { config, ... }: { options = { name = mkOption { type = types.nullOr types.str; default = null; description = '' Host name ''; }; location = mkOption { type = types.nullOr types.str; default = null; description = '' Host location domain ''; }; domain = mkOption { type = types.nullOr types.str; default = null; description = '' Host domain ''; }; fullDomain = mkOption { type = types.nullOr types.str; default = null; description = '' Domain including location, i.e. FQDN without host name ''; apply = v: if isNull v && !isNull config.domain then concatStringsSep "." ( (optional (!isNull config.location) config.location) ++ [ config.domain ] ) else v; }; fqdn = mkOption { type = types.nullOr types.str; default = null; description = '' Host FQDN ''; apply = v: if isNull v && !isNull config.name && !isNull config.domain then concatStringsSep "." ( [ config.name ] ++ (optional (!isNull config.location) config.location) ++ [ config.domain ] ) else v; }; target = mkOption { type = types.nullOr types.str; default = config.fqdn; description = '' Address/host to which the configuration is deployed to ''; }; }; }; systemdProperty = { config, ... }: { options = { property = mkOption { type = types.str; description = "systemd property name"; }; value = mkOption { type = types.str; description = "value to be checked"; }; timeout = mkOption { type = types.ints.unsigned; default = 60; description = "Max number of seconds to wait for the check to pass"; }; cooldown = mkOption { type = types.ints.unsigned; default = 3; description = "Number of seconds in between check attempts"; }; }; }; checkCommand = { config, ... }: { options = { description = mkOption { type = types.str; default = ""; description = "Command description"; }; command = mkOption { type = types.listOf types.str; description = '' Command and its arguments It is possible to access machine attributes as from CLI using curly brackets. For example, {host.fqdn} would be replaced by machine FQDN. See confctl ls -L for a list of available attributes. ''; }; exitStatus = mkOption { type = types.ints.unsigned; default = 0; description = "Expected exit status"; }; standardOutput = { match = mkOption { type = types.nullOr types.str; default = null; description = "Standard output must match this string"; }; include = mkOption { type = types.listOf types.str; default = []; description = "Strings that must be included in standard output"; }; exclude = mkOption { type = types.listOf types.str; default = []; description = "Strings that must not be included in standard output"; }; }; standardError = { match = mkOption { type = types.nullOr types.str; default = null; description = "Standard error must match this string"; }; include = mkOption { type = types.listOf types.str; default = []; description = "String that must be included in standard error"; }; exclude = mkOption { type = types.listOf types.str; default = []; description = "String that must not be included in standard error"; }; }; timeout = mkOption { type = types.ints.unsigned; default = 60; description = "Max number of seconds to wait for the check to pass"; }; cooldown = mkOption { type = types.ints.unsigned; default = 3; description = "Number of seconds in between check attempts"; }; }; }; in { options = { cluster = mkOption { type = types.attrsOf (types.submodule machine); default = {}; }; }; }