Microsoft Azure DNS Management Client Library for Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Creates a new DNS record set or updates an existing one with the specified records.
def create_or_update(
self,
resource_group_name: str,
zone_name: str,
relative_record_set_name: str,
record_type: Union[str, RecordType],
parameters: Union[RecordSet, IO[bytes]],
if_match: Optional[str] = None,
if_none_match: Optional[str] = None,
**kwargs: Any
) -> RecordSet:
"""
Create or update a DNS record set.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
relative_record_set_name: Name relative to zone (use "@" for apex records)
record_type: Type of DNS record (A, AAAA, CNAME, etc.)
parameters: Record set configuration with DNS records
if_match: ETag value for conditional updates
if_none_match: Set to "*" to prevent overwriting
Returns:
RecordSet: The created or updated record set
Raises:
HttpResponseError: If the operation fails
"""Usage Examples:
from azure.mgmt.dns.models import RecordSet, ARecord, CnameRecord, MxRecord, RecordType
# Create an A record set with multiple IP addresses
a_record_set = RecordSet(
ttl=300,
a_records=[
ARecord(ipv4_address="192.0.2.1"),
ARecord(ipv4_address="192.0.2.2")
]
)
result = dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="www",
record_type=RecordType.A,
parameters=a_record_set
)
# Create a CNAME record
cname_record_set = RecordSet(
ttl=3600,
cname_record=CnameRecord(cname="www.example.com")
)
dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="blog",
record_type=RecordType.CNAME,
parameters=cname_record_set
)
# Create MX records for email
mx_record_set = RecordSet(
ttl=3600,
mx_records=[
MxRecord(preference=10, exchange="mail1.example.com"),
MxRecord(preference=20, exchange="mail2.example.com")
]
)
dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="@", # Apex record
record_type=RecordType.MX,
parameters=mx_record_set
)Updates specific properties of an existing record set without replacing the entire record set.
def update(
self,
resource_group_name: str,
zone_name: str,
relative_record_set_name: str,
record_type: Union[str, RecordType],
parameters: Union[RecordSet, IO[bytes]],
if_match: Optional[str] = None,
**kwargs: Any
) -> RecordSet:
"""
Update properties of an existing DNS record set.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
relative_record_set_name: Name of the record set
record_type: Type of DNS record
parameters: Record set with updated properties
if_match: ETag value for conditional updates
Returns:
RecordSet: The updated record set
Raises:
HttpResponseError: If the record set is not found
"""Permanently deletes a DNS record set and all its records.
def delete(
self,
resource_group_name: str,
zone_name: str,
relative_record_set_name: str,
record_type: Union[str, RecordType],
if_match: Optional[str] = None,
**kwargs: Any
) -> None:
"""
Delete a DNS record set.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
relative_record_set_name: Name of the record set
record_type: Type of DNS record
if_match: ETag value for conditional deletion
Raises:
HttpResponseError: If the record set is not found
"""Usage Example:
# Delete a specific record set
dns_client.record_sets.delete(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="old-service",
record_type=RecordType.A
)Retrieves a specific DNS record set and its records.
def get(
self,
resource_group_name: str,
zone_name: str,
relative_record_set_name: str,
record_type: Union[str, RecordType],
**kwargs: Any
) -> RecordSet:
"""
Get a specific DNS record set.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
relative_record_set_name: Name of the record set
record_type: Type of DNS record
Returns:
RecordSet: The DNS record set with all its records
Raises:
HttpResponseError: If the record set is not found
"""Lists DNS record sets within a zone, with options to filter by type.
def list_by_dns_zone(
self,
resource_group_name: str,
zone_name: str,
top: Optional[int] = None,
recordsetnamesuffix: Optional[str] = None,
**kwargs: Any
) -> ItemPaged[RecordSet]:
"""
List all record sets in a DNS zone.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
top: Maximum number of record sets to return
recordsetnamesuffix: Filter by record set name suffix
Returns:
ItemPaged[RecordSet]: Paginated list of record sets
"""
def list_by_type(
self,
resource_group_name: str,
zone_name: str,
record_type: Union[str, RecordType],
top: Optional[int] = None,
recordsetnamesuffix: Optional[str] = None,
**kwargs: Any
) -> ItemPaged[RecordSet]:
"""
List record sets of a specific type in a DNS zone.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
record_type: Type of DNS record to filter by
top: Maximum number of record sets to return
recordsetnamesuffix: Filter by record set name suffix
Returns:
ItemPaged[RecordSet]: Paginated list of record sets
"""
def list_all_by_dns_zone(
self,
resource_group_name: str,
zone_name: str,
top: Optional[int] = None,
record_set_name_suffix: Optional[str] = None,
**kwargs: Any
) -> ItemPaged[RecordSet]:
"""
Alternative endpoint for listing all record sets in a zone.
Args:
resource_group_name: Name of the resource group containing the zone
zone_name: Name of the DNS zone
top: Maximum number of record sets to return
record_set_name_suffix: Filter by record set name suffix
Returns:
ItemPaged[RecordSet]: Paginated list of record sets
"""Usage Examples:
# List all record sets in a zone
all_records = dns_client.record_sets.list_by_dns_zone(
resource_group_name="my-rg",
zone_name="example.com"
)
for record_set in all_records:
print(f"{record_set.name} ({record_set.type}) - TTL: {record_set.ttl}")
# List only A records
a_records = dns_client.record_sets.list_by_type(
resource_group_name="my-rg",
zone_name="example.com",
record_type=RecordType.A
)
for record_set in a_records:
print(f"A record: {record_set.name} -> {[r.ipv4_address for r in record_set.a_records]}")
# List records with name suffix filtering
web_records = dns_client.record_sets.list_by_dns_zone(
resource_group_name="my-rg",
zone_name="example.com",
recordsetnamesuffix="web" # Matches "web", "web1", "webapp", etc.
)class ARecord:
"""IPv4 address record."""
ipv4_address: str # IPv4 address (e.g., "192.0.2.1")Usage:
from azure.mgmt.dns.models import RecordSet, ARecord
record_set = RecordSet(
ttl=300,
a_records=[
ARecord(ipv4_address="192.0.2.1"),
ARecord(ipv4_address="192.0.2.2")
]
)class AaaaRecord:
"""IPv6 address record."""
ipv6_address: str # IPv6 address (e.g., "2001:db8::1")class CnameRecord:
"""Canonical name record (alias)."""
cname: str # Target domain nameUsage:
from azure.mgmt.dns.models import RecordSet, CnameRecord
cname_record_set = RecordSet(
ttl=3600,
cname_record=CnameRecord(cname="target.example.com")
)class MxRecord:
"""Mail exchange record for email routing."""
preference: int # Priority (lower numbers have higher priority)
exchange: str # Mail server hostnameclass NsRecord:
"""Name server record."""
nsdname: str # Name server domain nameclass TxtRecord:
"""Text record for arbitrary text data."""
value: List[str] # List of text strings (each ≤255 characters)Usage:
from azure.mgmt.dns.models import RecordSet, TxtRecord
txt_record_set = RecordSet(
ttl=300,
txt_records=[
TxtRecord(value=["v=spf1 include:_spf.google.com ~all"]),
TxtRecord(value=["google-site-verification=abc123..."])
]
)class SrvRecord:
"""Service record for service discovery."""
priority: int # Priority (lower is higher priority)
weight: int # Weight for load balancing among same priority
port: int # Service port number
target: str # Target hostnameclass PtrRecord:
"""Pointer record for reverse DNS lookups."""
ptrdname: str # Target domain nameclass SoaRecord:
"""Start of Authority record (zone metadata)."""
host: str # Primary name server
email: str # Administrator email (dots replaced with @)
serial_number: int # Zone serial number
refresh_time: int # Refresh interval (seconds)
retry_time: int # Retry interval (seconds)
expire_time: int # Expiration time (seconds)
minimum_ttl: int # Minimum TTL for negative cachingclass CaaRecord:
"""Certificate Authority Authorization record."""
flags: int # Flags (typically 0 or 128 for critical)
tag: str # Property tag ("issue", "issuewild", "iodef")
value: str # Property value (CA domain or URL)Usage:
from azure.mgmt.dns.models import RecordSet, CaaRecord
caa_record_set = RecordSet(
ttl=3600,
caa_records=[
CaaRecord(flags=0, tag="issue", value="letsencrypt.org"),
CaaRecord(flags=0, tag="issue", value="digicert.com"),
CaaRecord(flags=128, tag="iodef", value="mailto:security@example.com")
]
)class RecordSet:
"""
Represents a DNS record set within a zone.
A record set groups multiple DNS records of the same type and name.
"""
# Read-only properties
id: str # Azure resource ID
name: str # Record set name relative to zone
type: str # Record set type (e.g., "Microsoft.Network/dnszones/A")
etag: str # ETag for concurrency control
fqdn: str # Fully qualified domain name (read-only)
# Configurable properties
ttl: int # Time-to-live in seconds (1-2147483647)
metadata: Dict[str, str] # Custom metadata key-value pairs
target_resource: SubResource # Reference to Azure resource (for alias records)
# Record type specific arrays (only one should be populated)
a_records: List[ARecord] # IPv4 address records
aaaa_records: List[AaaaRecord] # IPv6 address records
caa_records: List[CaaRecord] # Certificate authority records
cname_record: CnameRecord # Canonical name (single record)
mx_records: List[MxRecord] # Mail exchange records
ns_records: List[NsRecord] # Name server records
ptr_records: List[PtrRecord] # Pointer records
soa_record: SoaRecord # Start of authority (single record)
srv_records: List[SrvRecord] # Service records
txt_records: List[TxtRecord] # Text recordsclass RecordType(str, Enum):
"""Supported DNS record types."""
A = "A" # IPv4 address
AAAA = "AAAA" # IPv6 address
CAA = "CAA" # Certificate Authority Authorization
CNAME = "CNAME" # Canonical name
MX = "MX" # Mail exchange
NS = "NS" # Name server
PTR = "PTR" # Pointer (reverse DNS)
SOA = "SOA" # Start of authority
SRV = "SRV" # Service record
TXT = "TXT" # Text recordUse ETags to prevent conflicting updates when multiple clients modify the same record set:
# Get current record set with ETag
record_set = dns_client.record_sets.get(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="api",
record_type=RecordType.A
)
# Modify the record set
record_set.a_records.append(ARecord(ipv4_address="192.0.2.100"))
# Update with ETag to prevent conflicts
try:
updated_record_set = dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="api",
record_type=RecordType.A,
parameters=record_set,
if_match=record_set.etag
)
print("Update successful")
except HttpResponseError as e:
if e.status_code == 412:
print("Conflict: Record set was modified by another client")Process multiple record sets efficiently:
from concurrent.futures import ThreadPoolExecutor
from azure.mgmt.dns.models import RecordSet, ARecord, RecordType
def create_record_set(name, ip_address):
record_set = RecordSet(
ttl=300,
a_records=[ARecord(ipv4_address=ip_address)]
)
return dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name=name,
record_type=RecordType.A,
parameters=record_set
)
# Create multiple record sets in parallel
record_configs = [
("web1", "192.0.2.10"),
("web2", "192.0.2.11"),
("web3", "192.0.2.12")
]
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(lambda config: create_record_set(*config), record_configs))
print(f"Created {len(results)} record sets")from azure.core.exceptions import HttpResponseError
try:
record_set = dns_client.record_sets.create_or_update(
resource_group_name="my-rg",
zone_name="example.com",
relative_record_set_name="test",
record_type=RecordType.A,
parameters=RecordSet(ttl=300, a_records=[ARecord(ipv4_address="192.0.2.1")])
)
except HttpResponseError as e:
if e.status_code == 400:
print("Bad request: Check record set configuration")
elif e.status_code == 404:
print("Zone not found")
elif e.status_code == 409:
print("Conflict: Record set already exists (when using if_none_match)")
elif e.status_code == 412:
print("Precondition failed: ETag mismatch")
else:
print(f"Unexpected error: {e.status_code} - {e.message}")Common error scenarios:
if_none_match="*"Install with Tessl CLI
npx tessl i tessl/pypi-azure-mgmt-dns