Skip to content

Commit 171a5c2

Browse files
committed
refactor services
1 parent e89d79e commit 171a5c2

18 files changed

Lines changed: 721 additions & 717 deletions

modules/arr-common/configModule.nix

Lines changed: 0 additions & 25 deletions
This file was deleted.

modules/arr-common/default.nix

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{
2+
lib,
3+
pkgs,
4+
serviceName,
5+
}:
6+
with lib; let
7+
mkWaitForApiScript = import ./mkWaitForApiScript.nix {inherit lib pkgs;};
8+
capitalizedName = lib.toUpper (builtins.substring 0 1 serviceName) + builtins.substring 1 (-1) serviceName;
9+
in {
10+
options = mkOption {
11+
type = types.listOf (types.submodule {
12+
freeformType = types.attrsOf types.anything;
13+
options = {
14+
enable = mkOption {
15+
type = types.bool;
16+
default = true;
17+
description = "Whether or not this download client is enabled.";
18+
};
19+
name = mkOption {
20+
type = types.str;
21+
description = "User-defined name for the download client instance";
22+
};
23+
implementationName = mkOption {
24+
type = types.str;
25+
description = "Type of download client to configure (matches schema implementationName)";
26+
example = "SABnzbd";
27+
};
28+
apiKeyPath = mkOption {
29+
type = types.str;
30+
description = "Path to file containing the API key for the download client";
31+
};
32+
};
33+
});
34+
default = [];
35+
description = ''
36+
List of download clients to configure via the API /downloadclient endpoint.
37+
Any additional attributes beyond name, implementationName, and apiKeyPath
38+
will be applied as field values to the download client schema.
39+
The useSsl field defaults to true if not specified.
40+
'';
41+
};
42+
43+
mkService = serviceConfig: {
44+
description = "Configure ${serviceName} download clients via API";
45+
after = ["${serviceName}-config.service"];
46+
requires = ["${serviceName}-config.service"];
47+
wantedBy = ["multi-user.target"];
48+
49+
serviceConfig = {
50+
Type = "oneshot";
51+
RemainAfterExit = true;
52+
ExecStartPre = mkWaitForApiScript serviceName serviceConfig;
53+
};
54+
55+
script = ''
56+
set -eu
57+
58+
# Read API key secret
59+
API_KEY=$(cat ${serviceConfig.apiKeyPath})
60+
61+
BASE_URL="http://127.0.0.1:${builtins.toString serviceConfig.hostConfig.port}${serviceConfig.hostConfig.urlBase}/api/${serviceConfig.apiVersion}"
62+
63+
# Fetch all download client schemas
64+
echo "Fetching download client schemas..."
65+
SCHEMAS=$(${pkgs.curl}/bin/curl -sS -H "X-Api-Key: $API_KEY" "$BASE_URL/downloadclient/schema")
66+
67+
# Fetch existing download clients
68+
echo "Fetching existing download clients..."
69+
DOWNLOAD_CLIENTS=$(${pkgs.curl}/bin/curl -sS -H "X-Api-Key: $API_KEY" "$BASE_URL/downloadclient")
70+
71+
# Build list of configured download client names
72+
CONFIGURED_NAMES=$(cat <<'EOF'
73+
${builtins.toJSON (map (d: d.name) serviceConfig.downloadClients)}
74+
EOF
75+
)
76+
77+
# Delete download clients that are not in the configuration
78+
echo "Removing download clients not in configuration..."
79+
echo "$DOWNLOAD_CLIENTS" | ${pkgs.jq}/bin/jq -r '.[] | @json' | while IFS= read -r downloadClient; do
80+
CLIENT_NAME=$(echo "$downloadClient" | ${pkgs.jq}/bin/jq -r '.name')
81+
CLIENT_ID=$(echo "$downloadClient" | ${pkgs.jq}/bin/jq -r '.id')
82+
83+
if ! echo "$CONFIGURED_NAMES" | ${pkgs.jq}/bin/jq -e --arg name "$CLIENT_NAME" 'index($name)' >/dev/null 2>&1; then
84+
echo "Deleting download client not in config: $CLIENT_NAME (ID: $CLIENT_ID)"
85+
${pkgs.curl}/bin/curl -sSf -X DELETE \
86+
-H "X-Api-Key: $API_KEY" \
87+
"$BASE_URL/downloadclient/$CLIENT_ID" >/dev/null || echo "Warning: Failed to delete download client $CLIENT_NAME"
88+
fi
89+
done
90+
91+
${concatMapStringsSep "\n" (clientConfig: let
92+
clientName = clientConfig.name;
93+
inherit (clientConfig) implementationName;
94+
inherit (clientConfig) apiKeyPath;
95+
allOverrides = builtins.removeAttrs clientConfig ["implementationName" "apiKeyPath"];
96+
fieldOverrides = lib.filterAttrs (name: value: value != null && !lib.hasPrefix "_" name) allOverrides;
97+
fieldOverridesJson = builtins.toJSON fieldOverrides;
98+
in ''
99+
echo "Processing download client: ${clientName}"
100+
101+
apply_field_overrides() {
102+
local client_json="$1"
103+
local api_key="$2"
104+
local overrides="$3"
105+
106+
echo "$client_json" | ${pkgs.jq}/bin/jq \
107+
--arg apiKey "$api_key" \
108+
--argjson overrides "$overrides" '
109+
.fields[] |= (if .name == "apiKey" then .value = $apiKey else . end)
110+
| . + $overrides
111+
| .fields[] |= (
112+
. as $field |
113+
if $overrides[$field.name] != null then
114+
.value = $overrides[$field.name]
115+
else
116+
.
117+
end
118+
)
119+
'
120+
}
121+
122+
CLIENT_API_KEY=$(cat ${apiKeyPath})
123+
FIELD_OVERRIDES='${fieldOverridesJson}'
124+
125+
EXISTING_CLIENT=$(echo "$DOWNLOAD_CLIENTS" | ${pkgs.jq}/bin/jq -r '.[] | select(.name == "${clientName}") | @json' || echo "")
126+
127+
if [ -n "$EXISTING_CLIENT" ]; then
128+
echo "Download client ${clientName} already exists, updating..."
129+
CLIENT_ID=$(echo "$EXISTING_CLIENT" | ${pkgs.jq}/bin/jq -r '.id')
130+
131+
UPDATED_CLIENT=$(apply_field_overrides "$EXISTING_CLIENT" "$CLIENT_API_KEY" "$FIELD_OVERRIDES")
132+
133+
${pkgs.curl}/bin/curl -sSf -X PUT \
134+
-H "X-Api-Key: $API_KEY" \
135+
-H "Content-Type: application/json" \
136+
-d "$UPDATED_CLIENT" \
137+
"$BASE_URL/downloadclient/$CLIENT_ID" >/dev/null
138+
139+
echo "Download client ${clientName} updated"
140+
else
141+
echo "Download client ${clientName} does not exist, creating..."
142+
143+
SCHEMA=$(echo "$SCHEMAS" | ${pkgs.jq}/bin/jq -r '.[] | select(.implementationName == "${implementationName}") | @json' || echo "")
144+
145+
if [ -z "$SCHEMA" ]; then
146+
echo "Error: No schema found for download client implementationName ${implementationName}"
147+
exit 1
148+
fi
149+
150+
NEW_CLIENT=$(apply_field_overrides "$SCHEMA" "$CLIENT_API_KEY" "$FIELD_OVERRIDES")
151+
152+
${pkgs.curl}/bin/curl -sSf -X POST \
153+
-H "X-Api-Key: $API_KEY" \
154+
-H "Content-Type: application/json" \
155+
-d "$NEW_CLIENT" \
156+
"$BASE_URL/downloadclient" >/dev/null
157+
158+
echo "Download client ${clientName} created"
159+
fi
160+
'')
161+
serviceConfig.downloadClients}
162+
163+
echo "${capitalizedName} download clients configuration complete"
164+
'';
165+
};
166+
}

modules/arr-common/downloadClientsService.nix

Lines changed: 0 additions & 130 deletions
This file was deleted.

0 commit comments

Comments
 (0)