26
26
CF_ZONE_ID = os .getenv ("CF_ZONE_ID" )
27
27
DNS_RECORD_COMMENT_KEY = os .getenv ('DNS_RECORD_COMMENT_KEY' )
28
28
DOMAINS_FILE_PATH = os .getenv ('DOMAINS_FILE_PATH' )
29
- SCHEDULE_MINUTES = int (os .getenv ('SCHEDULE_MINUTES' , 60 ))
29
+ SCHEDULE_MINUTES = int (os .getenv ('SCHEDULE_MINUTES' , '60' ))
30
30
31
31
# Define API endpoints
32
32
BASE_URL = 'https://api.cloudflare.com/client/v4/'
@@ -69,7 +69,7 @@ def create_logger(level=logging.INFO):
69
69
70
70
# Get current DNS record for the specified domain
71
71
def get_dns_record (zone_id , domain_name ):
72
- LOGGER .info (f"Fetching record for '{ domain_name } ' in zone '{ zone_id } ." )
72
+ LOGGER .info (f"Fetching record for '%s ' in zone '%s'." , domain_name , zone_id )
73
73
74
74
headers = {
75
75
'Authorization' : 'Bearer ' + CF_API_TOKEN ,
@@ -80,16 +80,16 @@ def get_dns_record(zone_id, domain_name):
80
80
'name' : domain_name ,
81
81
}
82
82
83
- response = requests .get (f'{ BASE_URL } zones/{ zone_id } /dns_records' , headers = headers , params = params )
83
+ response = requests .get (f'{ BASE_URL } zones/{ zone_id } /dns_records' , headers = headers , params = params , timeout = 60 )
84
84
85
85
if response .status_code == 200 :
86
86
records = response .json ()['result' ]
87
87
88
88
if records :
89
- LOGGER .info (f"Successfully fetched data for '{ domain_name } '." )
89
+ LOGGER .info (f"Successfully fetched data for '%s '." , domain_name )
90
90
return records [0 ]
91
91
else :
92
- LOGGER .error (f"Failed to fetch data for '{ domain_name } '. Response: { response .json ()} " )
92
+ LOGGER .error (f"Failed to fetch data for '%s '. Response: %s" , domain_name , response .json ())
93
93
94
94
return None
95
95
@@ -108,18 +108,19 @@ def update_dns_record(record, content):
108
108
response = requests .patch (
109
109
f"{ BASE_URL } zones/{ record ['zone_id' ]} /dns_records/{ record ['id' ]} " ,
110
110
json = data ,
111
- headers = headers
111
+ headers = headers ,
112
+ timeout = 30
112
113
)
113
114
114
115
if response .status_code == 200 :
115
- LOGGER .info (f"DNS record updated successfully: { record ['name' ]} ( { record ['type' ]} ) -> { content } " )
116
+ LOGGER .info (f"DNS record updated successfully: %s (%s) -> %s" , record ['name' ], record ['type' ], content )
116
117
else :
117
- LOGGER .error (f"Failed to update DNS record: { response .json ()} " )
118
+ LOGGER .error (f"Failed to update DNS record: %s" , response .json ())
118
119
119
120
120
121
# Loads static wishlist of domains in json format along with their metadata
121
122
def read_zones_from_file (json_file_path , zone_id ):
122
- with open (json_file_path , 'r' ) as file :
123
+ with open (json_file_path , 'r' , encoding = "utf-8" ) as file :
123
124
data = json .load (file )
124
125
125
126
zones = data ['zones' ]
@@ -131,7 +132,7 @@ def read_zones_from_file(json_file_path, zone_id):
131
132
for domain in zone ['domains' ]:
132
133
domain ['zone_id' ] = zone ['id' ]
133
134
134
- LOGGER .info (f"Sucessfully read zone { zone } ." )
135
+ LOGGER .info (f"Sucessfully read zone %s." , zone )
135
136
136
137
return zones
137
138
@@ -140,7 +141,7 @@ def read_zones_from_file(json_file_path, zone_id):
140
141
def get_dns_records_by_name (zones ):
141
142
records = []
142
143
143
- LOGGER .info (f"Trying to fetch records for { len ( zones ) } zones." )
144
+ LOGGER .info (f"Trying to fetch records for %s zones." , len ( zones ) )
144
145
145
146
for zone in zones :
146
147
for domain in zone ['domains' ]:
@@ -163,18 +164,17 @@ def get_dns_records_by_comment(zone_id, comment_key):
163
164
'comment.contains' : comment_key ,
164
165
}
165
166
166
- LOGGER .info (f"Fetching DNS record with comment key: { comment_key } " )
167
- response = requests .get (f'{ BASE_URL } zones/{ zone_id } /dns_records' , headers = headers , params = params )
167
+ LOGGER .info (f"Fetching DNS record with comment key: %s" , comment_key )
168
+ response = requests .get (f'{ BASE_URL } zones/{ zone_id } /dns_records' , headers = headers , params = params , timeout = 60 )
168
169
169
170
if response .status_code == 200 :
170
171
records = response .json ()['result' ]
171
172
if records and len (records ) > 0 :
172
173
return records
173
- else :
174
- LOGGER .warning (f"Request was successful but no valid domains were found: { response .json ()} " )
175
- return []
174
+ LOGGER .warning (f"Request was successful but no valid domains were found: %s" , response .json ())
175
+ return []
176
176
else :
177
- LOGGER .error (f"Failed to get dns_records with comment key: { response .json ()} " )
177
+ LOGGER .error (f"Failed to get dns_records with comment key: %s" , response .json ())
178
178
179
179
return []
180
180
@@ -197,7 +197,8 @@ def is_connected():
197
197
host = socket .gethostbyname ("www.cloudflare.com" )
198
198
socket .create_connection ((host , 80 ), 2 )
199
199
return True
200
- except Exception :
200
+ except socket .error as exc :
201
+ LOGGER .error ("Socket error: %s" , exc )
201
202
pass
202
203
return False
203
204
@@ -212,32 +213,32 @@ def check_and_update_dns():
212
213
if CF_ZONE_ID is None :
213
214
LOGGER .error ("CF_ZONE_ID: At least one zone id must be set." )
214
215
return
215
- elif CF_API_TOKEN is None :
216
+ if CF_API_TOKEN is None :
216
217
LOGGER .error ("CF_API_TOKEN Missing: You have to provide your Cloudflare API Token." )
217
218
return
218
- elif DNS_RECORD_COMMENT_KEY is None and DOMAINS_FILE_PATH is None :
219
+ if DNS_RECORD_COMMENT_KEY is None and DOMAINS_FILE_PATH is None :
219
220
LOGGER .error ("DNS_RECORD_COMMENT_KEY and DOMAINS_FILE_PATH are missing, don't know which domains to update" )
220
221
return
221
222
222
223
public_ip = get_public_ip ()
223
224
domain_records = []
224
225
225
226
if DNS_RECORD_COMMENT_KEY is not None :
226
- LOGGER .info (f"Using DNS_RECORD_COMMENT_KEY='{ DNS_RECORD_COMMENT_KEY } ' to find DNS records to update." )
227
+ LOGGER .info (f"Using DNS_RECORD_COMMENT_KEY='%s ' to find DNS records to update." , DNS_RECORD_COMMENT_KEY )
227
228
domain_records = get_dns_records_by_comment (CF_ZONE_ID , DNS_RECORD_COMMENT_KEY )
228
229
else :
229
- LOGGER .info (f"Using DOMAINS_FILE_PATH='{ DOMAINS_FILE_PATH } ' to find DNS records to update." )
230
+ LOGGER .info (f"Using DOMAINS_FILE_PATH='%s ' to find DNS records to update." , DOMAINS_FILE_PATH )
230
231
domain_records = get_dns_records_by_name (read_zones_from_file (DOMAINS_FILE_PATH , CF_ZONE_ID ))
231
232
232
233
valid_domains = [x ['name' ] for x in domain_records if x is not None ]
233
- LOGGER .info (f"Found { len ( valid_domains ) } valid domains for update: [{ ',' .join (valid_domains )} ]" )
234
+ LOGGER .info (f"Found %s valid domains for update: [%s]" , len ( valid_domains ), ',' .join (valid_domains ))
234
235
235
236
if public_ip :
236
237
for record in domain_records :
237
238
domain_name = record ['name' ]
238
239
239
240
if record is None :
240
- LOGGER .error (f"DNS record for { domain_name } not found." )
241
+ LOGGER .error (f"DNS record for %s not found." , domain_name )
241
242
continue
242
243
243
244
if public_ip != record ['content' ]:
@@ -246,12 +247,12 @@ def check_and_update_dns():
246
247
public_ip
247
248
)
248
249
else :
249
- LOGGER .info (f"IP addresses are the same for { domain_name } . No update needed." )
250
+ LOGGER .info (f"IP addresses are the same for %s . No update needed." , domain_name )
250
251
else :
251
252
LOGGER .error ("Failed to retrieve public IP. Skipping check and update." )
252
253
253
254
254
- LOGGER .info (f"Schedule is set at { SCHEDULE_MINUTES } " )
255
+ LOGGER .info (f"Schedule is set at %s minutes" , SCHEDULE_MINUTES )
255
256
256
257
# Schedule the check and update process to run every X minutes
257
258
schedule .every (SCHEDULE_MINUTES ).minutes .do (check_and_update_dns ).run ()
0 commit comments