0
# DNS Record Set Management
1
2
Complete CRUD operations for DNS record sets supporting all major DNS record types (A, AAAA, CAA, CNAME, MX, NS, PTR, SOA, SRV, TXT) with conditional updates and batch operations. Record sets group multiple DNS records of the same type and name within a DNS zone.
3
4
## Record Set Operations
5
6
### Create or Update Record Set
7
8
Creates a new DNS record set or updates an existing one with the specified records.
9
10
```python { .api }
11
def create_or_update(
12
self,
13
resource_group_name: str,
14
zone_name: str,
15
relative_record_set_name: str,
16
record_type: Union[str, RecordType],
17
parameters: Union[RecordSet, IO[bytes]],
18
if_match: Optional[str] = None,
19
if_none_match: Optional[str] = None,
20
**kwargs: Any
21
) -> RecordSet:
22
"""
23
Create or update a DNS record set.
24
25
Args:
26
resource_group_name: Name of the resource group containing the zone
27
zone_name: Name of the DNS zone
28
relative_record_set_name: Name relative to zone (use "@" for apex records)
29
record_type: Type of DNS record (A, AAAA, CNAME, etc.)
30
parameters: Record set configuration with DNS records
31
if_match: ETag value for conditional updates
32
if_none_match: Set to "*" to prevent overwriting
33
34
Returns:
35
RecordSet: The created or updated record set
36
37
Raises:
38
HttpResponseError: If the operation fails
39
"""
40
```
41
42
**Usage Examples:**
43
44
```python
45
from azure.mgmt.dns.models import RecordSet, ARecord, CnameRecord, MxRecord, RecordType
46
47
# Create an A record set with multiple IP addresses
48
a_record_set = RecordSet(
49
ttl=300,
50
a_records=[
51
ARecord(ipv4_address="192.0.2.1"),
52
ARecord(ipv4_address="192.0.2.2")
53
]
54
)
55
56
result = dns_client.record_sets.create_or_update(
57
resource_group_name="my-rg",
58
zone_name="example.com",
59
relative_record_set_name="www",
60
record_type=RecordType.A,
61
parameters=a_record_set
62
)
63
64
# Create a CNAME record
65
cname_record_set = RecordSet(
66
ttl=3600,
67
cname_record=CnameRecord(cname="www.example.com")
68
)
69
70
dns_client.record_sets.create_or_update(
71
resource_group_name="my-rg",
72
zone_name="example.com",
73
relative_record_set_name="blog",
74
record_type=RecordType.CNAME,
75
parameters=cname_record_set
76
)
77
78
# Create MX records for email
79
mx_record_set = RecordSet(
80
ttl=3600,
81
mx_records=[
82
MxRecord(preference=10, exchange="mail1.example.com"),
83
MxRecord(preference=20, exchange="mail2.example.com")
84
]
85
)
86
87
dns_client.record_sets.create_or_update(
88
resource_group_name="my-rg",
89
zone_name="example.com",
90
relative_record_set_name="@", # Apex record
91
record_type=RecordType.MX,
92
parameters=mx_record_set
93
)
94
```
95
96
### Update Record Set
97
98
Updates specific properties of an existing record set without replacing the entire record set.
99
100
```python { .api }
101
def update(
102
self,
103
resource_group_name: str,
104
zone_name: str,
105
relative_record_set_name: str,
106
record_type: Union[str, RecordType],
107
parameters: Union[RecordSet, IO[bytes]],
108
if_match: Optional[str] = None,
109
**kwargs: Any
110
) -> RecordSet:
111
"""
112
Update properties of an existing DNS record set.
113
114
Args:
115
resource_group_name: Name of the resource group containing the zone
116
zone_name: Name of the DNS zone
117
relative_record_set_name: Name of the record set
118
record_type: Type of DNS record
119
parameters: Record set with updated properties
120
if_match: ETag value for conditional updates
121
122
Returns:
123
RecordSet: The updated record set
124
125
Raises:
126
HttpResponseError: If the record set is not found
127
"""
128
```
129
130
### Delete Record Set
131
132
Permanently deletes a DNS record set and all its records.
133
134
```python { .api }
135
def delete(
136
self,
137
resource_group_name: str,
138
zone_name: str,
139
relative_record_set_name: str,
140
record_type: Union[str, RecordType],
141
if_match: Optional[str] = None,
142
**kwargs: Any
143
) -> None:
144
"""
145
Delete a DNS record set.
146
147
Args:
148
resource_group_name: Name of the resource group containing the zone
149
zone_name: Name of the DNS zone
150
relative_record_set_name: Name of the record set
151
record_type: Type of DNS record
152
if_match: ETag value for conditional deletion
153
154
Raises:
155
HttpResponseError: If the record set is not found
156
"""
157
```
158
159
**Usage Example:**
160
161
```python
162
# Delete a specific record set
163
dns_client.record_sets.delete(
164
resource_group_name="my-rg",
165
zone_name="example.com",
166
relative_record_set_name="old-service",
167
record_type=RecordType.A
168
)
169
```
170
171
### Get Record Set
172
173
Retrieves a specific DNS record set and its records.
174
175
```python { .api }
176
def get(
177
self,
178
resource_group_name: str,
179
zone_name: str,
180
relative_record_set_name: str,
181
record_type: Union[str, RecordType],
182
**kwargs: Any
183
) -> RecordSet:
184
"""
185
Get a specific DNS record set.
186
187
Args:
188
resource_group_name: Name of the resource group containing the zone
189
zone_name: Name of the DNS zone
190
relative_record_set_name: Name of the record set
191
record_type: Type of DNS record
192
193
Returns:
194
RecordSet: The DNS record set with all its records
195
196
Raises:
197
HttpResponseError: If the record set is not found
198
"""
199
```
200
201
### List Record Sets
202
203
Lists DNS record sets within a zone, with options to filter by type.
204
205
```python { .api }
206
def list_by_dns_zone(
207
self,
208
resource_group_name: str,
209
zone_name: str,
210
top: Optional[int] = None,
211
recordsetnamesuffix: Optional[str] = None,
212
**kwargs: Any
213
) -> ItemPaged[RecordSet]:
214
"""
215
List all record sets in a DNS zone.
216
217
Args:
218
resource_group_name: Name of the resource group containing the zone
219
zone_name: Name of the DNS zone
220
top: Maximum number of record sets to return
221
recordsetnamesuffix: Filter by record set name suffix
222
223
Returns:
224
ItemPaged[RecordSet]: Paginated list of record sets
225
"""
226
227
def list_by_type(
228
self,
229
resource_group_name: str,
230
zone_name: str,
231
record_type: Union[str, RecordType],
232
top: Optional[int] = None,
233
recordsetnamesuffix: Optional[str] = None,
234
**kwargs: Any
235
) -> ItemPaged[RecordSet]:
236
"""
237
List record sets of a specific type in a DNS zone.
238
239
Args:
240
resource_group_name: Name of the resource group containing the zone
241
zone_name: Name of the DNS zone
242
record_type: Type of DNS record to filter by
243
top: Maximum number of record sets to return
244
recordsetnamesuffix: Filter by record set name suffix
245
246
Returns:
247
ItemPaged[RecordSet]: Paginated list of record sets
248
"""
249
250
def list_all_by_dns_zone(
251
self,
252
resource_group_name: str,
253
zone_name: str,
254
top: Optional[int] = None,
255
record_set_name_suffix: Optional[str] = None,
256
**kwargs: Any
257
) -> ItemPaged[RecordSet]:
258
"""
259
Alternative endpoint for listing all record sets in a zone.
260
261
Args:
262
resource_group_name: Name of the resource group containing the zone
263
zone_name: Name of the DNS zone
264
top: Maximum number of record sets to return
265
record_set_name_suffix: Filter by record set name suffix
266
267
Returns:
268
ItemPaged[RecordSet]: Paginated list of record sets
269
"""
270
```
271
272
**Usage Examples:**
273
274
```python
275
# List all record sets in a zone
276
all_records = dns_client.record_sets.list_by_dns_zone(
277
resource_group_name="my-rg",
278
zone_name="example.com"
279
)
280
for record_set in all_records:
281
print(f"{record_set.name} ({record_set.type}) - TTL: {record_set.ttl}")
282
283
# List only A records
284
a_records = dns_client.record_sets.list_by_type(
285
resource_group_name="my-rg",
286
zone_name="example.com",
287
record_type=RecordType.A
288
)
289
for record_set in a_records:
290
print(f"A record: {record_set.name} -> {[r.ipv4_address for r in record_set.a_records]}")
291
292
# List records with name suffix filtering
293
web_records = dns_client.record_sets.list_by_dns_zone(
294
resource_group_name="my-rg",
295
zone_name="example.com",
296
recordsetnamesuffix="web" # Matches "web", "web1", "webapp", etc.
297
)
298
```
299
300
## DNS Record Types
301
302
### A Records (IPv4 Addresses)
303
304
```python { .api }
305
class ARecord:
306
"""IPv4 address record."""
307
ipv4_address: str # IPv4 address (e.g., "192.0.2.1")
308
```
309
310
**Usage:**
311
```python
312
from azure.mgmt.dns.models import RecordSet, ARecord
313
314
record_set = RecordSet(
315
ttl=300,
316
a_records=[
317
ARecord(ipv4_address="192.0.2.1"),
318
ARecord(ipv4_address="192.0.2.2")
319
]
320
)
321
```
322
323
### AAAA Records (IPv6 Addresses)
324
325
```python { .api }
326
class AaaaRecord:
327
"""IPv6 address record."""
328
ipv6_address: str # IPv6 address (e.g., "2001:db8::1")
329
```
330
331
### CNAME Records (Canonical Names)
332
333
```python { .api }
334
class CnameRecord:
335
"""Canonical name record (alias)."""
336
cname: str # Target domain name
337
```
338
339
**Usage:**
340
```python
341
from azure.mgmt.dns.models import RecordSet, CnameRecord
342
343
cname_record_set = RecordSet(
344
ttl=3600,
345
cname_record=CnameRecord(cname="target.example.com")
346
)
347
```
348
349
### MX Records (Mail Exchange)
350
351
```python { .api }
352
class MxRecord:
353
"""Mail exchange record for email routing."""
354
preference: int # Priority (lower numbers have higher priority)
355
exchange: str # Mail server hostname
356
```
357
358
### NS Records (Name Servers)
359
360
```python { .api }
361
class NsRecord:
362
"""Name server record."""
363
nsdname: str # Name server domain name
364
```
365
366
### TXT Records (Text Data)
367
368
```python { .api }
369
class TxtRecord:
370
"""Text record for arbitrary text data."""
371
value: List[str] # List of text strings (each ≤255 characters)
372
```
373
374
**Usage:**
375
```python
376
from azure.mgmt.dns.models import RecordSet, TxtRecord
377
378
txt_record_set = RecordSet(
379
ttl=300,
380
txt_records=[
381
TxtRecord(value=["v=spf1 include:_spf.google.com ~all"]),
382
TxtRecord(value=["google-site-verification=abc123..."])
383
]
384
)
385
```
386
387
### SRV Records (Service Discovery)
388
389
```python { .api }
390
class SrvRecord:
391
"""Service record for service discovery."""
392
priority: int # Priority (lower is higher priority)
393
weight: int # Weight for load balancing among same priority
394
port: int # Service port number
395
target: str # Target hostname
396
```
397
398
### PTR Records (Reverse DNS)
399
400
```python { .api }
401
class PtrRecord:
402
"""Pointer record for reverse DNS lookups."""
403
ptrdname: str # Target domain name
404
```
405
406
### SOA Records (Start of Authority)
407
408
```python { .api }
409
class SoaRecord:
410
"""Start of Authority record (zone metadata)."""
411
host: str # Primary name server
412
email: str # Administrator email (dots replaced with @)
413
serial_number: int # Zone serial number
414
refresh_time: int # Refresh interval (seconds)
415
retry_time: int # Retry interval (seconds)
416
expire_time: int # Expiration time (seconds)
417
minimum_ttl: int # Minimum TTL for negative caching
418
```
419
420
### CAA Records (Certificate Authority Authorization)
421
422
```python { .api }
423
class CaaRecord:
424
"""Certificate Authority Authorization record."""
425
flags: int # Flags (typically 0 or 128 for critical)
426
tag: str # Property tag ("issue", "issuewild", "iodef")
427
value: str # Property value (CA domain or URL)
428
```
429
430
**Usage:**
431
```python
432
from azure.mgmt.dns.models import RecordSet, CaaRecord
433
434
caa_record_set = RecordSet(
435
ttl=3600,
436
caa_records=[
437
CaaRecord(flags=0, tag="issue", value="letsencrypt.org"),
438
CaaRecord(flags=0, tag="issue", value="digicert.com"),
439
CaaRecord(flags=128, tag="iodef", value="mailto:security@example.com")
440
]
441
)
442
```
443
444
## Record Set Data Model
445
446
### RecordSet Class
447
448
```python { .api }
449
class RecordSet:
450
"""
451
Represents a DNS record set within a zone.
452
453
A record set groups multiple DNS records of the same type and name.
454
"""
455
456
# Read-only properties
457
id: str # Azure resource ID
458
name: str # Record set name relative to zone
459
type: str # Record set type (e.g., "Microsoft.Network/dnszones/A")
460
etag: str # ETag for concurrency control
461
fqdn: str # Fully qualified domain name (read-only)
462
463
# Configurable properties
464
ttl: int # Time-to-live in seconds (1-2147483647)
465
metadata: Dict[str, str] # Custom metadata key-value pairs
466
target_resource: SubResource # Reference to Azure resource (for alias records)
467
468
# Record type specific arrays (only one should be populated)
469
a_records: List[ARecord] # IPv4 address records
470
aaaa_records: List[AaaaRecord] # IPv6 address records
471
caa_records: List[CaaRecord] # Certificate authority records
472
cname_record: CnameRecord # Canonical name (single record)
473
mx_records: List[MxRecord] # Mail exchange records
474
ns_records: List[NsRecord] # Name server records
475
ptr_records: List[PtrRecord] # Pointer records
476
soa_record: SoaRecord # Start of authority (single record)
477
srv_records: List[SrvRecord] # Service records
478
txt_records: List[TxtRecord] # Text records
479
```
480
481
### Record Types Enumeration
482
483
```python { .api }
484
class RecordType(str, Enum):
485
"""Supported DNS record types."""
486
A = "A" # IPv4 address
487
AAAA = "AAAA" # IPv6 address
488
CAA = "CAA" # Certificate Authority Authorization
489
CNAME = "CNAME" # Canonical name
490
MX = "MX" # Mail exchange
491
NS = "NS" # Name server
492
PTR = "PTR" # Pointer (reverse DNS)
493
SOA = "SOA" # Start of authority
494
SRV = "SRV" # Service record
495
TXT = "TXT" # Text record
496
```
497
498
## Advanced Scenarios
499
500
### Conditional Updates with ETags
501
502
Use ETags to prevent conflicting updates when multiple clients modify the same record set:
503
504
```python
505
# Get current record set with ETag
506
record_set = dns_client.record_sets.get(
507
resource_group_name="my-rg",
508
zone_name="example.com",
509
relative_record_set_name="api",
510
record_type=RecordType.A
511
)
512
513
# Modify the record set
514
record_set.a_records.append(ARecord(ipv4_address="192.0.2.100"))
515
516
# Update with ETag to prevent conflicts
517
try:
518
updated_record_set = dns_client.record_sets.create_or_update(
519
resource_group_name="my-rg",
520
zone_name="example.com",
521
relative_record_set_name="api",
522
record_type=RecordType.A,
523
parameters=record_set,
524
if_match=record_set.etag
525
)
526
print("Update successful")
527
except HttpResponseError as e:
528
if e.status_code == 412:
529
print("Conflict: Record set was modified by another client")
530
```
531
532
### Batch Operations
533
534
Process multiple record sets efficiently:
535
536
```python
537
from concurrent.futures import ThreadPoolExecutor
538
from azure.mgmt.dns.models import RecordSet, ARecord, RecordType
539
540
def create_record_set(name, ip_address):
541
record_set = RecordSet(
542
ttl=300,
543
a_records=[ARecord(ipv4_address=ip_address)]
544
)
545
546
return dns_client.record_sets.create_or_update(
547
resource_group_name="my-rg",
548
zone_name="example.com",
549
relative_record_set_name=name,
550
record_type=RecordType.A,
551
parameters=record_set
552
)
553
554
# Create multiple record sets in parallel
555
record_configs = [
556
("web1", "192.0.2.10"),
557
("web2", "192.0.2.11"),
558
("web3", "192.0.2.12")
559
]
560
561
with ThreadPoolExecutor(max_workers=5) as executor:
562
results = list(executor.map(lambda config: create_record_set(*config), record_configs))
563
564
print(f"Created {len(results)} record sets")
565
```
566
567
## Error Handling
568
569
```python
570
from azure.core.exceptions import HttpResponseError
571
572
try:
573
record_set = dns_client.record_sets.create_or_update(
574
resource_group_name="my-rg",
575
zone_name="example.com",
576
relative_record_set_name="test",
577
record_type=RecordType.A,
578
parameters=RecordSet(ttl=300, a_records=[ARecord(ipv4_address="192.0.2.1")])
579
)
580
except HttpResponseError as e:
581
if e.status_code == 400:
582
print("Bad request: Check record set configuration")
583
elif e.status_code == 404:
584
print("Zone not found")
585
elif e.status_code == 409:
586
print("Conflict: Record set already exists (when using if_none_match)")
587
elif e.status_code == 412:
588
print("Precondition failed: ETag mismatch")
589
else:
590
print(f"Unexpected error: {e.status_code} - {e.message}")
591
```
592
593
Common error scenarios:
594
- **400 Bad Request**: Invalid record configuration or malformed data
595
- **404 Not Found**: DNS zone doesn't exist
596
- **409 Conflict**: Record set exists when using `if_none_match="*"`
597
- **412 Precondition Failed**: ETag mismatch when using conditional updates