1use super::Client;
2use super::parse_json_response;
3use super::{Error, OPENAPI_STYLE, OPENAPI_VERSION};
4use bon::Builder;
5use serde::{Deserialize, Serialize};
6use std::borrow::Cow;
7use time::OffsetDateTime;
8use u_sdk_common::helper::into_header_map;
9use u_sdk_common::open_api_sign::{SignParams, get_openapi_request_header};
10
11impl Client {
12 pub fn describe_prefix_list_attributes(&self) -> DescribePrefixListAttributesBuilder<'_> {
13 DescribePrefixListAttributes::builder(self)
14 }
15
16 pub fn modify_prefix_list(&self) -> ModifyPrefixListBuilder<'_> {
17 ModifyPrefixList::builder(self)
18 }
19}
20
21#[derive(Builder, Serialize)]
23#[serde(rename_all = "PascalCase")]
24pub struct DescribePrefixListAttributes<'a> {
25 #[serde(skip_serializing)]
26 #[builder(start_fn)]
27 pub(crate) client: &'a Client,
28 region_id: &'a str,
30 prefix_list_id: &'a str,
32}
33
34#[derive(Debug, Deserialize)]
35#[serde(rename_all = "PascalCase")]
36pub struct DescribePrefixListAttributesResponse {
37 #[serde(with = "time::serde::iso8601")]
38 pub creation_time: OffsetDateTime,
39 pub max_entries: i32,
40 pub request_id: String,
41 pub description: String,
42 pub address_family: AddressFamily,
43 pub prefix_list_name: String,
44 pub prefix_list_id: String,
45 pub entries: Option<EntriesWrapper>,
46}
47
48#[derive(Debug, Deserialize)]
49#[serde(rename_all = "PascalCase")]
50pub struct EntriesWrapper {
51 pub entry: Vec<PrefixListEntry>,
52}
53
54#[derive(Debug, Deserialize)]
55#[serde(rename_all = "PascalCase")]
56pub struct PrefixListEntry {
57 pub description: String,
58 pub cidr: String,
59}
60
61#[derive(Debug, Deserialize)]
62pub enum AddressFamily {
63 IPv4,
64 IPv6,
65}
66
67impl DescribePrefixListAttributes<'_> {
68 pub async fn send(&self) -> Result<DescribePrefixListAttributesResponse, Error> {
69 let client = self.client;
70 let creds = client.credentials_provider.load().await?;
71
72 let sign_params = SignParams {
73 req_method: "GET",
74 host: &client.host,
75 query_map: self,
76 x_acs_action: "DescribePrefixListAttributes",
77 x_acs_version: OPENAPI_VERSION,
78 x_acs_security_token: creds.sts_security_token.as_deref(),
79 request_body: None,
80 style: &OPENAPI_STYLE,
81 };
82
83 let (common_headers, url_) =
84 get_openapi_request_header(&creds.access_key_secret, &creds.access_key_id, sign_params)
85 .map_err(|e| {
86 Error::Common(format!("failed to get openapi request header: {}", e))
87 })?;
88 let header_map = into_header_map(common_headers);
89
90 let resp = client
91 .http_client
92 .get(url_)
93 .headers(header_map)
94 .send()
95 .await?;
96
97 let data = parse_json_response(resp).await?;
98 Ok(data)
99 }
100}
101
102#[serde_with::skip_serializing_none]
104#[derive(Serialize, Builder)]
105#[serde(rename_all = "PascalCase")]
106pub struct ModifyPrefixList<'a> {
107 #[builder(start_fn)]
108 #[serde(skip_serializing)]
109 pub(crate) client: &'a Client,
110
111 #[builder(field)]
112 #[serde(
113 skip_serializing_if = "Vec::is_empty",
114 serialize_with = "serialize_add_entry"
115 )]
116 add_entry: Vec<(Cow<'a, str>, Option<&'a str>)>,
117 #[builder(field)]
118 #[serde(
119 skip_serializing_if = "Vec::is_empty",
120 serialize_with = "serialize_remove_entry"
121 )]
122 remove_entry: Vec<Cow<'a, str>>,
123
124 region_id: &'a str,
125 prefix_list_id: &'a str,
126 prefix_list_name: Option<&'a str>,
127 description: Option<&'a str>,
128}
129
130impl<'a, S: modify_prefix_list_builder::State> ModifyPrefixListBuilder<'a, S> {
131 pub fn add_entry(
132 mut self,
133 cidr: impl Into<Cow<'a, str>>,
134 description: Option<&'a str>,
135 ) -> Self {
136 self.add_entry.push((cidr.into(), description));
137 self
138 }
139
140 pub fn maybe_add_entry(
142 mut self,
143 cidr: Option<impl Into<Cow<'a, str>>>,
144 description: Option<&'a str>,
145 ) -> Self {
146 if let Some(cidr) = cidr {
147 self.add_entry.push((cidr.into(), description));
148 }
149 self
150 }
151
152 pub fn add_entries<I, C>(mut self, items: I) -> Self
153 where
154 I: IntoIterator<Item = (C, Option<&'a str>)>,
155 C: Into<Cow<'a, str>>,
156 {
157 self.add_entry.extend(
158 items
159 .into_iter()
160 .map(|(cidr, description)| (cidr.into(), description)),
161 );
162 self
163 }
164
165 pub fn maybe_add_entries<I, C>(mut self, items: Option<I>) -> Self
166 where
167 I: IntoIterator<Item = (C, Option<&'a str>)>,
168 C: Into<Cow<'a, str>>,
169 {
170 if let Some(items) = items {
171 self.add_entry.extend(
172 items
173 .into_iter()
174 .map(|(cidr, description)| (cidr.into(), description)),
175 );
176 }
177 self
178 }
179
180 pub fn remove_entry(mut self, cidr: impl Into<Cow<'a, str>>) -> Self {
181 self.remove_entry.push(cidr.into());
182 self
183 }
184
185 pub fn maybe_remove_entry(mut self, cidr: Option<impl Into<Cow<'a, str>>>) -> Self {
186 if let Some(cidr) = cidr {
187 self.remove_entry.push(cidr.into());
188 }
189 self
190 }
191
192 pub fn remove_entries<I, C>(mut self, items: I) -> Self
193 where
194 I: IntoIterator<Item = C>,
195 C: Into<Cow<'a, str>>,
196 {
197 self.remove_entry.extend(items.into_iter().map(Into::into));
198 self
199 }
200
201 pub fn maybe_remove_entries<I, C>(mut self, items: Option<I>) -> Self
202 where
203 I: IntoIterator<Item = C>,
204 C: Into<Cow<'a, str>>,
205 {
206 if let Some(items) = items {
207 self.remove_entry.extend(items.into_iter().map(Into::into));
208 }
209 self
210 }
211}
212
213#[serde_with::skip_serializing_none]
214#[derive(Serialize)]
215#[serde(rename_all = "PascalCase")]
216struct AddEntryItem<'a> {
217 cidr: Cow<'a, str>,
218 description: Option<&'a str>,
219}
220
221#[derive(Serialize)]
222#[serde(rename_all = "PascalCase")]
223struct RemoveEntryItem<'a> {
224 cidr: Cow<'a, str>,
225}
226
227fn serialize_add_entry<S>(
228 items: &[(Cow<str>, Option<&str>)],
229 serializer: S,
230) -> Result<S::Ok, S::Error>
231where
232 S: serde::Serializer,
233{
234 let add_entry_items: Vec<AddEntryItem> = items
235 .iter()
236 .map(|(cidr, description)| AddEntryItem {
237 cidr: Cow::Borrowed(cidr.as_ref()),
238 description: *description,
239 })
240 .collect();
241 add_entry_items.serialize(serializer)
242}
243
244fn serialize_remove_entry<S>(items: &[Cow<str>], serializer: S) -> Result<S::Ok, S::Error>
245where
246 S: serde::Serializer,
247{
248 let remove_entry_items: Vec<RemoveEntryItem> = items
249 .iter()
250 .map(|cidr| RemoveEntryItem {
251 cidr: Cow::Borrowed(cidr.as_ref()),
252 })
253 .collect();
254 remove_entry_items.serialize(serializer)
255}
256
257#[derive(Debug, Deserialize)]
258#[serde(rename_all = "PascalCase")]
259pub struct ModifyPrefixListResponse {
260 pub request_id: String,
261}
262
263impl ModifyPrefixList<'_> {
264 pub async fn send(&self) -> Result<ModifyPrefixListResponse, Error> {
265 let client = self.client;
266 let creds = client.credentials_provider.load().await?;
267
268 let sign_params = SignParams {
269 req_method: "POST",
270 host: &client.host,
271 query_map: self,
272 x_acs_action: "ModifyPrefixList",
273 x_acs_version: OPENAPI_VERSION,
274 x_acs_security_token: creds.sts_security_token.as_deref(),
275 request_body: None,
276 style: &OPENAPI_STYLE,
277 };
278
279 let (common_headers, url_) =
280 get_openapi_request_header(&creds.access_key_secret, &creds.access_key_id, sign_params)
281 .map_err(|e| {
282 Error::Common(format!("failed to get openapi request header: {}", e))
283 })?;
284 let header_map = into_header_map(common_headers);
285
286 let resp = client
287 .http_client
288 .post(url_)
289 .headers(header_map)
290 .send()
291 .await?;
292
293 let data = parse_json_response::<ModifyPrefixListResponse>(resp).await?;
294 Ok(data)
295 }
296}