technitium 0.4.0

Typed async Rust client for the Technitium DNS Server API
Documentation
use crate::client::Client;
use crate::error::Error;
use crate::types::record::{AddRecord, DeleteRecordId, Record, UpdateRecord};
use crate::types::zone::{ZoneOptions, ZoneType};

/// A zone-scoped handle that delegates to [`Client`] with a bound zone name.
///
/// Created via [`Client::zone`] or [`Client::zone_for_domain`].
///
/// # Examples
///
/// ```no_run
/// # async fn example() -> Result<(), technitium::Error> {
/// let client = technitium::Client::connect(
///     "http://localhost:5380", "admin", "admin",
/// ).await?;
///
/// let zone = client.zone("example.com");
/// let record = technitium::AddRecord::a(
///     "www.example.com", technitium::Ttl(300), "192.168.1.1".parse().unwrap(),
/// );
/// zone.add_record(&record).await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct ZoneClient<'a> {
    client: &'a Client,
    zone: String,
}

impl<'a> ZoneClient<'a> {
    pub(crate) fn new(client: &'a Client, zone: String) -> Self {
        Self { client, zone }
    }

    /// Returns the bound zone name.
    #[must_use]
    pub fn name(&self) -> &str {
        &self.zone
    }

    /// List DNS records in this zone, optionally filtered by domain.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn list_records(&self, domain: Option<&str>) -> Result<Vec<Record>, Error> {
        self.client.list_records(&self.zone, domain).await
    }

    /// Add a DNS record to this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn add_record(&self, record: &AddRecord) -> Result<(), Error> {
        self.client.add_record(&self.zone, record).await
    }

    /// Update an existing DNS record in this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn update_record(&self, record: &UpdateRecord) -> Result<(), Error> {
        self.client.update_record(&self.zone, record).await
    }

    /// Delete a DNS record from this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn delete_record(
        &self,
        domain: &str,
        record_id: &DeleteRecordId,
    ) -> Result<(), Error> {
        self.client
            .delete_record(&self.zone, domain, record_id)
            .await
    }

    /// Delete this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn delete(&self) -> Result<(), Error> {
        self.client.delete_zone(&self.zone).await
    }

    /// Enable this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn enable(&self) -> Result<(), Error> {
        self.client.enable_zone(&self.zone).await
    }

    /// Disable this zone.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn disable(&self) -> Result<(), Error> {
        self.client.disable_zone(&self.zone).await
    }

    /// Export this zone as a DNS zone file (text).
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn export(&self) -> Result<String, Error> {
        self.client.export_zone(&self.zone).await
    }

    /// Import records into this zone from a DNS zone file.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn import(&self, zone_file: &[u8]) -> Result<(), Error> {
        self.client.import_zone(&self.zone, zone_file).await
    }

    /// Clone this zone to a new name.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn clone_to(&self, new_zone: &str) -> Result<(), Error> {
        self.client.clone_zone(&self.zone, new_zone).await
    }

    /// Convert this zone to a different type.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn convert(&self, new_type: ZoneType) -> Result<(), Error> {
        self.client.convert_zone(&self.zone, new_type).await
    }

    /// Get this zone's configuration options.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn options(&self) -> Result<ZoneOptions, Error> {
        self.client.get_zone_options(&self.zone).await
    }

    /// Set this zone's configuration options.
    ///
    /// # Errors
    ///
    /// Returns `Error` if the API request fails.
    pub async fn set_options(&self, options: &ZoneOptions) -> Result<(), Error> {
        self.client.set_zone_options(&self.zone, options).await
    }
}