refactor: move support functions to ./lib; change piholeConfiguration option to piholeConfig

The first part of the refactor simplifies the logic in the module and hides functions which are only used to extract container env vars.
Second the option renaming to piholeConfig unifies the naming with the hostConfig option.
This commit is contained in:
Christopher Bacher 2022-10-29 14:09:43 +02:00
parent f734aea139
commit c536fb7293
4 changed files with 73 additions and 63 deletions

View file

@ -6,7 +6,10 @@
flake-utils.url = "github:numtide/flake-utils";
linger.url = "github:mindsbackyard/linger-flake";
linger = {
url = "github:mindsbackyard/linger-flake";
inputs.flake-utils.follows = "flake-utils";
};
};
outputs = { self, nixpkgs, flake-utils, linger }: with flake-utils.lib; eachSystem (with system; [ x86_64-linux aarch64-linux ]) (curSystem:

40
lib/options.nix Normal file
View file

@ -0,0 +1,40 @@
nixpkgsLib: with nixpkgsLib; {
mkContainerEnvOption = { envVar, ... }@optionAttrs:
(mkOption (removeAttrs optionAttrs [ "envVar" ]))
// { inherit envVar; };
mkHostPortsOption = { service, publicDefaultPort }: {
hostInternalPort = mkOption {
type = types.port;
description = ''
The internal port on the host on which the ${service} port of the pihole container should be exposed.
Only needs to be specified if he container port should be exposed
or if the port-forwarding for this service is enabled.
As the pihole container is running rootless this cannot be a privileged port (<1024).
'';
};
hostPublicPort = mkOption {
type = types.port;
description = ''
The public port on the host on which the ${service} port of the pihole container should be forwared to.
This option can be used to together with the according `forwardPublicToInternal` to expose a pihole subservice on a privileged port,
e.g., if you want to expose the DNS service on port 53.
'';
default = publicDefaultPort;
};
forwardPublicToInternal = mkOption {
type = types.bool;
description = ''
Enable port-forwarding between the public & the internal port of the host.
This effectively makes pihole's ${service} port available on the network to which the host is connected to.
Use this option together with the according `hostPublicPort` to expose a pihole subservice on a privileged port.
'';
default = false;
};
};
}

View file

@ -1,5 +1,5 @@
{
collectAttrFragments = predicate: attrs: with builtins; let
with builtins; let
collectAttrFragments = predicate: attrs: let
_collectAttrFragments = attrs:
concatMap (key: _collectAttrFragmentsBelowKey key attrs.${key}) (attrNames attrs)
;
@ -12,7 +12,7 @@
in _collectAttrFragments attrs
;
accessValueOfFragment = attrs: fragment: with builtins; let
accessValueOfFragment = attrs: fragment: let
_accessValueOfFragment = value: fragment:
if fragment == [] then value
else _accessValueOfFragment (value.${head fragment}) (tail fragment)
@ -20,8 +20,26 @@
in _accessValueOfFragment attrs fragment
;
toEnvValue = value: with builtins;
if isBool value then (if value then "true" else "false")
else if isList value then "[${concatStringSep ";" value}]"
else value;
toEnvValue = value:
if isBool value then (if value then "true" else "false")
else if isList value then "[${concatStringSep ";" value}]"
else value
;
in {
extractContainerEnvVars = piholeOptionDeclarations: piholeOptionDefinitions: let
_opt = piholeOptionDeclarations;
_cfg = piholeOptionDefinitions;
_envVarFragments = collectAttrFragments (value: isAttrs value && value ? "envVar") _opt.piholeConfig;
in filter
(envVar: envVar.value != null)
(map
(fragment: {
name = getAttr "envVar" (accessValueOfFragment _opt.piholeConfig fragment);
value = toEnvValue (accessValueOfFragment _cfg.piholeConfig fragment);
})
_envVarFragments
)
;
}

View file

@ -1,50 +1,12 @@
{ piholeFlake, lingerFlake }: { config, pkgs, lib, ... }: with lib; with builtins; let
inherit (import ../lib/util.nix) collectAttrFragments accessValueOfFragment toEnvValue;
inherit (import ../lib/util.nix) extractContainerEnvVars;
inherit (import ../lib/options.nix lib) mkContainerEnvOption mkHostPortsOption;
cfg = config.services.pihole;
hostUserCfg = config.users.users.${cfg.hostConfig.user};
systemTimeZone = config.time.timeZone;
defaultPiholeVolumesDir = "${config.users.users.${cfg.hostConfig.user}.home}/pihole-volumes";
mkContainerEnvOption = { envVar, ... }@optionAttrs:
(mkOption (removeAttrs optionAttrs [ "envVar" ]))
// { inherit envVar; };
mkHostPortsOption = { service, publicDefaultPort }: {
hostInternalPort = mkOption {
type = types.port;
description = ''
The internal port on the host on which the ${service} port of the pihole container should be exposed.
Only needs to be specified if he container port should be exposed
or if the port-forwarding for this service is enabled.
As the pihole container is running rootless this cannot be a privileged port (<1024).
'';
};
hostPublicPort = mkOption {
type = types.port;
description = ''
The public port on the host on which the ${service} port of the pihole container should be forwared to.
This option can be used to together with the according `forwardPublicToInternal` to expose a pihole subservice on a privileged port,
e.g., if you want to expose the DNS service on port 53.
'';
default = publicDefaultPort;
};
forwardPublicToInternal = mkOption {
type = types.bool;
description = ''
Enable port-forwarding between the public & the internal port of the host.
This effectively makes pihole's ${service} port available on the network to which the host is connected to.
Use this option together with the according `hostPublicPort` to expose a pihole subservice on a privileged port.
'';
default = false;
};
};
in rec {
options = {
services.pihole = {
@ -113,7 +75,7 @@ in rec {
};
piholeConfiguration = {
piholeConfig = {
tz = mkContainerEnvOption {
type = types.str;
description = "Set your timezone to make sure logs rotate at local midnight instead of at UTC midnight.";
@ -334,20 +296,7 @@ in rec {
path = [ "/run/wrappers" ];
serviceConfig = let
opt = options.services.pihole;
containerEnvVars = let
envVarFragments = collectAttrFragments (value: isAttrs value && value ? "envVar") opt.piholeConfiguration;
in filter
(envVar: envVar.value != null)
(map
(fragment: {
name = getAttr "envVar" (accessValueOfFragment opt.piholeConfiguration fragment);
value = toEnvValue (accessValueOfFragment cfg.piholeConfiguration fragment);
})
envVarFragments
)
;
containerEnvVars = extractContainerEnvVars options.services.pihole cfg;
in {
ExecStartPre = mkIf cfg.hostConfig.persistVolumes [
"${pkgs.coreutils}/bin/mkdir -p ${cfg.hostConfig.volumesPath}/etc-pihole"