Skip to main content

A Python gateway for DNS.services API

Project description

DNS.Services Gateway

PyPI version Python Versions License: MIT Code style: black Development Status

Built with various AI coding tools

This entire production-ready module was created in just two weeks during the evenings using Windsurf Editor. From initial planning to comprehensive testing, Windsurf's AI-powered capabilities enabled rapid development while maintaining exceptional code quality:

  • >70% test coverage
  • Full type safety
  • Async-first architecture
  • Production-ready error handling

It was fun learning/using Windsurf, and I'm excited to share the results with the community.

Description

No affiliation with DNS.services, made by users of DNS.services

Although no affiliation with DNS.services, I did present the module to them for approval before making it available.

A Python client library and CLI tool for managing Domains and DNS records through the DNS.services API. This tool provides a simple and intuitive interface for managing domains and DNS records programmatically or via command line, single entry, batch entries or use our template system.

For this module, the DNS.Services API endpoints have been descoped, to only implement domains, DNS and Clientarea endpoints.

The scope of this module is to securely manage domains and DNS entries programatically.

Features

  • Flexible Authentication
    • JWT token-based authentication
    • Basic Authentication support
    • Automatic token refresh handling
  • Comprehensive domain management
    • Bulk domain listing with metadata
    • Pagination and filtering support
    • Domain details with expiration dates
    • Configuration verification
    • Nameserver management
    • Domain availability checking
    • TLD listing with pricing
    • DNSSEC key management
  • Full DNS record management
    • Support for A, AAAA, CNAME, MX, and TXT records
    • Type-specific validation for all record types
    • Record verification system
    • TTL management
    • Batch operations support
  • Performance features
    • Async/await for non-blocking operations
    • Efficient bulk operations
    • Parallel processing for batch operations
    • Comprehensive error handling
  • Quality assurance
    • Full type hints with mypy
    • 97% test coverage
    • Black code formatting
    • Flake8 compliance

DNS Templates

The DNS Services Gateway supports a powerful templating system for managing DNS configurations across multiple domains and environments. Templates allow you to define reusable DNS configurations with variable substitution, environment-specific overrides, and comprehensive validation.

Template Features

  • YAML-based configuration
  • Variable substitution
  • Environment-specific overrides
  • Pre-application validation
  • Safety features (backup, rollback)
  • Version tracking
  • Multiple application modes
  • Change notifications (Email/Slack)
  • Change tracking and history

Template Structure

# Template metadata
metadata:
  version: "1.0.0"
  description: "Common web and mail configuration"
  author: "DNS Services Gateway"

# Variables for substitution
variables:
  domain: "example.com"
  ttl: 3600

# Record groups by purpose
records:
  web:
    - type: A
      name: "@"
      value: "203.0.113.10"
      ttl: ${ttl}
  mail:
    - type: MX
      name: "@"
      value: "mail.${domain}"
      priority: 10
      ttl: ${ttl}

# Environment overrides
environments:
  production:
    variables:
      ttl: 3600
  staging:
    variables:
      ttl: 300
      domain: "staging.example.com"

# Safety settings
settings:
  backup:
    enabled: true
    retention: 30

  rollback:
    enabled: true
    automatic: true

  change_management:
    require_approval: true
    notify:
      email: ["admin@example.com"]
      slack: ["#dns-changes"]

Using Templates

CLI Usage

  1. Create a new template:
dns-services template create example-com -d "Example.com DNS template" -a "John Doe"
  1. Validate a template:
dns-services template validate ~/.dns-services/templates/example-com.yaml
  1. Apply template with different modes:
# Force mode (update/create all records)
dns-services template apply template.yaml -d example.com -e production

# Create only missing records
dns-services template apply template.yaml -d example.com -e production -m create-missing

# Update only existing records
dns-services template apply template.yaml -d example.com -e production -m update-existing

# Dry run to see changes
dns-services template apply template.yaml -d example.com -e production --dry-run
  1. View change history:
# List all changes
dns-services template changes

# Filter by status
dns-services template changes --status pending

# Show specific change
dns-services template show-change CHG_20230615_123456

Python API Usage

from dns_services_gateway import DNSServicesClient

async with DNSServicesClient() as client:
    # Load and validate template
    template = await client.load_template("my-domain-template.yaml")

    # Apply template with dry-run
    result = await client.apply_template(
        template,
        domain="example.com",
        environment="production",
        mode="force",  # or "create-missing", "update-existing"
        dry_run=True
    )

    # Apply template if dry-run looks good
    if result.is_valid:
        await client.apply_template(
            template,
            domain="example.com",
            environment="production",
            mode="force",
            dry_run=False
        )

Template Best Practices

  1. Version Your Templates: Always include version information in template metadata
  2. Use Variables: Make templates reusable by using variables for common values
  3. Group Records: Organize records by purpose (web, mail, security, etc.)
  4. Include Documentation: Add descriptions to records and document template purpose
  5. Test Changes: Always use dry-run before applying templates
  6. Back Up Records: Enable backup feature in template settings
  7. Environment Separation: Use environment-specific overrides for different stages
  8. Change Management: Enable approval workflow for production changes
  9. Notifications: Configure email/Slack notifications for important changes
  10. Use Appropriate Modes: Choose the right application mode for your use case

Safety Features

Templates include several safety features:

  • Pre-application validation
  • Automatic backup of existing records
  • Automatic rollback on failure
  • Change approval workflow
  • Email and Slack notifications
  • Detailed change logging
  • Change tracking with unique IDs
  • Multiple application modes
  • Dry-run capability
  • Conflict detection
  • Version compatibility checking

For more details and examples, see the Template Documentation.

Installation

Using pip

pip install dns-services-gateway

From source

git clone https://github.com/yourusername/dns-services-gateway.git
cd dns-services-gateway
pip install -r requirements.txt

Usage

Installation

# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate  # Linux/Mac
# or
.\venv\Scripts\activate  # Windows

# Install package
pip install -r requirements.txt

Configuration

Set up your environment variables:

# Required
export DNS_SERVICES_USERNAME="your_username"
export DNS_SERVICES_PASSWORD="your_password"

# Optional
export DNS_SERVICES_BASE_URL="https://dns.services"  # Default
export DNS_SERVICES_TOKEN_PATH="~/.dns-services/token"  # JWT token storage
export DNS_SERVICES_VERIFY_SSL="true"  # Enable/disable SSL verification
export DNS_SERVICES_TIMEOUT="30"  # API timeout in seconds
export DNS_SERVICES_DEBUG="false"  # Enable debug logging
export DNS_SERVICES_AUTH_TYPE="JWT"  # Authentication type: JWT or BASIC

Or create a .env file (see .env.example).

Examples

from dns_services_gateway import DNSServicesClient, DNSServicesConfig, AuthType
from dns_services_gateway.records import ARecord, MXRecord, RecordAction
from dns_services_gateway.dnssec import DNSSECManager

# Create client with JWT authentication (default)
config = DNSServicesConfig.from_env()
client = DNSServicesClient(config)

# Or use Basic Authentication
basic_config = DNSServicesConfig(
    username="your_username",
    password="your_password",
    auth_type=AuthType.BASIC
)
basic_client = DNSServicesClient(basic_config)

# List domains with pagination and metadata
response = await client.list_domains(
    page=1,
    per_page=20,
    include_metadata=True,
    filters={"status": "active", "expiring_within_days": 30}
)

# Access bulk domain information
for domain in response.domains:
    print(f"Domain: {domain.name}")
    print(f"Status: {domain.status}")
    print(f"Expires: {domain.expiration_date}")
    print(f"Nameservers: {', '.join(domain.nameservers)}")

# Get domain details with full metadata
response = await client.get_domain_details("example.com")

# Verify domain
response = await client.verify_domain("example.com")

# Get domain metadata
response = await client.get_domain_metadata("example.com")

# Check domain availability
response = await client.check_domain_availability(
    domain="example.com",
    check_premium=True  # Optional: check if domain is premium
)

# List available TLDs
response = await client.list_available_tlds()
for tld in response.tlds:
    print(f"{tld.name}: {tld.price} {tld.currency}")

# Manage DNS records
records_manager = client.records

# Create an A record
a_record = ARecord(name="www", value="192.168.1.1", ttl=3600)
response = await records_manager.manage_record(
    action=RecordAction.CREATE,
    domain="example.com",
    record=a_record
)

# Create an MX record with priority
mx_record = MXRecord(
    name="@",
    value="mail.example.com",
    priority=10,
    ttl=3600
)
response = await records_manager.manage_record(
    action=RecordAction.CREATE,
    domain="example.com",
    record=mx_record
)

# Manage DNSSEC keys
dnssec_manager = client.dnssec

# List DNSSEC keys
response = await dnssec_manager.list_keys("example.com")
for key in response.keys:
    print(f"Key tag: {key.key_tag}, Algorithm: {key.algorithm}")

# Add a DNSSEC key
response = await dnssec_manager.add_key(
    domain="example.com",
    algorithm=13,  # ECDSAP256SHA256
    public_key="your_public_key_data",
    flags=256  # Optional flags
)

# Remove a DNSSEC key
response = await dnssec_manager.remove_key(
    domain="example.com",
    key_tag=12345
)

# Verify record propagation
verified = await records_manager.verify_record(
    domain="example.com",
    record=a_record,
    timeout=60  # Wait up to 60 seconds
)

API Documentation

For detailed API documentation and examples, please see:

Known Issues

Test Coverage Reporting

When running tests with pytest-cov (coverage.py 6.0.0), you may see the following warning:

/venv/lib/python3.12/site-packages/coverage/inorout.py:508: CoverageWarning: Module src/dns_services_gateway/domain.py was never imported. (module-not-imported)

This is a known issue with coverage.py when using Python 3.12.3. The warning is a false positive and does not affect the actual test coverage (currently at 97%) or functionality. The module is properly imported and tested, but coverage.py sometimes fails to detect imports in certain Python module structures.

For more information, see:

  • Coverage.py version: 6.0.0
  • Python version: 3.12.3

This issue will be resolved when coverage.py releases an update that better handles Python 3.12's module system.

Contributing

Please follow the guidelines in docs/guidelines.md for contributing to this project.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dns_services_gateway-0.9.6.tar.gz (76.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dns_services_gateway-0.9.6-py3-none-any.whl (48.8 kB view details)

Uploaded Python 3

File details

Details for the file dns_services_gateway-0.9.6.tar.gz.

File metadata

  • Download URL: dns_services_gateway-0.9.6.tar.gz
  • Upload date:
  • Size: 76.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.3

File hashes

Hashes for dns_services_gateway-0.9.6.tar.gz
Algorithm Hash digest
SHA256 de44dd805bac5f72cf471a5f1c5b43cb433d0b2ce4d95c816e7c7e4437a2063c
MD5 a3f2fec546722a69077295140fb41d04
BLAKE2b-256 71483bcf89ef18f9632ecaffba81b2620d74afd8d613621a9e8a6da8cf29abcb

See more details on using hashes here.

File details

Details for the file dns_services_gateway-0.9.6-py3-none-any.whl.

File metadata

File hashes

Hashes for dns_services_gateway-0.9.6-py3-none-any.whl
Algorithm Hash digest
SHA256 7a5f30db18cf1e8b9e79c7c023a2a4bd36d06124213f1405fbac5a61aa88f1de
MD5 89b678d4051ebd6f1ab995e28c3b082a
BLAKE2b-256 5d7a54795bc805896fcdd49727168326d3eccc4dc9265fda37ade4e7fa909fef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page