checkpoint
This commit is contained in:
parent
be2843ca80
commit
e07257e137
61 changed files with 258 additions and 156 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
{
|
{
|
||||||
description = "Nixos config flake";
|
description = "Nixos config flake";
|
||||||
|
|
||||||
|
nixConfig = {
|
||||||
|
warn-dirty = false;
|
||||||
|
};
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
{ config, lib, pkgs, namespace, system, inputs, ... }:
|
{ config, lib, pkgs, namespace, system, inputs, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib) mkIf mkEnableOption mkOption types toUpper toSentenceCase nameValuePair mapAttrs mapAttrs' concatMapAttrs concatMapStringsSep filterAttrsRecursive listToAttrs imap0 head drop length literalExpression attrNames;
|
inherit (lib) mkIf mkEnableOption mkOption toString types toUpper toSentenceCase nameValuePair mapAttrs mapAttrs' concatMapAttrs concatMapStringsSep filterAttrsRecursive listToAttrs imap0 head drop length literalExpression attrNames;
|
||||||
inherit (lib.${namespace}.strings) toSnakeCase;
|
inherit (lib.${namespace}.strings) toSnakeCase;
|
||||||
|
|
||||||
cfg = config.${namespace}.services.authentication.zitadel;
|
cfg = config.${namespace}.services.authentication.zitadel;
|
||||||
|
port = 3010;
|
||||||
|
|
||||||
database = "zitadel";
|
database = "zitadel";
|
||||||
in
|
in
|
||||||
|
|
@ -543,12 +544,12 @@ in
|
||||||
networking.caddy = {
|
networking.caddy = {
|
||||||
hosts = {
|
hosts = {
|
||||||
"auth.kruining.eu" = ''
|
"auth.kruining.eu" = ''
|
||||||
reverse_proxy h2c://[::1]:9092
|
reverse_proxy h2c://[::1]:${toString port}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
(auth) {
|
(auth) {
|
||||||
forward_auth h2c://[::1]:9092 {
|
forward_auth h2c://[::1]:${toString port} {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
}
|
}
|
||||||
|
|
@ -612,7 +613,7 @@ in
|
||||||
masterKeyFile = config.sops.secrets."zitadel/masterKey".path;
|
masterKeyFile = config.sops.secrets."zitadel/masterKey".path;
|
||||||
tlsMode = "external";
|
tlsMode = "external";
|
||||||
settings = {
|
settings = {
|
||||||
Port = 9092;
|
Port = port;
|
||||||
|
|
||||||
ExternalDomain = "auth.kruining.eu";
|
ExternalDomain = "auth.kruining.eu";
|
||||||
ExternalPort = 443;
|
ExternalPort = 443;
|
||||||
|
|
@ -698,8 +699,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
||||||
|
|
||||||
# Secrets
|
# Secrets
|
||||||
sops = {
|
sops = {
|
||||||
secrets = {
|
secrets = {
|
||||||
|
|
|
||||||
|
|
@ -112,9 +112,29 @@ in {
|
||||||
(mkMautrix "mautrix-telegram" 2 {})
|
(mkMautrix "mautrix-telegram" 2 {})
|
||||||
(mkMautrix "mautrix-whatsapp" 3 {})
|
(mkMautrix "mautrix-whatsapp" 3 {})
|
||||||
(mkMautrix "arrtrix" 4 {
|
(mkMautrix "arrtrix" 4 {
|
||||||
settings.observability = {
|
environmentFile = config.sops.templates."arrtrix/secrets".path;
|
||||||
otlp_grpc_endpoint = "http://[::1]:1000";
|
|
||||||
service_name = "arrtrix";
|
settings = {
|
||||||
|
observability = {
|
||||||
|
otlp_grpc_endpoint = "http://[::1]:9062";
|
||||||
|
service_name = "arrtrix";
|
||||||
|
};
|
||||||
|
|
||||||
|
network.content = {
|
||||||
|
movies = {
|
||||||
|
url = "http://[::1]:${toString config.services.radarr.settings.server.port}";
|
||||||
|
api_key = "$RADARR_APIKEY";
|
||||||
|
root_folder_path = "/var/media/movies";
|
||||||
|
quality_profile_id = 5;
|
||||||
|
};
|
||||||
|
series = {
|
||||||
|
url = "http://[::1]:${toString config.services.radarr.settings.server.port}";
|
||||||
|
api_key = "$SONARR_APIKEY";
|
||||||
|
root_folder_path = "/var/media/series";
|
||||||
|
quality_profile_id = 5;
|
||||||
|
language_profile_id = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
@ -167,7 +187,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
sso = {
|
sso = {
|
||||||
client_whitelist = ["http://[::1]:9092/" "https://auth.kruining.eu/"];
|
client_whitelist = ["http://[::1]:${toString config.services.zitadel.settings.Port}/" "https://auth.kruining.eu/"];
|
||||||
update_profile_information = true;
|
update_profile_information = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -365,6 +385,14 @@ in {
|
||||||
'';
|
'';
|
||||||
restartUnits = ["matrix-synapse.service"];
|
restartUnits = ["matrix-synapse.service"];
|
||||||
};
|
};
|
||||||
|
"arrtrix/secrets" = {
|
||||||
|
owner = "arrtrix";
|
||||||
|
content = ''
|
||||||
|
RADARR_APIKEY=${config.sops.placeholder."radarr/apikey"}
|
||||||
|
SONARR_APIKEY=${config.sops.placeholder."sonarr/apikey"}
|
||||||
|
'';
|
||||||
|
restartUnits = ["arrtrix.service"];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
${namespace}.services.networking.caddy.hosts = {
|
# ${namespace}.services.networking.caddy.hosts = {
|
||||||
"https://${config.networking.hostName}:443" = ''
|
# "https://${config.networking.hostName}.arda:443" = ''
|
||||||
reverse_proxy http://[::1]:2000
|
# reverse_proxy http://[::1]:2000
|
||||||
'';
|
# '';
|
||||||
};
|
# };
|
||||||
|
|
||||||
services.glance = {
|
services.glance = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ in {
|
||||||
auth.authenticationMethod = "External";
|
auth.authenticationMethod = "External";
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
bindaddress = "0.0.0.0";
|
# bindaddress = "0.0.0.0";
|
||||||
|
bindaddress = "[::]";
|
||||||
port = port;
|
port = port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -194,7 +195,7 @@ in {
|
||||||
source = "devopsarr/${service}";
|
source = "devopsarr/${service}";
|
||||||
version =
|
version =
|
||||||
{
|
{
|
||||||
radarr = "2.3.3";
|
radarr = "2.3.5";
|
||||||
sonarr = "3.4.0";
|
sonarr = "3.4.0";
|
||||||
prowlarr = "3.1.0";
|
prowlarr = "3.1.0";
|
||||||
lidarr = "1.13.0";
|
lidarr = "1.13.0";
|
||||||
|
|
@ -217,10 +218,15 @@ in {
|
||||||
{
|
{
|
||||||
method = 1; # HTTP METHOD 1=POST, 2=PUT
|
method = 1; # HTTP METHOD 1=POST, 2=PUT
|
||||||
name = "Arrtrix";
|
name = "Arrtrix";
|
||||||
url = "http://[::1]${toString config'.services.arrtrix.settings.appservice.port}";
|
url = "http://localhost:${toString config'.services.arrtrix.settings.appservice.port}/_arrtrix/webhook";
|
||||||
|
|
||||||
|
on_grab = true;
|
||||||
|
on_download = true;
|
||||||
|
on_rename = true;
|
||||||
|
on_upgrade = true;
|
||||||
}
|
}
|
||||||
// (lib.optionalAttrs (lib.elem service ["radarr" "whisparr"]) {
|
// (lib.optionalAttrs (lib.elem service ["radarr" "whisparr"]) {
|
||||||
onMovieDelete = true;
|
on_movie_delete = true;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -244,15 +250,25 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
"${service}_download_client_sabnzbd" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
|
"${service}_download_client_sabnzbd" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
|
||||||
"main" = {
|
"main" =
|
||||||
name = "SABnzbd";
|
{
|
||||||
enable = true;
|
name = "SABnzbd";
|
||||||
priority = 1;
|
enable = true;
|
||||||
host = "localhost";
|
priority = 1;
|
||||||
api_key = lib.tfRef "var.sabnzbd_api_key";
|
host = "localhost";
|
||||||
url_base = "/";
|
api_key = lib.tfRef "var.sabnzbd_api_key";
|
||||||
port = 2090;
|
url_base = "/";
|
||||||
};
|
port = 2090;
|
||||||
|
}
|
||||||
|
// ({
|
||||||
|
radarr = {movie_category = "movies";};
|
||||||
|
sonarr = {tv_category = "tv";};
|
||||||
|
lidarr = {music_category = "audio";};
|
||||||
|
whisparr = {movie_category = "movies";};
|
||||||
|
readarr = {book_category = "Default";};
|
||||||
|
}.${
|
||||||
|
service
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// (lib.optionalAttrs (service == "prowlarr") (
|
// (lib.optionalAttrs (service == "prowlarr") (
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf hasHosts {
|
config = mkIf hasHosts {
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
|
||||||
services.caddy = {
|
services.caddy = {
|
||||||
enable = cfg.enable;
|
enable = cfg.enable;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
{ config, lib, namespace, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (builtins) toString;
|
inherit (builtins) toString;
|
||||||
inherit (lib) mkEnableOption mkIf;
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
|
|
@ -9,8 +13,7 @@ let
|
||||||
otlpGrpcPort = 9071;
|
otlpGrpcPort = 9071;
|
||||||
otlpHttpPort = 9072;
|
otlpHttpPort = 9072;
|
||||||
tempoOtlpGrpcPort = 9062;
|
tempoOtlpGrpcPort = 9062;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options.${namespace}.services.observability.alloy = {
|
options.${namespace}.services.observability.alloy = {
|
||||||
enable = mkEnableOption "enable Grafana Alloy";
|
enable = mkEnableOption "enable Grafana Alloy";
|
||||||
};
|
};
|
||||||
|
|
@ -21,7 +24,7 @@ in
|
||||||
configPath = "/etc/alloy";
|
configPath = "/etc/alloy";
|
||||||
extraFlags = [
|
extraFlags = [
|
||||||
"--disable-reporting"
|
"--disable-reporting"
|
||||||
"--server.http.listen-addr=0.0.0.0:${toString httpPort}"
|
"--server.http.listen-addr=[::]:${toString httpPort}"
|
||||||
"--storage.path=/var/lib/alloy"
|
"--storage.path=/var/lib/alloy"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
@ -29,11 +32,11 @@ in
|
||||||
environment.etc."alloy/config.alloy".text = ''
|
environment.etc."alloy/config.alloy".text = ''
|
||||||
otelcol.receiver.otlp "default" {
|
otelcol.receiver.otlp "default" {
|
||||||
grpc {
|
grpc {
|
||||||
endpoint = "127.0.0.1:${toString otlpGrpcPort}"
|
endpoint = "[::1]:${toString otlpGrpcPort}"
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
endpoint = "127.0.0.1:${toString otlpHttpPort}"
|
endpoint = "[::1]:${toString otlpHttpPort}"
|
||||||
}
|
}
|
||||||
|
|
||||||
output {
|
output {
|
||||||
|
|
@ -60,13 +63,13 @@ in
|
||||||
|
|
||||||
prometheus.remote_write "local" {
|
prometheus.remote_write "local" {
|
||||||
endpoint {
|
endpoint {
|
||||||
url = "http://127.0.0.1:${toString config.services.prometheus.port}/api/v1/write"
|
url = "http://[::1]:${toString config.services.prometheus.port}/api/v1/write"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
otelcol.exporter.otlp "tempo" {
|
otelcol.exporter.otlp "tempo" {
|
||||||
client {
|
client {
|
||||||
endpoint = "127.0.0.1:${toString tempoOtlpGrpcPort}"
|
endpoint = "[::1]:${toString tempoOtlpGrpcPort}"
|
||||||
|
|
||||||
tls {
|
tls {
|
||||||
insecure = true
|
insecure = true
|
||||||
|
|
@ -75,6 +78,6 @@ in
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ httpPort ];
|
networking.firewall.allowedTCPPorts = [httpPort];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ in {
|
||||||
settings = {
|
settings = {
|
||||||
server = {
|
server = {
|
||||||
http_port = 9010;
|
http_port = 9010;
|
||||||
http_addr = "0.0.0.0";
|
http_addr = "::";
|
||||||
domain = "ulmo";
|
domain = "ulmo";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -102,43 +102,43 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
datasources.settings.datasources = [
|
datasources.settings.datasources = [
|
||||||
{
|
# {
|
||||||
name = "Prometheus";
|
# name = "Prometheus";
|
||||||
uid = "prometheus";
|
# uid = "prometheus";
|
||||||
type = "prometheus";
|
# type = "prometheus";
|
||||||
url = "http://localhost:9020";
|
# url = "http://[::1]:9020";
|
||||||
isDefault = true;
|
# isDefault = true;
|
||||||
editable = false;
|
# editable = false;
|
||||||
}
|
# }
|
||||||
|
|
||||||
{
|
# {
|
||||||
name = "Loki";
|
# name = "Loki";
|
||||||
uid = "loki";
|
# uid = "loki";
|
||||||
type = "loki";
|
# type = "loki";
|
||||||
url = "http://localhost:9030";
|
# url = "http://[::1]:9030";
|
||||||
editable = false;
|
# editable = false;
|
||||||
}
|
# }
|
||||||
|
|
||||||
{
|
# {
|
||||||
name = "Tempo";
|
# name = "Tempo";
|
||||||
uid = "tempo";
|
# uid = "tempo";
|
||||||
type = "tempo";
|
# type = "tempo";
|
||||||
url = "http://localhost:9060";
|
# url = "http://localhost:9060";
|
||||||
editable = false;
|
# editable = false;
|
||||||
jsonData = {
|
# jsonData = {
|
||||||
nodeGraph.enabled = true;
|
# nodeGraph.enabled = true;
|
||||||
serviceMap.datasourceUid = "prometheus";
|
# serviceMap.datasourceUid = "prometheus";
|
||||||
tracesToLogsV2 = {
|
# tracesToLogsV2 = {
|
||||||
datasourceUid = "loki";
|
# datasourceUid = "loki";
|
||||||
filterByTraceID = true;
|
# filterByTraceID = true;
|
||||||
spanStartTimeShift = "-1h";
|
# spanStartTimeShift = "-1h";
|
||||||
spanEndTimeShift = "1h";
|
# spanEndTimeShift = "1h";
|
||||||
};
|
# };
|
||||||
};
|
# };
|
||||||
}
|
# }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
postgresql = {
|
postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
{ config, lib, namespace, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkEnableOption mkIf;
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
cfg = config.${namespace}.services.observability.tempo;
|
cfg = config.${namespace}.services.observability.tempo;
|
||||||
|
|
@ -8,8 +12,7 @@ let
|
||||||
grpcPort = 9061;
|
grpcPort = 9061;
|
||||||
otlpGrpcPort = 9062;
|
otlpGrpcPort = 9062;
|
||||||
otlpHttpPort = 9063;
|
otlpHttpPort = 9063;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options.${namespace}.services.observability.tempo = {
|
options.${namespace}.services.observability.tempo = {
|
||||||
enable = mkEnableOption "enable Grafana Tempo";
|
enable = mkEnableOption "enable Grafana Tempo";
|
||||||
};
|
};
|
||||||
|
|
@ -22,15 +25,15 @@ in
|
||||||
search_enabled = true;
|
search_enabled = true;
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
http_listen_address = "0.0.0.0";
|
http_listen_address = "[::]";
|
||||||
http_listen_port = httpPort;
|
http_listen_port = httpPort;
|
||||||
grpc_listen_address = "127.0.0.1";
|
grpc_listen_address = "[::1]";
|
||||||
grpc_listen_port = grpcPort;
|
grpc_listen_port = grpcPort;
|
||||||
};
|
};
|
||||||
|
|
||||||
distributor.receivers.otlp.protocols = {
|
distributor.receivers.otlp.protocols = {
|
||||||
grpc.endpoint = "127.0.0.1:${builtins.toString otlpGrpcPort}";
|
grpc.endpoint = "[::1]:${builtins.toString otlpGrpcPort}";
|
||||||
http.endpoint = "127.0.0.1:${builtins.toString otlpHttpPort}";
|
http.endpoint = "[::1]:${builtins.toString otlpHttpPort}";
|
||||||
};
|
};
|
||||||
|
|
||||||
storage.trace = {
|
storage.trace = {
|
||||||
|
|
@ -43,6 +46,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ httpPort ];
|
networking.firewall.allowedTCPPorts = [httpPort];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,18 @@ in {
|
||||||
example = {};
|
example = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environmentFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
File containing environment variables to be passed to the arrtrix service.
|
||||||
|
If an environment variable `ARRTRIX_BRIDGE_LOGIN_SHARED_SECRET` is set,
|
||||||
|
then its value will be used in the configuration file for the option
|
||||||
|
`double_puppet.secrets` without leaking it to the store, using the configured
|
||||||
|
`homeserver.domain` as key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
serviceDependencies = lib.mkOption {
|
serviceDependencies = lib.mkOption {
|
||||||
type = with lib.types; listOf str;
|
type = with lib.types; listOf str;
|
||||||
default =
|
default =
|
||||||
|
|
@ -168,6 +180,7 @@ in {
|
||||||
|
|
||||||
StateDirectory = baseNameOf dataDir;
|
StateDirectory = baseNameOf dataDir;
|
||||||
WorkingDirectory = dataDir;
|
WorkingDirectory = dataDir;
|
||||||
|
EnvironmentFile = cfg.environmentFile;
|
||||||
|
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${lib.getExe cfg.package} --config='${settingsFile}' --registration='${registrationFile}'
|
${lib.getExe cfg.package} --config='${settingsFile}' --registration='${registrationFile}'
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,16 @@ func updateConfigFromEnv(cfg, networkData any, prefix string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
key = strings.ToLower(key)
|
key = strings.ToLower(key)
|
||||||
|
lookupKey := key
|
||||||
if !strings.ContainsRune(key, '.') {
|
if !strings.ContainsRune(key, '.') {
|
||||||
key = strings.ReplaceAll(key, "__", ".")
|
key = strings.ReplaceAll(key, "__", ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
path := strings.Split(key, ".")
|
path := strings.Split(key, ".")
|
||||||
field, ok := reflectGetFromMainOrNetwork(cfgVal, networkVal, path)
|
field, ok := reflectGetFromMainOrNetwork(cfgVal, networkVal, path)
|
||||||
|
if !ok && !strings.ContainsRune(lookupKey, '.') {
|
||||||
|
field, ok = reflectGetFromMainOrNetworkTokens(cfgVal, networkVal, strings.Split(lookupKey, "_"))
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s not found", formatKey(path))
|
return fmt.Errorf("%s not found", formatKey(path))
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +84,13 @@ func reflectGetFromMainOrNetwork(main, network reflect.Value, path []string) (*r
|
||||||
return reflectGetYAML(main, path)
|
return reflectGetYAML(main, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reflectGetFromMainOrNetworkTokens(main, network reflect.Value, tokens []string) (*reflectedField, bool) {
|
||||||
|
if len(tokens) > 0 && normalizeKey(tokens[0]) == "network" {
|
||||||
|
return reflectGetYAMLTokens(network, tokens[1:])
|
||||||
|
}
|
||||||
|
return reflectGetYAMLTokens(main, tokens)
|
||||||
|
}
|
||||||
|
|
||||||
func reflectGetYAML(value reflect.Value, path []string) (*reflectedField, bool) {
|
func reflectGetYAML(value reflect.Value, path []string) (*reflectedField, bool) {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return &reflectedField{value: value, valueKind: value.Kind()}, true
|
return &reflectedField{value: value, valueKind: value.Kind()}, true
|
||||||
|
|
@ -108,6 +119,41 @@ func reflectGetYAML(value reflect.Value, path []string) (*reflectedField, bool)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reflectGetYAMLTokens(value reflect.Value, tokens []string) (*reflectedField, bool) {
|
||||||
|
if len(tokens) == 0 {
|
||||||
|
return &reflectedField{value: value, valueKind: value.Kind()}, true
|
||||||
|
}
|
||||||
|
if value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
return &reflectedField{
|
||||||
|
value: value,
|
||||||
|
valueKind: value.Type().Elem().Kind(),
|
||||||
|
remainingPath: []string{strings.Join(tokens, "_")},
|
||||||
|
}, true
|
||||||
|
case reflect.Struct:
|
||||||
|
fields := reflect.VisibleFields(value.Type())
|
||||||
|
for _, field := range fields {
|
||||||
|
name := yamlFieldName(field)
|
||||||
|
if name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
normalizedFieldName := normalizeKey(name)
|
||||||
|
for i := len(tokens); i >= 1; i-- {
|
||||||
|
if normalizeKey(strings.Join(tokens[:i], "_")) != normalizedFieldName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return reflectGetYAMLTokens(value.FieldByIndex(field.Index), tokens[i:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
func yamlFieldName(field reflect.StructField) string {
|
func yamlFieldName(field reflect.StructField) string {
|
||||||
parts := strings.SplitN(field.Tag.Get("yaml"), ",", 2)
|
parts := strings.SplitN(field.Tag.Get("yaml"), ",", 2)
|
||||||
switch name := parts[0]; {
|
switch name := parts[0]; {
|
||||||
|
|
@ -120,6 +166,10 @@ func yamlFieldName(field reflect.StructField) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeKey(value string) string {
|
||||||
|
return strings.ReplaceAll(strings.ToLower(value), "_", "")
|
||||||
|
}
|
||||||
|
|
||||||
func setReflectedValue(field *reflectedField, path []string, raw string) error {
|
func setReflectedValue(field *reflectedField, path []string, raw string) error {
|
||||||
parsed, err := parseValue(field.valueKind, raw, path)
|
parsed, err := parseValue(field.valueKind, raw, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
57
packages/arrtrix/pkg/runtime/envconfig_test.go
Normal file
57
packages/arrtrix/pkg/runtime/envconfig_test.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
|
||||||
|
|
||||||
|
"sneeuwvlok/packages/arrtrix/pkg/connector"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUpdateConfigFromEnvSupportsFlatUnderscorePaths(t *testing.T) {
|
||||||
|
t.Setenv("ARRTRIX_NETWORK_CONTENT_MOVIES_APIKEY", "radarr-secret")
|
||||||
|
|
||||||
|
cfg := &bridgeconfig.Config{}
|
||||||
|
network := &connector.Config{}
|
||||||
|
if err := updateConfigFromEnv(cfg, network, "ARRTRIX_"); err != nil {
|
||||||
|
t.Fatalf("updateConfigFromEnv returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Content.Movies.APIKey != "radarr-secret" {
|
||||||
|
t.Fatalf("expected movies api key to be overridden, got %q", network.Content.Movies.APIKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateConfigFromEnvSupportsExplicitUnderscoredFieldNames(t *testing.T) {
|
||||||
|
t.Setenv("ARRTRIX_NETWORK_CONTENT_MOVIES_ROOT_FOLDER_PATH", "/data/movies")
|
||||||
|
|
||||||
|
cfg := &bridgeconfig.Config{}
|
||||||
|
network := &connector.Config{}
|
||||||
|
if err := updateConfigFromEnv(cfg, network, "ARRTRIX_"); err != nil {
|
||||||
|
t.Fatalf("updateConfigFromEnv returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Content.Movies.RootFolderPath != "/data/movies" {
|
||||||
|
t.Fatalf("expected root folder path to be overridden, got %q", network.Content.Movies.RootFolderPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateConfigFromEnvSupportsDoubleUnderscorePaths(t *testing.T) {
|
||||||
|
t.Setenv("ARRTRIX_NETWORK__CONTENT__SERIES__API_KEY", "sonarr-secret")
|
||||||
|
|
||||||
|
cfg := &bridgeconfig.Config{}
|
||||||
|
network := &connector.Config{}
|
||||||
|
if err := updateConfigFromEnv(cfg, network, "ARRTRIX_"); err != nil {
|
||||||
|
t.Fatalf("updateConfigFromEnv returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Content.Series.APIKey != "sonarr-secret" {
|
||||||
|
t.Fatalf("expected series api key to be overridden, got %q", network.Content.Series.APIKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
code := m.Run()
|
||||||
|
os.Exit(code)
|
||||||
|
}
|
||||||
|
|
@ -39,31 +39,6 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# virtualisation = {
|
|
||||||
# containers.enable = true;
|
|
||||||
# podman = {
|
|
||||||
# enable = true;
|
|
||||||
# dockerCompat = true;
|
|
||||||
# };
|
|
||||||
|
|
||||||
# oci-containers = {
|
|
||||||
# backend = "podman";
|
|
||||||
# containers = {
|
|
||||||
# homey = {
|
|
||||||
# image = "ghcr.io/athombv/homey-shs:latest";
|
|
||||||
# autoStart = true;
|
|
||||||
# privileged = true;
|
|
||||||
# volumes = [
|
|
||||||
# "/home/chris/.homey-shs:/homey/user"
|
|
||||||
# ];
|
|
||||||
# ports = [
|
|
||||||
# "4859:4859"
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
sneeuwvlok = {
|
sneeuwvlok = {
|
||||||
services = {
|
services = {
|
||||||
backup.borg.enable = true;
|
backup.borg.enable = true;
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/machines/ulmo
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../../../../../../sops/users/chris
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue