1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
//! Operation contracts for the Cloud Asset API (v1).
//!
//! Auto-generated from the GCP Discovery Document.
//! **Do not edit manually** — modify the manifest and re-run codegen.
//!
//! These are the raw HTTP operations with correct URLs, methods,
//! and parameter ordering. The hand-written `api/cloudasset.rs` wraps
//! these with ergonomic builders, operation polling, etc.
use crate::types::cloudasset::*;
use crate::{GcpHttpClient, Result};
use urlencoding::encode;
/// Raw HTTP operations for the Cloud Asset API.
///
/// These methods encode the correct URL paths, HTTP methods, and
/// parameter ordering from the GCP Discovery Document.
/// They are `pub(crate)` — use the ergonomic wrappers in
/// [`super::cloudasset::CloudassetClient`] instead.
pub struct CloudassetOps<'a> {
pub(crate) client: &'a GcpHttpClient,
}
impl<'a> CloudassetOps<'a> {
pub(crate) fn new(client: &'a GcpHttpClient) -> Self {
Self { client }
}
fn base_url(&self) -> &str {
#[cfg(any(test, feature = "test-support"))]
{
if let Some(ref base) = self.client.base_url {
return base.trim_end_matches('/');
}
}
"https://cloudasset.googleapis.com"
}
/// Searches all Google Cloud resources within the specified scope, such as a project,
/// folder, or organization. The caller must be granted the
/// `cloudasset.assets.searchAllResources` permission on the desired scope, otherwise the
/// request will be rejected.
///
/// **GCP API**: `GET v1/{+scope}:searchAllResources`
/// **Reference**: <https://cloud.google.com/asset-inventory/docs/v1/searchAllResources>
///
/// # Path Parameters
/// - `scope` — Required. A scope can be a project, a folder, or an organization. The search is limited to the resources within the `sco *(required)*
///
/// # Query Parameters
/// - `assetTypes` — Optional. A list of asset types that this request searches for. If empty, it will search all the asset types [supported
/// - `orderBy` — Optional. A comma-separated list of fields specifying the sorting order of the results. The default order is ascending.
/// - `pageSize` — Optional. The page size for search result pagination. Page size is capped at 500 even if a larger value is given. If set
/// - `pageToken` — Optional. If present, then retrieve the next batch of results from the preceding call to this method. `page_token` must
/// - `query` — Optional. The query statement. See [how to construct a query](https://cloud.google.com/asset-inventory/docs/searching-re
/// - `readMask` — Optional. A comma-separated list of fields that you want returned in the results. The following fields are returned by d
///
/// # Response
/// [`SearchAllResourcesResponse`]
#[allow(clippy::too_many_arguments)]
#[allow(dead_code)]
pub(crate) async fn search_all_resources(
&self,
scope: &str,
query: &str,
asset_types: &[&str],
page_size: &str,
page_token: &str,
order_by: &str,
read_mask: &str,
) -> Result<SearchAllResourcesResponse> {
let url = format!("{}/v1/{}:searchAllResources", self.base_url(), scope,);
let mut __qp: Vec<String> = Vec::new();
if !query.is_empty() {
__qp.push(format!("query={}", encode(query)));
}
for __v in asset_types {
__qp.push(format!("assetTypes={}", encode(__v)));
}
if !page_size.is_empty() {
__qp.push(format!("pageSize={}", encode(page_size)));
}
if !page_token.is_empty() {
__qp.push(format!("pageToken={}", encode(page_token)));
}
if !order_by.is_empty() {
__qp.push(format!("orderBy={}", encode(order_by)));
}
if !read_mask.is_empty() {
__qp.push(format!("readMask={}", encode(read_mask)));
}
let url = if __qp.is_empty() {
url
} else {
format!("{}?{}", url, __qp.join("&"))
};
let response = self.client.get(&url).await?;
serde_json::from_slice(&response).map_err(|e| crate::GcpError::InvalidResponse {
message: format!("Failed to parse search_all_resources response: {e}"),
body: Some(String::from_utf8_lossy(&response).to_string()),
})
}
/// Searches all IAM policies within the specified scope, such as a project, folder, or
/// organization. The caller must be granted the `cloudasset.assets.searchAllIamPolicies`
/// permission on the desired scope, otherwise the request will be rejected.
///
/// **GCP API**: `GET v1/{+scope}:searchAllIamPolicies`
/// **Reference**: <https://cloud.google.com/asset-inventory/docs/v1/searchAllIamPolicies>
///
/// # Path Parameters
/// - `scope` — Required. A scope can be a project, a folder, or an organization. The search is limited to the IAM policies within the ` *(required)*
///
/// # Query Parameters
/// - `assetTypes` — Optional. A list of asset types that the IAM policies are attached to. If empty, it will search the IAM policies that ar
/// - `orderBy` — Optional. A comma-separated list of fields specifying the sorting order of the results. The default order is ascending.
/// - `pageSize` — Optional. The page size for search result pagination. Page size is capped at 500 even if a larger value is given. If set
/// - `pageToken` — Optional. If present, retrieve the next batch of results from the preceding call to this method. `page_token` must be th
/// - `query` — Optional. The query statement. See [how to construct a query](https://cloud.google.com/asset-inventory/docs/searching-ia
///
/// # Response
/// [`SearchAllIamPoliciesResponse`]
#[allow(dead_code)]
pub(crate) async fn search_all_iam_policies(
&self,
scope: &str,
query: &str,
asset_types: &[&str],
page_size: &str,
page_token: &str,
order_by: &str,
) -> Result<SearchAllIamPoliciesResponse> {
let url = format!("{}/v1/{}:searchAllIamPolicies", self.base_url(), scope,);
let mut __qp: Vec<String> = Vec::new();
if !query.is_empty() {
__qp.push(format!("query={}", encode(query)));
}
for __v in asset_types {
__qp.push(format!("assetTypes={}", encode(__v)));
}
if !page_size.is_empty() {
__qp.push(format!("pageSize={}", encode(page_size)));
}
if !page_token.is_empty() {
__qp.push(format!("pageToken={}", encode(page_token)));
}
if !order_by.is_empty() {
__qp.push(format!("orderBy={}", encode(order_by)));
}
let url = if __qp.is_empty() {
url
} else {
format!("{}?{}", url, __qp.join("&"))
};
let response = self.client.get(&url).await?;
serde_json::from_slice(&response).map_err(|e| crate::GcpError::InvalidResponse {
message: format!("Failed to parse search_all_iam_policies response: {e}"),
body: Some(String::from_utf8_lossy(&response).to_string()),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_search_all_resources() {
let mut mock = crate::MockClient::new();
mock.expect_get("/v1/test-scope:searchAllResources?query=test-query&assetTypes=test-assetTypes&pageSize=test-pageSize&pageToken=test-pageToken&orderBy=test-orderBy&readMask=test-readMask")
.returning_json(serde_json::to_value(SearchAllResourcesResponse::fixture()).unwrap());
let client = crate::GcpHttpClient::from_mock(mock);
let ops = CloudassetOps::new(&client);
let result = ops
.search_all_resources(
"test-scope",
"test-query",
&["test-assetTypes"],
"test-pageSize",
"test-pageToken",
"test-orderBy",
"test-readMask",
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_search_all_iam_policies() {
let mut mock = crate::MockClient::new();
mock.expect_get("/v1/test-scope:searchAllIamPolicies?query=test-query&assetTypes=test-assetTypes&pageSize=test-pageSize&pageToken=test-pageToken&orderBy=test-orderBy")
.returning_json(serde_json::to_value(SearchAllIamPoliciesResponse::fixture()).unwrap());
let client = crate::GcpHttpClient::from_mock(mock);
let ops = CloudassetOps::new(&client);
let result = ops
.search_all_iam_policies(
"test-scope",
"test-query",
&["test-assetTypes"],
"test-pageSize",
"test-pageToken",
"test-orderBy",
)
.await;
assert!(result.is_ok());
}
}