1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use super::{ApiLinks, ApiMeta};
use super::{HasPagination, HasResponse, HasValue};
use {ROOT_URL, STATIC_URL_ERROR};
use method::{Create, Delete, Get, List};
use request::DomainRequest;
use request::Request;
use serde::Serialize;
use std::fmt::Display;
use std::net::IpAddr;
use url::Url;

const DOMAINS_SEGMENT: &'static str = "domains";

/// Domain resources are domain names that you have purchased from a domain
/// name registrar that you are managing through the DigitalOcean DNS interface.
///
/// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#domains)
#[derive(Deserialize, Serialize, Debug, Clone, Getters, Setters)]
pub struct Domain {
    /// The name of the domain itself. This should follow the standard domain
    /// format of domain.TLD. For instance, example.com is a valid domain name.
    #[get = "pub"]
    name: String,
    /// This value is the time to live for the records on this domain, in
    /// seconds. This defines the time frame that clients can cache queried
    /// information before a refresh should be requested.
    #[get = "pub"]
    ttl: Option<usize>,
    /// This attribute contains the complete contents of the zone file for the
    /// selected domain. Individual domain record resources should be used to
    /// get more granular control over records. However, this attribute can
    /// also be used to get information about the SOA record, which is created
    /// automatically and is not accessible as an individual record resource.
    #[get = "pub"]
    zone_file: Option<String>,
}

impl Domain {
    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#create-a-new-domain)
    pub fn create<N, I>(name: N, ip_address: I) -> DomainRequest<Create, Domain>
    where
        N: AsRef<str> + Serialize + Display,
        I: Into<IpAddr> + Serialize + Display,
    {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut().expect(STATIC_URL_ERROR).push(
            DOMAINS_SEGMENT,
        );

        let mut req = Request::new(url);
        req.set_body(json!({
            "name": name,
            "ip_address": ip_address,
        }));
        req
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-domains)
    pub fn list() -> DomainRequest<List, Vec<Domain>> {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut().expect(STATIC_URL_ERROR).push(
            DOMAINS_SEGMENT,
        );

        Request::new(url)
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-domain)
    pub fn get<N>(name: N) -> DomainRequest<Get, Domain>
    where
        N: AsRef<str> + Display,
    {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(DOMAINS_SEGMENT)
            .push(name.as_ref());

        Request::new(url)
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#delete-a-domain)
    pub fn delete<N>(name: N) -> DomainRequest<Delete, ()>
    where
        N: AsRef<str> + Display,
    {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(DOMAINS_SEGMENT)
            .push(name.as_ref());

        Request::new(url)
    }
}

/// Response type returned from Digital Ocean.
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct DomainResponse {
    domain: Domain,
}

impl HasResponse for Domain {
    type Response = DomainResponse;
}

impl HasValue for DomainResponse {
    type Value = Domain;
    fn value(self) -> Domain {
        self.domain
    }
}

/// Response type returned from Digital Ocean.
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct DomainListResponse {
    domains: Vec<Domain>,
    links: ApiLinks,
    meta: ApiMeta,
}

impl HasResponse for Vec<Domain> {
    type Response = DomainListResponse;
}

impl HasPagination for DomainListResponse {
    fn next_page(&self) -> Option<Url> {
        self.links.next()
    }
}

impl HasValue for DomainListResponse {
    type Value = Vec<Domain>;
    fn value(self) -> Vec<Domain> {
        self.domains
    }
}