tencent_sdk/services/dns/
create.rs

1use crate::{
2    client::{TencentCloudAsync, TencentCloudBlocking},
3    core::{Endpoint, TencentCloudResult},
4    services::dns::{RecordLine, RecordType},
5};
6use serde::Deserialize;
7use serde_json::{json, Value};
8use std::borrow::Cow;
9
10#[derive(Debug, Deserialize)]
11pub struct CreateTXTRecordResponse {
12    #[serde(rename = "Response")]
13    pub response: CreateTXTRecordResult,
14}
15
16#[derive(Debug, Deserialize)]
17pub struct CreateTXTRecordResult {
18    #[serde(rename = "RecordId")]
19    pub record_id: Option<u64>,
20    #[serde(rename = "RequestId")]
21    pub request_id: String,
22}
23
24/// Request parameters for adding a TXT record.
25pub struct CreateTXTRecord<'a> {
26    pub domain: &'a str,
27    pub sub_domain: &'a str,
28    pub record_line: RecordLine<'a>,
29    pub value: &'a str,
30    pub record_type: RecordType<'a>,
31    pub domain_id: Option<u64>,
32    pub record_line_id: Option<&'a str>,
33    pub ttl: Option<u32>,
34    pub status: Option<&'a str>,
35    pub remark: Option<&'a str>,
36    pub group_id: Option<u64>,
37}
38
39impl<'a> CreateTXTRecord<'a> {
40    /// Create a TXT record request (defaults `RecordType` to `"TXT"`).
41    pub fn new(domain: &'a str, sub_domain: &'a str, record_line: &'a str, value: &'a str) -> Self {
42        Self {
43            domain,
44            sub_domain,
45            record_line: record_line.into(),
46            value,
47            record_type: RecordType::Txt,
48            domain_id: None,
49            record_line_id: None,
50            ttl: None,
51            status: None,
52            remark: None,
53            group_id: None,
54        }
55    }
56
57    pub fn with_domain_id(mut self, domain_id: u64) -> Self {
58        self.domain_id = Some(domain_id);
59        self
60    }
61
62    pub fn with_record_line_id(mut self, record_line_id: &'a str) -> Self {
63        self.record_line_id = Some(record_line_id);
64        self
65    }
66
67    pub fn with_ttl(mut self, ttl: u32) -> Self {
68        self.ttl = Some(ttl);
69        self
70    }
71
72    pub fn with_status(mut self, status: &'a str) -> Self {
73        self.status = Some(status);
74        self
75    }
76
77    pub fn with_remark(mut self, remark: &'a str) -> Self {
78        self.remark = Some(remark);
79        self
80    }
81
82    pub fn with_group_id(mut self, group_id: u64) -> Self {
83        self.group_id = Some(group_id);
84        self
85    }
86
87    pub fn with_sub_domain(mut self, sub_domain: &'a str) -> Self {
88        self.sub_domain = sub_domain;
89        self
90    }
91
92    pub fn with_record_type(mut self, record_type: RecordType<'a>) -> Self {
93        self.record_type = record_type;
94        self
95    }
96
97    pub fn with_record_line(mut self, record_line: RecordLine<'a>) -> Self {
98        self.record_line = record_line;
99        self
100    }
101}
102
103impl<'a> Endpoint for CreateTXTRecord<'a> {
104    type Output = CreateTXTRecordResponse;
105
106    fn service(&self) -> Cow<'static, str> {
107        Cow::Borrowed("dnspod")
108    }
109
110    fn action(&self) -> Cow<'static, str> {
111        Cow::Borrowed("CreateRecord")
112    }
113
114    fn version(&self) -> Cow<'static, str> {
115        Cow::Borrowed("2021-03-23")
116    }
117
118    fn region(&self) -> Option<Cow<'_, str>> {
119        // DNSPod CreateRecord does not require a region parameter
120        None
121    }
122
123    fn payload(&self) -> Value {
124        let mut payload = json!({
125            "Domain": self.domain,
126            "SubDomain": self.sub_domain,
127            "RecordType": self.record_type,
128            "RecordLine": self.record_line,
129            "Value": self.value,
130        });
131
132        if let Some(domain_id) = self.domain_id {
133            payload["DomainId"] = json!(domain_id);
134        }
135        if let Some(record_line_id) = self.record_line_id {
136            payload["RecordLineId"] = json!(record_line_id);
137        }
138        if let Some(ttl) = self.ttl {
139            payload["TTL"] = json!(ttl);
140        }
141        if let Some(status) = self.status {
142            payload["Status"] = json!(status);
143        }
144        if let Some(remark) = self.remark {
145            payload["Remark"] = json!(remark);
146        }
147        if let Some(group_id) = self.group_id {
148            payload["GroupId"] = json!(group_id);
149        }
150
151        payload
152    }
153}
154
155/// Call DNSPod `CreateRecord` with the async client.
156pub async fn create_txt_record_async(
157    client: &TencentCloudAsync,
158    request: &CreateTXTRecord<'_>,
159) -> TencentCloudResult<CreateTXTRecordResponse> {
160    client.request(request).await
161}
162
163/// Call DNSPod `CreateRecord` with the blocking client.
164pub fn create_txt_record_blocking(
165    client: &TencentCloudBlocking,
166    request: &CreateTXTRecord<'_>,
167) -> TencentCloudResult<CreateTXTRecordResponse> {
168    client.request(request)
169}
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[test]
176    fn test_create_txt_record_builder() {
177        let request = CreateTXTRecord::new("example.com", "www", "default", "test-value")
178            .with_ttl(600)
179            .with_status("ENABLE")
180            .with_remark("test record")
181            .with_group_id(1234);
182
183        assert_eq!(request.domain, "example.com");
184        assert_eq!(request.sub_domain, "www");
185        assert_eq!(request.record_line, RecordLine::Default);
186        assert_eq!(request.value, "test-value");
187        assert_eq!(request.record_type, RecordType::Txt);
188        assert_eq!(request.ttl, Some(600));
189        assert_eq!(request.status, Some("ENABLE"));
190        assert_eq!(request.remark, Some("test record"));
191        assert_eq!(request.group_id, Some(1234));
192    }
193
194    #[test]
195    fn test_create_txt_record_payload() {
196        let request = CreateTXTRecord::new("example.com", "www", "default", "test-value")
197            .with_ttl(600)
198            .with_status("ENABLE");
199
200        let payload = request.payload();
201        assert_eq!(payload["Domain"], json!("example.com"));
202        assert_eq!(payload["SubDomain"], json!("www"));
203        assert_eq!(payload["RecordType"], json!("TXT"));
204        assert_eq!(payload["RecordLine"], json!(RecordLine::Default.as_str()));
205        assert_eq!(payload["Value"], json!("test-value"));
206        assert_eq!(payload["TTL"], json!(600));
207        assert_eq!(payload["Status"], json!("ENABLE"));
208    }
209
210    #[test]
211    fn test_deserialize_create_response() {
212        let json = r#"{
213            "Response": {
214                "RecordId": 123,
215                "RequestId": "req-123456"
216            }
217        }"#;
218
219        let response: CreateTXTRecordResponse =
220            serde_json::from_str(json).expect("deserialize CreateTXTRecordResponse");
221        assert_eq!(response.response.record_id, Some(123));
222        assert_eq!(response.response.request_id, "req-123456");
223    }
224
225    #[test]
226    fn test_endpoint_implementation() {
227        let create_request =
228            CreateTXTRecord::new("test.com", "_acme-challenge", "default", "value");
229        assert_eq!(create_request.service().as_ref(), "dnspod");
230        assert_eq!(create_request.action().as_ref(), "CreateRecord");
231        assert_eq!(create_request.version().as_ref(), "2021-03-23");
232        assert!(create_request.region().is_none());
233    }
234
235    #[test]
236    fn custom_record_type_and_line_serialize() {
237        let request = CreateTXTRecord::new("example.com", "www", "default", "value")
238            .with_record_type(RecordType::from("CNAME"))
239            .with_record_line(RecordLine::from("custom-line"));
240
241        let payload = request.payload();
242        assert_eq!(payload["RecordType"], json!("CNAME"));
243        assert_eq!(payload["RecordLine"], json!("custom-line"));
244    }
245}