|
5 | 5 | from urllib.parse import urlparse |
6 | 6 |
|
7 | 7 | import aiodns |
| 8 | +import tldextract |
8 | 9 | from pydantic import BaseModel, HttpUrl |
9 | 10 |
|
10 | 11 | from .conf import settings |
@@ -198,6 +199,13 @@ async def check_domain( |
198 | 199 | record_type = dns_rule.dns["type"] |
199 | 200 | record_value = dns_rule.dns["value"] |
200 | 201 |
|
| 202 | + if record_type == "alias": |
| 203 | + # ALIAS records cannot be reliably validated via DNS since the |
| 204 | + # provider resolves them to A records asynchronously. Consider |
| 205 | + # the rule as valid and trust the user's configuration. |
| 206 | + status[dns_rule.name] = True |
| 207 | + continue |
| 208 | + |
201 | 209 | try: |
202 | 210 | entries = await resolver.query(record_name, record_type.upper()) |
203 | 211 | except aiodns.error.DNSError: |
@@ -249,19 +257,35 @@ def get_required_dns_rules( |
249 | 257 | elif target == TargetType.INSTANCE: |
250 | 258 | cname_value = f"{hostname}.{settings.DNS_INSTANCE_DOMAIN}" |
251 | 259 |
|
252 | | - # cname rule |
253 | | - dns_rules.append( |
254 | | - DNSRule( |
255 | | - name="cname", |
256 | | - dns={ |
257 | | - "type": "cname", |
258 | | - "name": hostname, |
259 | | - "value": cname_value, |
260 | | - }, |
261 | | - info=f"Create a CNAME record for {hostname} with value {cname_value}", |
262 | | - on_error=f"CNAME record not found: {hostname}", |
| 260 | + # cname or alias rule |
| 261 | + if self.is_root_domain(hostname): |
| 262 | + record_type = "alias" |
| 263 | + dns_rules.append( |
| 264 | + DNSRule( |
| 265 | + name=record_type, |
| 266 | + dns={ |
| 267 | + "type": record_type, |
| 268 | + "name": hostname, |
| 269 | + "value": cname_value, |
| 270 | + }, |
| 271 | + info=f"Create an ALIAS record for {hostname} with value {cname_value}", |
| 272 | + on_error=f"ALIAS record not found: {hostname}", |
| 273 | + ) |
| 274 | + ) |
| 275 | + else: |
| 276 | + record_type = "cname" |
| 277 | + dns_rules.append( |
| 278 | + DNSRule( |
| 279 | + name=record_type, |
| 280 | + dns={ |
| 281 | + "type": record_type, |
| 282 | + "name": hostname, |
| 283 | + "value": cname_value, |
| 284 | + }, |
| 285 | + info=f"Create a CNAME record for {hostname} with value {cname_value}", |
| 286 | + on_error=f"CNAME record not found: {hostname}", |
| 287 | + ) |
263 | 288 | ) |
264 | | - ) |
265 | 289 |
|
266 | 290 | if target == TargetType.IPFS: |
267 | 291 | # ipfs rule |
@@ -294,3 +318,8 @@ def get_required_dns_rules( |
294 | 318 | ) |
295 | 319 |
|
296 | 320 | return dns_rules |
| 321 | + |
| 322 | + @staticmethod |
| 323 | + def is_root_domain(hostname: Hostname) -> bool: |
| 324 | + extracted = tldextract.extract(hostname) |
| 325 | + return bool(extracted.domain) and not extracted.subdomain |
0 commit comments