Skip to main content

u_sdk/ecs/
prefix_list.rs

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/// [DescribePrefixListAttributes](https://help.aliyun.com/zh/ecs/developer-reference/api-ecs-2014-05-26-describeprefixlistattributes)
22#[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    /// 地域 ID。您可以调用 DescribeRegions 查看最新的阿里云地域列表。
29    region_id: &'a str,
30    /// 前缀列表 ID
31    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/// [ModifyPrefixList](https://help.aliyun.com/zh/ecs/developer-reference/api-ecs-2014-05-26-modifyprefixlist)
103#[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    /// 如果cidr为None,则不添加该条目,此时description参数会被忽略
141    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}