@@ -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"
2221dns_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"
7849dns_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