gcloud_spanner/admin/instance/
instance_admin_client.rs

1use google_cloud_gax::conn::Channel;
2use google_cloud_gax::create_request;
3use google_cloud_gax::grpc::{Response, Status};
4use google_cloud_gax::retry::{invoke, MapErr, RetrySetting};
5use google_cloud_googleapis::iam::v1::{
6    GetIamPolicyRequest, Policy, SetIamPolicyRequest, TestIamPermissionsRequest, TestIamPermissionsResponse,
7};
8use google_cloud_googleapis::spanner::admin::instance::v1::instance_admin_client::InstanceAdminClient as InternalInstanceAdminClient;
9use google_cloud_googleapis::spanner::admin::instance::v1::{
10    CreateInstanceRequest, DeleteInstanceRequest, GetInstanceConfigRequest, GetInstanceRequest, Instance,
11    InstanceConfig, ListInstanceConfigsRequest, ListInstancesRequest, UpdateInstanceRequest,
12};
13use google_cloud_longrunning::autogen::operations_client::OperationsClient;
14use google_cloud_longrunning::longrunning::Operation;
15
16use crate::admin::default_retry_setting;
17
18#[derive(Clone)]
19pub struct InstanceAdminClient {
20    inner: InternalInstanceAdminClient<Channel>,
21    lro_client: OperationsClient,
22}
23
24impl InstanceAdminClient {
25    pub fn new(channel: Channel, lro_client: OperationsClient) -> Self {
26        Self {
27            inner: InternalInstanceAdminClient::new(channel).max_decoding_message_size(i32::MAX as usize),
28            lro_client,
29        }
30    }
31
32    /// list_instance_configs lists the supported instance configurations for a given project.
33    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
34    pub async fn list_instance_configs(
35        &self,
36        mut req: ListInstanceConfigsRequest,
37        retry: Option<RetrySetting>,
38    ) -> Result<Vec<InstanceConfig>, Status> {
39        let retry = Some(retry.unwrap_or_else(default_retry_setting));
40        let parent = &req.parent;
41        let mut all = vec![];
42        //eager loading
43        loop {
44            let action = || async {
45                let request = create_request(format!("parent={parent}"), req.clone());
46                self.inner
47                    .clone()
48                    .list_instance_configs(request)
49                    .await
50                    .map(|d| d.into_inner())
51                    .map_transient_err()
52            };
53            let response = invoke(retry.clone(), action).await?;
54            all.extend(response.instance_configs.into_iter());
55            if response.next_page_token.is_empty() {
56                return Ok(all);
57            }
58            req.page_token = response.next_page_token;
59        }
60    }
61
62    /// get_instance_config gets information about a particular instance configuration.
63    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
64    pub async fn get_instance_config(
65        &self,
66        req: GetInstanceConfigRequest,
67        retry: Option<RetrySetting>,
68    ) -> Result<InstanceConfig, Status> {
69        let retry = Some(retry.unwrap_or_else(default_retry_setting));
70        let name = &req.name;
71        let action = || async {
72            let request = create_request(format!("name={name}"), req.clone());
73            self.inner
74                .clone()
75                .get_instance_config(request)
76                .await
77                .map(|d| d.into_inner())
78                .map_transient_err()
79        };
80        invoke(retry, action).await
81    }
82
83    /// list_instances lists all instances in the given project.
84    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
85    pub async fn list_instances(
86        &self,
87        mut req: ListInstancesRequest,
88        retry: Option<RetrySetting>,
89    ) -> Result<Vec<Instance>, Status> {
90        let retry = Some(retry.unwrap_or_else(default_retry_setting));
91        let parent = &req.parent;
92        let mut all = vec![];
93        //eager loading
94        loop {
95            let action = || async {
96                let request = create_request(format!("parent={parent}"), req.clone());
97                self.inner
98                    .clone()
99                    .list_instances(request)
100                    .await
101                    .map(|d| d.into_inner())
102                    .map_transient_err()
103            };
104            let response = invoke(retry.clone(), action).await?;
105            all.extend(response.instances.into_iter());
106            if response.next_page_token.is_empty() {
107                return Ok(all);
108            }
109            req.page_token = response.next_page_token;
110        }
111    }
112
113    /// gets information about a particular instance.
114    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
115    pub async fn get_instance(
116        &self,
117        req: GetInstanceRequest,
118        retry: Option<RetrySetting>,
119    ) -> Result<Response<Instance>, Status> {
120        let retry = Some(retry.unwrap_or_else(default_retry_setting));
121        let name = &req.name;
122        let action = || async {
123            let request = create_request(format!("name={name}"), req.clone());
124            self.inner.clone().get_instance(request).await.map_transient_err()
125        };
126        invoke(retry, action).await
127    }
128
129    /// create_instance creates an instance and begins preparing it to begin serving. The
130    /// returned [long-running operation][google.longrunning.Operation]
131    /// can be used to track the progress of preparing the new
132    /// instance. The instance name is assigned by the caller. If the
133    /// named instance already exists, CreateInstance returns
134    /// ALREADY_EXISTS.
135    ///
136    /// Immediately upon completion of this request:
137    ///
138    ///   The instance is readable via the API, with all requested attributes
139    ///   but no allocated resources. Its state is CREATING.
140    ///
141    /// Until completion of the returned operation:
142    ///
143    ///   Cancelling the operation renders the instance immediately unreadable
144    ///   via the API.
145    ///
146    ///   The instance can be deleted.
147    ///
148    ///   All other attempts to modify the instance are rejected.
149    ///
150    /// Upon completion of the returned operation:
151    ///
152    ///   Billing for all successfully-allocated resources begins (some types
153    ///   may have lower than the requested levels).
154    ///
155    ///   Databases can be created in the instance.
156    ///
157    ///   The instance’s allocated resource levels are readable via the API.
158    ///
159    ///   The instance’s state becomes READY.
160    ///
161    /// The returned [long-running operation][google.longrunning.Operation] will
162    /// have a name of the format <instance_name>/operations/<operation_id> and
163    /// can be used to track creation of the instance.  The
164    /// metadata field type is
165    /// CreateInstanceMetadata.
166    /// The response field type is
167    /// Instance, if successful.
168    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
169    pub async fn create_instance(
170        &self,
171        req: CreateInstanceRequest,
172        retry: Option<RetrySetting>,
173    ) -> Result<Operation<Instance>, Status> {
174        let retry = Some(retry.unwrap_or_else(default_retry_setting));
175        let parent = &req.parent;
176        let action = || async {
177            let request = create_request(format!("parent={parent}"), req.clone());
178            self.inner.clone().create_instance(request).await.map_transient_err()
179        };
180        invoke(retry, action)
181            .await
182            .map(|d| Operation::new(self.lro_client.clone(), d.into_inner()))
183    }
184
185    /// update_instance updates an instance, and begins allocating or releasing resources
186    /// as requested. The returned [long-running
187    /// operation][google.longrunning.Operation] can be used to track the
188    /// progress of updating the instance. If the named instance does not
189    /// exist, returns NOT_FOUND.
190    ///
191    /// Immediately upon completion of this request:
192    ///
193    ///   For resource types for which a decrease in the instance’s allocation
194    ///   has been requested, billing is based on the newly-requested level.
195    ///
196    /// Until completion of the returned operation:
197    ///
198    ///   Cancelling the operation sets its metadata’s
199    ///   cancel_time, and begins
200    ///   restoring resources to their pre-request values. The operation
201    ///   is guaranteed to succeed at undoing all resource changes,
202    ///   after which point it terminates with a CANCELLED status.
203    ///
204    ///   All other attempts to modify the instance are rejected.
205    ///
206    ///   Reading the instance via the API continues to give the pre-request
207    ///   resource levels.
208    ///
209    /// Upon completion of the returned operation:
210    ///
211    ///   Billing begins for all successfully-allocated resources (some types
212    ///   may have lower than the requested levels).
213    ///
214    ///   All newly-reserved resources are available for serving the instance’s
215    ///   tables.
216    ///
217    ///   The instance’s new resource levels are readable via the API.
218    ///
219    /// The returned [long-running operation][google.longrunning.Operation] will
220    /// have a name of the format <instance_name>/operations/<operation_id> and
221    /// can be used to track the instance modification.  The
222    /// metadata field type is
223    /// UpdateInstanceMetadata.
224    /// The response field type is
225    /// Instance, if successful.
226    ///
227    /// Authorization requires spanner.instances.update permission on
228    /// resource [name][google.spanner.admin.instance.v1.Instance.name (at http://google.spanner.admin.instance.v1.Instance.name)].
229    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
230    pub async fn update_instance(
231        &self,
232        req: UpdateInstanceRequest,
233        retry: Option<RetrySetting>,
234    ) -> Result<Operation<Instance>, Status> {
235        let retry = Some(retry.unwrap_or_else(default_retry_setting));
236        let instance_name = &req.instance.as_ref().unwrap().name;
237        let action = || async {
238            let request = create_request(format!("instance.name={instance_name}"), req.clone());
239            self.inner.clone().update_instance(request).await.map_transient_err()
240        };
241        invoke(retry, action)
242            .await
243            .map(|d| Operation::new(self.lro_client.clone(), d.into_inner()))
244    }
245
246    /// DeleteInstance deletes an instance.
247    ///
248    /// Immediately upon completion of the request:
249    ///
250    ///   Billing ceases for all of the instance’s reserved resources.
251    ///
252    /// Soon afterward:
253    ///
254    ///   The instance and all of its databases immediately and
255    ///   irrevocably disappear from the API. All data in the databases
256    ///   is permanently deleted.
257    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
258    pub async fn delete_instance(
259        &self,
260        req: DeleteInstanceRequest,
261        retry: Option<RetrySetting>,
262    ) -> Result<Response<()>, Status> {
263        let retry = Some(retry.unwrap_or_else(default_retry_setting));
264        let name = &req.name;
265        let action = || async {
266            let request = create_request(format!("name={name}"), req.clone());
267            self.inner.clone().delete_instance(request).await.map_transient_err()
268        };
269        invoke(retry, action).await
270    }
271
272    /// set_iam_policy sets the access control policy on an instance resource. Replaces any
273    /// existing policy.
274    ///
275    /// Authorization requires spanner.instances.setIamPolicy on resource.
276    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
277    pub async fn set_iam_policy(
278        &self,
279        req: SetIamPolicyRequest,
280        retry: Option<RetrySetting>,
281    ) -> Result<Response<Policy>, Status> {
282        let resource = &req.resource;
283        let retry = Some(retry.unwrap_or_else(default_retry_setting));
284        let action = || async {
285            let request = create_request(format!("resource={resource}"), req.clone());
286            self.inner.clone().set_iam_policy(request).await.map_transient_err()
287        };
288        invoke(retry, action).await
289    }
290
291    /// get_iam_policy sets the access control policy on an instance resource. Replaces any
292    /// existing policy.
293    ///
294    /// Authorization requires spanner.instances.setIamPolicy on resource.
295    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
296    pub async fn get_iam_policy(
297        &self,
298        req: GetIamPolicyRequest,
299        retry: Option<RetrySetting>,
300    ) -> Result<Response<Policy>, Status> {
301        let resource = &req.resource;
302        let retry = Some(retry.unwrap_or_else(default_retry_setting));
303        let action = || async {
304            let request = create_request(format!("resource={resource}"), req.clone());
305            self.inner.clone().get_iam_policy(request).await.map_transient_err()
306        };
307        invoke(retry, action).await
308    }
309
310    /// test_iam_permissions returns permissions that the caller has on the specified instance resource.
311    ///
312    /// Attempting this RPC on a non-existent Cloud Spanner instance resource will
313    /// result in a NOT_FOUND error if the user has spanner.instances.list
314    /// permission on the containing Google Cloud Project. Otherwise returns an
315    /// empty set of permissions.
316    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
317    pub async fn test_iam_permissions(
318        &self,
319        req: TestIamPermissionsRequest,
320        retry: Option<RetrySetting>,
321    ) -> Result<Response<TestIamPermissionsResponse>, Status> {
322        let resource = &req.resource;
323        let retry = Some(retry.unwrap_or_else(default_retry_setting));
324        let action = || async {
325            let request = create_request(format!("resource={resource}"), req.clone());
326            self.inner
327                .clone()
328                .test_iam_permissions(request)
329                .await
330                .map_transient_err()
331        };
332        invoke(retry, action).await
333    }
334}