test cases dont work

This commit is contained in:
Snorre 2025-04-03 15:05:17 +02:00
parent dd45dffba1
commit 01fd56a42a
4 changed files with 152 additions and 78 deletions

View file

@ -1,7 +1,5 @@
{ nixpkgs, ... }: {nixpkgs, ...}: {
{ toXMLGeneric = let
toXMLGeneric =
let
toXMLRecursive = toXMLRecursive =
toXmlRecursive' toXmlRecursive'
"<?xml version='1.0' encoding='utf-8'?>\n" "<?xml version='1.0' encoding='utf-8'?>\n"
@ -13,29 +11,28 @@
else (" " + (indent (depth - 1))) else (" " + (indent (depth - 1)))
); );
toXmlRecursive' = str: depth: xml: toXmlRecursive' = str: depth: xml: let
let
parseTag = str: depth: xml: (builtins.concatStringsSep "" [ parseTag = str: depth: xml: (builtins.concatStringsSep "" [
str str
"${indent depth}<${xml.name}${ "${indent depth}<${xml.tag}${
if (builtins.hasAttr "content" xml) if (builtins.hasAttr "content" xml) && ((builtins.isString xml.content) || (builtins.isList xml.content) && ((builtins.length xml.content) > 0))
then ">" then ">"
else " " else " "
}" }"
( (
if (builtins.hasAttr "properties" xml) if (builtins.hasAttr "attrib" xml)
then then
(" " (" "
+ builtins.concatStringsSep " " (nixpkgs.lib.attrsets.mapAttrsToList + builtins.concatStringsSep " " (nixpkgs.lib.attrsets.mapAttrsToList
(name: value: "${name}=\"${nixpkgs.lib.strings.escapeXML value}\"") (name: value: "${name}=\"${nixpkgs.lib.strings.escapeXML value}\"")
xml.properties)) xml.attrib))
else "" else ""
) )
( (
if builtins.hasAttr "content" xml if (builtins.hasAttr "content" xml) && ((builtins.isString xml.content) || (builtins.isList xml.content) && ((builtins.length xml.content) > 0))
then ((toXmlRecursive' "\n" (depth + 1) xml.content) + "</${xml.name}>") then ((toXmlRecursive' "\n" (depth + 1) xml.content) + "</${xml.tag}>")
else "/>" else "/>"
) )
]); ]);
@ -48,8 +45,7 @@
then (builtins.toString xml) then (builtins.toString xml)
else if (builtins.isString xml) else if (builtins.isString xml)
then xml then xml
else throw "Cannot convert a ${builtins.typeOf xml} to XML"; else throw "Cannot convert a ${builtins.typeOf xml} to XML. ${toString (builtins.trace xml xml)}";
in in
toXMLRecursive; toXMLRecursive;
} }

View file

@ -1,12 +1,11 @@
{ {
config, config,
nixpkgs,
pkgs, pkgs,
lib, lib,
... ...
}: let }: let
cfg = config.services.declarative-jellyfin; cfg = config.services.declarative-jellyfin;
toXml = (import ../../lib {inherit nixpkgs;}).toXMLGeneric; toXml' = (import ../../lib {nixpkgs = pkgs;}).toXMLGeneric;
in in
with lib; { with lib; {
imports = [ imports = [
@ -23,24 +22,29 @@ in
mkIf cfg.enable mkIf cfg.enable
( (
let let
listOfStrPrepass = xml: (builtins.mapAttrs (name: value: prepass = x:
( if (builtins.isAttrs x)
if ((name == "content") && (builtins.isList value))
then then
if (builtins.all builtins.isString value) if !(builtins.hasAttr "tag" x)
then # listOf str then
(builtins.map (content: { attrsets.mapAttrsToList (tag: value: {
name = "string"; inherit tag;
inherit content; content = value;
})) })
else # Lis of something else x
warnIf (!(builtins.all builtins.isAttrs value)) "Recieved list of mixed values. This will most likely not evaluate correctly" (listOfStrPrepass value) else if (builtins.hasAttr "content" x)
else (listOfStrPrepass value) then {
) tag = x.tag;
xml)); content = prepass x.content;
toXml = name: x: (toXml { }
inherit name; else x
properties = { else if (builtins.isList x)
then builtins.map prepass x
else throw "wtf";
toXml = tag: x: (toXml' {
inherit tag;
attrib = {
"xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance"; "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance";
"xmlns:xsd" = "http://www.w3.org/2001/XMLSchema"; "xmlns:xsd" = "http://www.w3.org/2001/XMLSchema";
}; };
@ -49,9 +53,12 @@ in
in { in {
system.activationScripts."link-network-xml" = lib.stringAfter ["var"] ( system.activationScripts."link-network-xml" = lib.stringAfter ["var"] (
let let
content = toXml "NetworkConfiguration" (listOfStrPrepass cfg.network); content = toXml "NetworkConfiguration" (prepass cfg.network);
in '' in ''
${pkgs.writeTextFile}/bin/writeTextFile /var/lib/jellyfin/config/network.xml '${strings.escape ["'"] content}' mkdir -p /var/lib/jellyfin/config
if [ ! -f "/var/lib/jellyfin/config/network.xml" ]; then
echo '${strings.escape ["'"] content}' > /var/lib/jellyfin/config/network.xml
fi
'' ''
); );
} }

View file

@ -3,32 +3,40 @@ with lib; {
options.services.declarative-jellyfin.network = { options.services.declarative-jellyfin.network = {
BaseUrl = mkOption { BaseUrl = mkOption {
type = types.str; type = types.str;
default = "";
description = "Add a custom subdirectory to the server URL. For example: http://example.com/<baseurl>";
}; };
EnableHttps = mkEnableOption "Enable HTTPS"; EnableHttps = mkEnableOption "Enable HTTPS";
RequireHttps = mkEnableOption "Require HTTPS"; RequireHttps = mkEnableOption "Require HTTPS";
CertificatePath = mkOption { CertificatePath = mkOption {
type = with types; either str path; type = with types; either str path;
description = "Path to the certificate file"; default = "";
description = "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.";
}; };
CertificatePassword = mkOption { CertificatePassword = mkOption {
type = types.str; type = types.str;
description = "Password for the certificate"; default = "";
description = "If your certificate requires a password, please enter it here.";
}; };
InternalHttpPort = mkOption { InternalHttpPort = mkOption {
type = types.port; type = types.port;
description = "The internal HTTP port jellyfin is run at"; default = 8096;
description = "The TCP port number for the HTTP server.";
}; };
InternalHttpsPort = mkOption { InternalHttpsPort = mkOption {
type = types.port; type = types.port;
description = "The internal HTTPS port jellyfin is run at"; default = 8920;
description = "The TCP port number for the HTTPS server.";
}; };
PublicHttpPort = mkOption { PublicHttpPort = mkOption {
type = types.port; type = types.port;
description = "The public HTTP port jellyfin is run at"; default = 8096;
description = "The public port number that should be mapped to the local HTTP port.";
}; };
PublicHttpsPort = mkOption { PublicHttpsPort = mkOption {
type = types.port; type = types.port;
description = "The public HTTPS port jellyfin is run at"; default = 8920;
description = "The public port number that should be mapped to the local HTTPS port.";
}; };
AutoDiscovery = mkOption { AutoDiscovery = mkOption {
type = types.bool; type = types.bool;
@ -51,7 +59,15 @@ with lib; {
default = true; default = true;
description = "Enable remote access"; description = "Enable remote access";
}; };
LocalNetworkSubnets = mkEnableOption "UNIMPLEMENTED"; LocalNetworkSubnets = mkOption {
type = with types; listOf str;
default = [];
description = ''
List of IP addresses or IP/netmask entries for networks that will be considered on local network when enforcing bandwidth restrictions.
If set, all other IP addresses will be considered to be on the external network and will be subject to the external bandwidth restrictions.
If left empty, only the server's subnet is considered to be on the local network.
'';
};
LocalNetworkAddresses = mkEnableOption "UNIMPLEMENTED"; LocalNetworkAddresses = mkEnableOption "UNIMPLEMENTED";
KnownProxies = mkOption { KnownProxies = mkOption {
type = with types; listOf str; type = with types; listOf str;
@ -79,8 +95,12 @@ with lib; {
default = []; default = [];
}; };
RemoteIpFilter = mkOption { RemoteIpFilter = mkOption {
type = types.str; type = with types; listOf str;
description = "Remote ip filter"; default = [];
description = ''
List of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
If left empty, all remote addresses will be allowed.
'';
}; };
IsRemoteIPFilterBlacklist = mkEnableOption "Is the remote ip filter list a blacklist or a whitelist"; IsRemoteIPFilterBlacklist = mkEnableOption "Is the remote ip filter list a blacklist or a whitelist";
}; };

51
tests/networking.nix Normal file
View file

@ -0,0 +1,51 @@
{pkgs ? import <nixpkgs> {}, ...}: let
name = "networking";
in {
inherit name;
test = pkgs.nixosTest {
inherit name;
nodes = {
machine = {
config,
pkgs,
...
}: {
imports = [
../modules/default.nix
];
virtualisation.memorySize = 1024;
services.declarative-jellyfin = {
enable = true;
network = {
PublishedServerUriBySubnet = [
"all=https://test.test.test"
];
};
};
};
};
# stfu i dont care about python linting
skipLint = true;
testScript = ''
import xml.etree.ElementTree as ET
machine.start()
machine.wait_for_unit("multi-user.target");
with subtest("Jellyfin URI"):
machine.succeed("ls /var/lib/jellyfin")
tree = ET.parse("/var/lib/jellyfin/config/network.xml")
root = tree.getroot()
found = False
for child in root:
if child.tag == "PublishedServerUriBySubnet":
found = True
print(child)
assert False
'';
};
}