Skip to content

Commit 9e584e3

Browse files
committed
Refactor: Add _opusdns_api helper, simplify code
- Added _opusdns_api() for all API requests - Added _opusdns_init() for config initialization - Removed duplicate code in add/rm functions - Removed dead code (orphaned lines 173-178) - Script now 158 lines (was 255, originally 379)
1 parent 163eb1a commit 9e584e3

File tree

1 file changed

+63
-160
lines changed

1 file changed

+63
-160
lines changed

dnsapi/dns_opusdns.sh

Lines changed: 63 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ OPUSDNS_TTL_Default=60
1818
######## Public functions ###########
1919

2020
# Add DNS TXT record
21-
# Usage: dns_opusdns_add _acme-challenge.example.com "token_value"
2221
dns_opusdns_add() {
2322
fulldomain=$1
2423
txtvalue=$2
@@ -27,44 +26,17 @@ dns_opusdns_add() {
2726
_debug fulldomain "$fulldomain"
2827
_debug txtvalue "$txtvalue"
2928

30-
# Load and validate credentials
31-
OPUSDNS_API_Key="${OPUSDNS_API_Key:-$(_readaccountconf_mutable OPUSDNS_API_Key)}"
32-
if [ -z "$OPUSDNS_API_Key" ]; then
33-
_err "OPUSDNS_API_Key not set. Please set it and try again."
34-
_err "You can create an API key at your OpusDNS dashboard."
29+
if ! _opusdns_init; then
3530
return 1
3631
fi
3732

38-
# Save credentials for future use
39-
_saveaccountconf_mutable OPUSDNS_API_Key "$OPUSDNS_API_Key"
40-
41-
# Load optional configuration
42-
OPUSDNS_API_Endpoint="${OPUSDNS_API_Endpoint:-$(_readaccountconf_mutable OPUSDNS_API_Endpoint)}"
43-
if [ -z "$OPUSDNS_API_Endpoint" ]; then
44-
OPUSDNS_API_Endpoint="$OPUSDNS_API_Endpoint_Default"
45-
fi
46-
_saveaccountconf_mutable OPUSDNS_API_Endpoint "$OPUSDNS_API_Endpoint"
47-
48-
OPUSDNS_TTL="${OPUSDNS_TTL:-$(_readaccountconf_mutable OPUSDNS_TTL)}"
49-
if [ -z "$OPUSDNS_TTL" ]; then
50-
OPUSDNS_TTL="$OPUSDNS_TTL_Default"
51-
fi
52-
_saveaccountconf_mutable OPUSDNS_TTL "$OPUSDNS_TTL"
53-
54-
_debug "API Endpoint: $OPUSDNS_API_Endpoint"
55-
_debug "TTL: $OPUSDNS_TTL"
56-
57-
# Detect zone from FQDN
5833
if ! _get_zone "$fulldomain"; then
59-
_err "Failed to detect zone for domain: $fulldomain"
6034
return 1
6135
fi
6236

63-
_info "Detected zone: $_zone"
64-
_debug "Record name: $_record_name"
37+
_info "Zone: $_zone, Record: $_record_name"
6538

66-
# Add the TXT record
67-
if ! _opusdns_add_record "$_zone" "$_record_name" "$txtvalue"; then
39+
if ! _opusdns_api PATCH "/v1/dns/$_zone/records" "{\"ops\":[{\"op\":\"upsert\",\"record\":{\"name\":\"$_record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$txtvalue\\\"\"}}]}"; then
6840
_err "Failed to add TXT record"
6941
return 1
7042
fi
@@ -74,7 +46,6 @@ dns_opusdns_add() {
7446
}
7547

7648
# Remove DNS TXT record
77-
# Usage: dns_opusdns_rm _acme-challenge.example.com "token_value"
7849
dns_opusdns_rm() {
7950
fulldomain=$1
8051
txtvalue=$2
@@ -83,38 +54,19 @@ dns_opusdns_rm() {
8354
_debug fulldomain "$fulldomain"
8455
_debug txtvalue "$txtvalue"
8556

86-
# Load credentials
87-
OPUSDNS_API_Key="${OPUSDNS_API_Key:-$(_readaccountconf_mutable OPUSDNS_API_Key)}"
88-
OPUSDNS_API_Endpoint="${OPUSDNS_API_Endpoint:-$(_readaccountconf_mutable OPUSDNS_API_Endpoint)}"
89-
OPUSDNS_TTL="${OPUSDNS_TTL:-$(_readaccountconf_mutable OPUSDNS_TTL)}"
90-
91-
if [ -z "$OPUSDNS_API_Endpoint" ]; then
92-
OPUSDNS_API_Endpoint="$OPUSDNS_API_Endpoint_Default"
93-
fi
94-
95-
if [ -z "$OPUSDNS_TTL" ]; then
96-
OPUSDNS_TTL="$OPUSDNS_TTL_Default"
97-
fi
98-
99-
if [ -z "$OPUSDNS_API_Key" ]; then
100-
_err "OPUSDNS_API_Key not found"
57+
if ! _opusdns_init; then
10158
return 1
10259
fi
10360

104-
# Detect zone from FQDN
10561
if ! _get_zone "$fulldomain"; then
106-
_err "Failed to detect zone for domain: $fulldomain"
107-
# Don't fail cleanup - best effort
62+
_err "Zone not found, cleanup skipped"
10863
return 0
10964
fi
11065

111-
_info "Detected zone: $_zone"
112-
_debug "Record name: $_record_name"
66+
_info "Zone: $_zone, Record: $_record_name"
11367

114-
# Remove the TXT record (need to pass txtvalue)
115-
if ! _opusdns_remove_record "$_zone" "$_record_name" "$txtvalue"; then
116-
_err "Warning: Failed to remove TXT record (this is usually not critical)"
117-
# Don't fail cleanup - best effort
68+
if ! _opusdns_api PATCH "/v1/dns/$_zone/records" "{\"ops\":[{\"op\":\"remove\",\"record\":{\"name\":\"$_record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$txtvalue\\\"\"}}]}"; then
69+
_err "Warning: Failed to remove TXT record"
11870
return 0
11971
fi
12072

@@ -124,132 +76,83 @@ dns_opusdns_rm() {
12476

12577
######## Private functions ###########
12678

127-
# Detect zone from FQDN by checking against OpusDNS API
128-
# Iterates through domain parts until a valid zone is found
129-
# Sets global variables: _zone, _record_name
130-
_get_zone() {
131-
domain=$1
132-
_debug "Detecting zone for: $domain"
133-
134-
# Remove trailing dot if present
135-
domain=$(echo "$domain" | sed 's/\.$//')
136-
137-
export _H1="X-Api-Key: $OPUSDNS_API_Key"
138-
139-
# Start from position 2 (skip first part like _acme-challenge)
140-
i=2
141-
p=1
142-
while true; do
143-
# Extract potential zone (domain parts from position i onwards)
144-
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
145-
_debug "Trying zone: $h"
146-
147-
if [ -z "$h" ]; then
148-
# No more parts to try
149-
_err "Could not find a valid zone for: $domain"
150-
return 1
151-
fi
152-
153-
# Check if this zone exists in OpusDNS
154-
response=$(_get "$OPUSDNS_API_Endpoint/v1/dns/$h")
155-
156-
if _contains "$response" '"name"'; then
157-
# Zone found
158-
_record_name=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
159-
_zone="$h"
160-
_debug "Found zone: $_zone"
161-
_debug "Record name: $_record_name"
162-
return 0
163-
fi
79+
# Initialize and validate configuration
80+
_opusdns_init() {
81+
OPUSDNS_API_Key="${OPUSDNS_API_Key:-$(_readaccountconf_mutable OPUSDNS_API_Key)}"
82+
OPUSDNS_API_Endpoint="${OPUSDNS_API_Endpoint:-$(_readaccountconf_mutable OPUSDNS_API_Endpoint)}"
83+
OPUSDNS_TTL="${OPUSDNS_TTL:-$(_readaccountconf_mutable OPUSDNS_TTL)}"
16484

165-
_debug "$h not found, trying next"
166-
p="$i"
167-
i=$(_math "$i" + 1)
168-
done
85+
if [ -z "$OPUSDNS_API_Key" ]; then
86+
_err "OPUSDNS_API_Key not set"
87+
return 1
88+
fi
16989

170-
return 1
171-
}
90+
[ -z "$OPUSDNS_API_Endpoint" ] && OPUSDNS_API_Endpoint="$OPUSDNS_API_Endpoint_Default"
91+
[ -z "$OPUSDNS_TTL" ] && OPUSDNS_TTL="$OPUSDNS_TTL_Default"
17292

173-
if [ -z "$_record_name" ]; then
174-
_record_name="@"
175-
fi
93+
_saveaccountconf_mutable OPUSDNS_API_Key "$OPUSDNS_API_Key"
94+
_saveaccountconf_mutable OPUSDNS_API_Endpoint "$OPUSDNS_API_Endpoint"
95+
_saveaccountconf_mutable OPUSDNS_TTL "$OPUSDNS_TTL"
17696

97+
_debug "Endpoint: $OPUSDNS_API_Endpoint"
17798
return 0
17899
}
179100

180-
# Add TXT record using OpusDNS API
181-
_opusdns_add_record() {
182-
zone=$1
183-
record_name=$2
184-
txtvalue=$3
101+
# Make API request
102+
# Usage: _opusdns_api METHOD PATH [DATA]
103+
_opusdns_api() {
104+
method=$1
105+
path=$2
106+
data=$3
185107

186-
_debug "Adding TXT record: $record_name.$zone = $txtvalue"
187-
188-
# Escape all JSON special characters in txtvalue
189-
# Order matters: escape backslashes first, then other characters
190-
escaped_value=$(printf '%s' "$txtvalue" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/ /\\t/g' | sed ':a;N;$!ba;s/\n/\\n/g')
191-
192-
# Build JSON payload
193-
# Note: TXT records need quotes around the value in rdata
194-
json_payload="{\"ops\":[{\"op\":\"upsert\",\"record\":{\"name\":\"$record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$escaped_value\\\"\"}}]}"
195-
196-
_debug2 "JSON payload: $json_payload"
197-
198-
# Send PATCH request
199108
export _H1="X-Api-Key: $OPUSDNS_API_Key"
200109
export _H2="Content-Type: application/json"
201110

202-
response=$(_post "$json_payload" "$OPUSDNS_API_Endpoint/v1/dns/$zone/records" "" "PATCH")
203-
status=$?
204-
205-
_debug2 "API Response: $response"
111+
url="$OPUSDNS_API_Endpoint$path"
112+
_debug2 "API: $method $url"
113+
[ -n "$data" ] && _debug2 "Data: $data"
206114

207-
if [ $status -ne 0 ]; then
208-
_err "Failed to add TXT record"
209-
_err "API Response: $response"
210-
return 1
115+
if [ -n "$data" ]; then
116+
response=$(_post "$data" "$url" "" "$method")
117+
else
118+
response=$(_get "$url")
211119
fi
212120

213-
# Check for error in response (OpusDNS returns JSON error even on failure)
214-
# Use anchored pattern to avoid matching field names like "error_count"
215-
if echo "$response" | grep -q '"error":'; then
216-
_err "API returned error: $response"
121+
if [ $? -ne 0 ]; then
122+
_err "API request failed"
123+
_debug "Response: $response"
217124
return 1
218125
fi
219126

127+
_debug2 "Response: $response"
220128
return 0
221129
}
222130

223-
# Remove TXT record using OpusDNS API
224-
_opusdns_remove_record() {
225-
zone=$1
226-
record_name=$2
227-
txtvalue=$3
228-
229-
_debug "Removing TXT record: $record_name.$zone = $txtvalue"
230-
231-
# Escape all JSON special characters in txtvalue (same as add)
232-
escaped_value=$(printf '%s' "$txtvalue" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/ /\\t/g' | sed ':a;N;$!ba;s/\n/\\n/g')
233-
234-
# Build JSON payload for removal - needs complete record specification
235-
json_payload="{\"ops\":[{\"op\":\"remove\",\"record\":{\"name\":\"$record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$escaped_value\\\"\"}}]}"
236-
237-
_debug2 "JSON payload: $json_payload"
238-
239-
# Send PATCH request
240-
export _H1="X-Api-Key: $OPUSDNS_API_Key"
241-
export _H2="Content-Type: application/json"
131+
# Detect zone from FQDN
132+
# Sets: _zone, _record_name
133+
_get_zone() {
134+
domain=$(echo "$1" | sed 's/\.$//')
135+
_debug "Finding zone for: $domain"
242136

243-
response=$(_post "$json_payload" "$OPUSDNS_API_Endpoint/v1/dns/$zone/records" "" "PATCH")
244-
status=$?
137+
i=2
138+
p=1
139+
while true; do
140+
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
245141

246-
_debug2 "API Response: $response"
142+
if [ -z "$h" ]; then
143+
_err "No valid zone found for: $domain"
144+
return 1
145+
fi
247146

248-
if [ $status -ne 0 ]; then
249-
_err "Failed to remove TXT record"
250-
_err "API Response: $response"
251-
return 1
252-
fi
147+
_debug "Trying: $h"
148+
if _opusdns_api GET "/v1/dns/$h" && _contains "$response" '"name"'; then
149+
_zone="$h"
150+
_record_name=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
151+
[ -z "$_record_name" ] && _record_name="@"
152+
return 0
153+
fi
253154

254-
return 0
155+
p="$i"
156+
i=$(_math "$i" + 1)
157+
done
255158
}

0 commit comments

Comments
 (0)