1use std::net::{Ipv4Addr, Ipv6Addr};
2
3use serde::{Deserialize, Serialize};
4use time::OffsetDateTime;
5
6use super::EntityDescriptorConst;
7
8#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
9pub struct DnsRecordSpecV1 {
10 pub external_id: Option<String>,
11 pub root_domain: String,
13 pub root_domain_external_id: Option<String>,
15 pub data: DnsRecordData,
16}
17
18impl DnsRecordSpecV1 {
19 pub fn kind(&self) -> DnsRecordKind {
20 self.data.kind_name()
21 }
22
23 pub fn full_domain(&self) -> String {
24 let name = self.data.common().name.trim().trim_end_matches('.');
25
26 if name.is_empty() || name == "@" {
27 self.root_domain.clone()
28 } else {
29 format!("{}.{}", name, self.root_domain)
30 }
31 }
32}
33
34impl EntityDescriptorConst for DnsRecordSpecV1 {
35 const NAMESPACE: &'static str = "wasmer.io";
36 const NAME: &'static str = "DnsRecord";
37 const VERSION: &'static str = "v1";
38 const KIND: &'static str = "wasmer.io/DnsRecord.v1";
39
40 type Spec = Self;
41 type State = ();
42}
43
44#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Copy, Debug, schemars::JsonSchema)]
45pub enum DnsRecordKind {
46 A,
47 Aaaa,
48 CName,
49 Txt,
50 Mx,
51 Ns,
52 Caa,
53 DName,
54 Ptr,
55 Soa,
56}
57
58impl DnsRecordKind {
59 pub fn as_str(&self) -> &str {
60 match self {
61 Self::A => "A",
62 Self::Aaaa => "AAAA",
63 Self::CName => "CNAME",
64 Self::Txt => "TXT",
65 Self::Mx => "MX",
66 Self::Ns => "NS",
67 Self::Caa => "CAA",
68 Self::DName => "DNAME",
69 Self::Ptr => "PTR",
70 Self::Soa => "SOA",
71 }
72 }
73}
74
75impl std::fmt::Display for DnsRecordKind {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", self.as_str())
78 }
79}
80
81#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
82pub enum DnsRecordData {
83 #[serde(rename = "a")]
84 A(ARecord),
85 #[serde(rename = "aaaa")]
86 Aaaa(AaaaRecord),
87 #[serde(rename = "cname")]
88 CName(CNameRecord),
89 #[serde(rename = "txt")]
90 Txt(TxtRecord),
91 #[serde(rename = "mx")]
92 Mx(MxRecord),
93 #[serde(rename = "ns")]
94 Ns(NsRecord),
95 #[serde(rename = "caa")]
96 Caa(CaaRecord),
97 #[serde(rename = "dname")]
98 DName(DNameRecord),
99 #[serde(rename = "ptr")]
100 Ptr(PtrRecord),
101 #[serde(rename = "soa")]
102 Soa(SoaRecord),
103}
104
105impl DnsRecordData {
106 pub fn common(&self) -> &DnsRecordCommon {
107 match self {
108 DnsRecordData::A(x) => &x.common,
109 DnsRecordData::Aaaa(x) => &x.common,
110 DnsRecordData::CName(x) => &x.common,
111 DnsRecordData::Txt(x) => &x.common,
112 DnsRecordData::Mx(x) => &x.common,
113 DnsRecordData::Ns(x) => &x.common,
114 DnsRecordData::Caa(x) => &x.common,
115 DnsRecordData::DName(x) => &x.common,
116 DnsRecordData::Ptr(x) => &x.common,
117 DnsRecordData::Soa(x) => &x.common,
118 }
119 }
120
121 pub fn kind_name(&self) -> DnsRecordKind {
122 match self {
123 DnsRecordData::A(_) => DnsRecordKind::A,
124 DnsRecordData::Aaaa(_) => DnsRecordKind::Aaaa,
125 DnsRecordData::CName(_) => DnsRecordKind::CName,
126 DnsRecordData::Txt(_) => DnsRecordKind::Txt,
127 DnsRecordData::Mx(_) => DnsRecordKind::Mx,
128 DnsRecordData::Ns(_) => DnsRecordKind::Ns,
129 DnsRecordData::Caa(_) => DnsRecordKind::Caa,
130 DnsRecordData::DName(_) => DnsRecordKind::DName,
131 DnsRecordData::Ptr(_) => DnsRecordKind::Ptr,
132 DnsRecordData::Soa(_) => DnsRecordKind::Soa,
133 }
134 }
135}
136
137#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
138pub struct ARecord {
139 #[serde(flatten)]
140 pub common: DnsRecordCommon,
141 #[schemars(with = "String")]
142 pub address: Ipv4Addr,
143}
144
145#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
146pub struct AaaaRecord {
147 #[serde(flatten)]
148 pub common: DnsRecordCommon,
149 pub address: Ipv6Addr,
150}
151
152#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
153pub struct CNameRecord {
154 #[serde(flatten)]
155 pub common: DnsRecordCommon,
156 pub cname: String,
157}
158
159#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
160pub struct TxtRecord {
161 #[serde(flatten)]
162 pub common: DnsRecordCommon,
163 pub data: String,
164}
165
166#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
167pub struct MxRecord {
168 #[serde(flatten)]
169 pub common: DnsRecordCommon,
170 pub mx: String,
171 pub preference: u16,
172}
173
174#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
175pub struct NsRecord {
176 #[serde(flatten)]
177 pub common: DnsRecordCommon,
178 pub nameserver: String,
179}
180
181#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
182pub struct CaaRecord {
183 #[serde(flatten)]
184 pub common: DnsRecordCommon,
185 pub value: String,
186 pub flags: i32,
187 pub tag: String,
188}
189
190#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
191pub struct DNameRecord {
192 #[serde(flatten)]
193 pub common: DnsRecordCommon,
194 pub dname: String,
195}
196
197#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
198pub struct PtrRecord {
199 #[serde(flatten)]
200 pub common: DnsRecordCommon,
201 pub ptr: String,
202}
203
204#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
205pub struct SoaRecord {
206 #[serde(flatten)]
207 pub common: DnsRecordCommon,
208 pub mname: String,
209 pub rname: String,
210 pub serial: i64,
211 pub refresh: i64,
212 pub retry: i64,
213 pub expire: i64,
214 pub minimum: i64,
215}
216
217#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
218pub struct SrvRecord {
219 #[serde(flatten)]
220 pub common: DnsRecordCommon,
221
222 pub service: String,
223 pub protocol: String,
224 pub priority: i32,
225 pub weight: i32,
226 pub port: i32,
227 pub target: String,
228}
229
230#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
231pub struct DnsRecordCommon {
232 pub name: String,
233 pub ttl: Seconds,
234 #[serde(
235 default,
236 with = "time::serde::timestamp::option",
237 skip_serializing_if = "Option::is_none"
238 )]
239 #[schemars(with = "Option<u64>")]
240 pub created_at: Option<OffsetDateTime>,
241 #[serde(
242 default,
243 with = "time::serde::timestamp::option",
244 skip_serializing_if = "Option::is_none"
245 )]
246 #[schemars(with = "Option<u64>")]
247 pub updated_at: Option<OffsetDateTime>,
248 #[serde(
249 default,
250 with = "time::serde::timestamp::option",
251 skip_serializing_if = "Option::is_none"
252 )]
253 #[schemars(with = "Option<u64>")]
254 pub deleted_at: Option<OffsetDateTime>,
255}
256
257#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
258pub struct Seconds(pub u32);