azure_lite_rs/api/
subscriptions.rs1use crate::{
9 AzureError, AzureHttpClient, Result,
10 ops::subscriptions::SubscriptionsOps,
11 types::subscriptions::{SubscriptionInfo, SubscriptionListResponse},
12};
13
14pub struct SubscriptionsClient<'a> {
18 ops: SubscriptionsOps<'a>,
19}
20
21impl<'a> SubscriptionsClient<'a> {
22 pub(crate) fn new(client: &'a AzureHttpClient) -> Self {
24 Self {
25 ops: SubscriptionsOps::new(client),
26 }
27 }
28
29 pub async fn list(&self) -> Result<Vec<SubscriptionInfo>> {
37 let mut all = Vec::new();
38 let first_page = self.ops.list_subscriptions().await?;
39 all.extend(first_page.value);
40
41 let mut next_link = first_page.next_link;
42 while let Some(url) = next_link {
43 let page = self.fetch_page(&url).await?;
44 all.extend(page.value);
45 next_link = page.next_link;
46 }
47
48 Ok(all)
49 }
50
51 async fn fetch_page(&self, url: &str) -> Result<SubscriptionListResponse> {
52 let response = self.ops.client.get(url).await?;
53 let response = response.error_for_status().await?;
54 let bytes = response
55 .bytes()
56 .await
57 .map_err(|e| AzureError::InvalidResponse {
58 message: format!("Failed to read subscriptions page: {e}"),
59 body: None,
60 })?;
61 serde_json::from_slice(&bytes).map_err(|e| AzureError::InvalidResponse {
62 message: format!("Failed to parse subscriptions page: {e}"),
63 body: Some(String::from_utf8_lossy(&bytes).to_string()),
64 })
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use crate::MockClient;
72
73 fn make_client(mock: MockClient) -> AzureHttpClient {
74 AzureHttpClient::from_mock(mock)
75 }
76
77 #[tokio::test]
78 async fn list_returns_all_subscriptions_single_page() {
79 let mut mock = MockClient::new();
80 mock.expect_get("/subscriptions")
81 .returning_json(serde_json::json!({
82 "value": [
83 {
84 "subscriptionId": "35010625-993d-403a-a18c-9f32945c327e",
85 "displayName": "Fractal Production",
86 "tenantId": "1dff187b-fb27-4db3-a7b9-286a24aaa818",
87 "state": "Enabled"
88 }
89 ]
90 }));
91 let client = make_client(mock);
92 let subs = client.subscriptions().list().await.expect("list failed");
93 assert_eq!(subs.len(), 1);
94 assert_eq!(
95 subs[0].subscription_id.as_deref(),
96 Some("35010625-993d-403a-a18c-9f32945c327e")
97 );
98 assert_eq!(subs[0].display_name.as_deref(), Some("Fractal Production"));
99 assert_eq!(subs[0].state.as_deref(), Some("Enabled"));
100 }
101
102 #[tokio::test]
103 async fn list_returns_empty_when_no_subscriptions() {
104 let mut mock = MockClient::new();
105 mock.expect_get("/subscriptions")
106 .returning_json(serde_json::json!({ "value": [] }));
107 let client = make_client(mock);
108 let subs = client.subscriptions().list().await.expect("list failed");
109 assert_eq!(subs.len(), 0);
110 }
111}