pdns_client/client/servers.rs
1//! impl the server related PDNS API functions
2//! source: <https://doc.powerdns.com/authoritative/http-api/server.html>
3
4use super::error::PdnsAPIError;
5use super::result::Result;
6
7use serde::Deserialize;
8use std::fmt;
9
10// src: https://github.com/zhiburt/tabled#set-column-order
11use tabled::Tabled;
12
13/// The server information returned by pdns API.
14/// Note, crucially, this does not contain any information about the client (and thus the pdns webserver) used to retrieve this information.
15/// As a result, users may want to ensure that servers being compared, are retrieved from the same client/pdns webserver.
16#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Tabled)]
17pub struct Server {
18 /// server id
19 #[tabled(order = 0)]
20 pub id: String,
21
22 /// daemon type
23 #[tabled(order = 1)]
24 pub daemon_type: String,
25
26 /// server version
27 #[tabled(order = 2)]
28 pub version: String,
29
30 #[serde(rename = "type")] // type is a keyword in rust and thus unusable as field name
31 /// server type
32 #[tabled(skip)]
33 pub server_type: String,
34
35 /// server url
36 #[tabled(skip)]
37 pub url: String,
38
39 /// server's config url
40 #[tabled(skip)]
41 pub config_url: String,
42
43 /// server's zone url
44 #[tabled(skip)]
45 pub zones_url: String,
46
47 /// server's automprimaries url
48 #[tabled(skip)]
49 pub autoprimaries: String,
50}
51
52impl fmt::Display for Server {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(
55 f,
56 "pdns server with id={}, type={}, daemon_type={}",
57 self.id, self.server_type, self.daemon_type
58 )
59 }
60}
61
62impl super::Client {
63 /// list the servers
64 ///
65 /// # Errors
66 /// - [`super::Error::Url`] if the api endpoint url could not be formed
67 /// - [`super::Error::Http`] if errors in making request
68 /// - [`super::Error::Http`] if errors in decoding response JSON on a successful request
69 /// - [`super::Error::APIError`] if api returned an error (not 200 OK status)
70 pub fn list_servers(&self) -> Result<Vec<Server>> {
71 let url = self.base_url.join("servers")?;
72
73 let resp = self.client.get(url).send()?;
74 let status = resp.status();
75
76 // status code denotes error
77 if status != http::StatusCode::OK {
78 // here since resp.json it not returned directly, the compiler
79 // cant figure out the type to deserialize it into and thus we must specify it
80 // the return type does, at least, signal to the compiler what type into should convert to
81 return Err(resp.json::<PdnsAPIError>()?.into());
82 }
83
84 Ok(resp.json()?) // fn return type specifies the type to deserialize into
85 }
86
87 /// lists information on a specific server
88 ///
89 /// # Errors
90 /// - [`super::Error::Url`] if the api endpoint url could not be formed
91 /// - [`super::Error::Http`] if errors in making request
92 /// - [`super::Error::Http`] if errors in decoding response JSON on a successful request
93 /// - [`super::Error::APIError`] if api returned an error (not 200 OK status)
94 pub fn list_server(&self, server_id: &str) -> Result<Server> {
95 let url = self.base_url.join(&format!("servers/{server_id}"))?;
96
97 let resp = self.client.get(url).send()?;
98 let status = resp.status();
99
100 // status code denotes error
101 if status != http::StatusCode::OK {
102 // here since resp.json it not returned directly, the compiler
103 // cant figure out the type to deserialize it into and thus we must specify it
104 // the return type does, at least, signal to the compiler what type into should convert to
105 return Err(resp.json::<PdnsAPIError>()?.into());
106 }
107
108 Ok(resp.json()?) // fn return type specifies the type to deserialize into
109 }
110}