rustfs_rsc/client/
operate_bucket.rs

1use hyper::header;
2use hyper::Method;
3
4use super::args::ObjectLockConfig;
5use super::{BucketArgs, ListObjectVersionsArgs, ListObjectsArgs, Tags};
6use crate::datatype::AccessControlPolicy;
7use crate::datatype::CORSConfiguration;
8use crate::datatype::ListAllMyBucketsResult;
9use crate::datatype::ListBucketResult;
10use crate::datatype::ListVersionsResult;
11use crate::datatype::LocationConstraint;
12use crate::datatype::PublicAccessBlockConfiguration;
13use crate::datatype::ServerSideEncryptionConfiguration;
14use crate::datatype::{Bucket, Owner, VersioningConfiguration};
15use crate::error::{Error, Result};
16use crate::Minio;
17
18macro_rules! get_attr {
19    ($name:ident, $query:expr, $T:tt) => {
20        #[doc = concat!("Get [",stringify!($T),"] of a bucket")]
21        /// ## Example
22        /// ```rust
23        /// # use minio_rsc::{Minio, error::Result};
24        /// # async fn example(minio: Minio) -> Result<()> {
25        #[doc = concat!("let config = minio.", stringify!($name), r#"("bucket").await?;"#)]
26        /// # Ok(())}
27        /// ```
28        ///
29        #[inline]
30        pub async fn $name<B>(&self, bucket: B) -> Result<$T>
31        where
32            B: Into<BucketArgs>,
33        {
34            self._bucket_executor(bucket.into(), Method::GET)
35                .query($query, "")
36                .send_xml_ok()
37                .await
38        }
39    };
40}
41
42macro_rules! set_attr {
43    ($name:ident, $query:expr, $T:tt) => {
44        #[doc = concat!("Set [",stringify!($T),"] of a bucket")]
45        #[inline]
46        pub async fn $name<B>(&self, bucket: B, value: $T) -> Result<()>
47        where
48            B: Into<BucketArgs>,
49        {
50            self._bucket_executor(bucket.into(), Method::PUT)
51                .query($query, "")
52                .xml(&value)
53                .send_ok()
54                .await
55                .map(|_| ())
56        }
57    };
58}
59
60macro_rules! del_attr {
61    ($name:ident, $query:expr) => {
62        #[doc = concat!("Delete ",$query," of a bucket")]
63        #[inline]
64        pub async fn $name<B>(&self, bucket: B) -> Result<()>
65        where
66            B: Into<BucketArgs>,
67        {
68            self._bucket_executor(bucket.into(), Method::DELETE)
69                .query($query, "")
70                .send_ok()
71                .await
72                .map(|_| ())
73        }
74    };
75}
76
77/// Operating the bucket
78impl Minio {
79    #[inline]
80    pub(crate) fn _bucket_executor(
81        &self,
82        bucket: BucketArgs,
83        method: Method,
84    ) -> super::BaseExecutor {
85        self.executor(method)
86            .bucket_name(bucket.name)
87            .headers_merge2(bucket.extra_headers)
88            .apply(|e| {
89                let e = if let Some(region) = bucket.region {
90                    e.region(region)
91                } else {
92                    e
93                };
94                if let Some(owner) = bucket.expected_bucket_owner {
95                    e.header("x-amz-expected-bucket-owner", owner)
96                } else {
97                    e
98                }
99            })
100    }
101
102    /// Check if a bucket exists.
103    /// If bucket exists and you have permission to access it, return [Ok(true)], otherwise [Ok(false)]
104    /// ## Example
105    /// ```rust
106    /// use minio_rsc::client::BucketArgs;
107    /// # use minio_rsc::Minio;
108    /// # use minio_rsc::error::Result;
109    /// # async fn example(minio: Minio) -> Result<()>{
110    /// let exists:bool = minio.bucket_exists(BucketArgs::new("bucket")).await?;
111    /// let exists:bool = minio.bucket_exists("bucket").await?;
112    /// # Ok(())
113    /// # }
114    /// ```
115    pub async fn bucket_exists<B>(&self, bucket: B) -> Result<bool>
116    where
117        B: Into<BucketArgs>,
118    {
119        let bucket: BucketArgs = bucket.into();
120        self._bucket_executor(bucket, Method::HEAD)
121            .send()
122            .await
123            .map(|res| res.status().is_success())
124    }
125
126    /// List information of all accessible buckets.
127    /// ## Example
128    /// ```rust
129    /// # use minio_rsc::Minio;
130    /// # async fn example(minio: Minio){
131    /// let (buckets, owner) = minio.list_buckets().await.unwrap();
132    /// # }
133    /// ```
134    pub async fn list_buckets(&self) -> Result<(Vec<Bucket>, Owner)> {
135        let res = self
136            .executor(Method::GET)
137            .send_xml_ok::<ListAllMyBucketsResult>()
138            .await?;
139        Ok((res.buckets.bucket, res.owner))
140    }
141
142    /// Lists metadata about all versions of the objects in a bucket.
143    /// ## Example
144    /// ```rust
145    /// use minio_rsc::client::ListObjectVersionsArgs;
146    /// # use minio_rsc::Minio;
147    /// # async fn example(minio: Minio){
148    /// let mut args = ListObjectVersionsArgs::default();
149    /// args.max_keys = 100;
150    /// minio.list_object_versions("bucket", args).await;
151    /// # }
152    /// ```
153    pub async fn list_object_versions<B>(
154        &self,
155        bucket: B,
156        args: ListObjectVersionsArgs,
157    ) -> Result<ListVersionsResult>
158    where
159        B: Into<BucketArgs>,
160    {
161        let bucket: BucketArgs = bucket.into();
162        self._bucket_executor(bucket, Method::GET)
163            .querys(args.args_query_map())
164            .headers_merge2(args.extra_headers)
165            .send_xml_ok()
166            .await
167    }
168
169    /// Lists object information of a bucket.
170    /// ## Example
171    /// ```rust
172    /// use minio_rsc::client::ListObjectsArgs;
173    /// # use minio_rsc::Minio;
174    /// # async fn example(minio: Minio){
175    /// let args = ListObjectsArgs::default().max_keys(10);
176    /// minio.list_objects("bucket", args).await;
177    /// # }
178    /// ```
179    pub async fn list_objects<B>(
180        &self,
181        bucket: B,
182        args: ListObjectsArgs,
183    ) -> Result<ListBucketResult>
184    where
185        B: Into<BucketArgs>,
186    {
187        let bucket: BucketArgs = bucket.into();
188        self._bucket_executor(bucket, Method::GET)
189            .querys(args.args_query_map())
190            .headers_merge2(args.extra_headers)
191            .send_xml_ok()
192            .await
193    }
194
195    get_attr!(get_bucket_acl, "acl", AccessControlPolicy);
196
197    /// Get the Region the bucket resides in
198    pub async fn get_bucket_region<B>(&self, bucket: B) -> Result<String>
199    where
200        B: Into<BucketArgs>,
201    {
202        let bucket: BucketArgs = bucket.into();
203        self._bucket_executor(bucket, Method::GET)
204            .query("location", "")
205            .send_xml_ok::<LocationConstraint>()
206            .await
207            .map(|loc| loc.location_constraint)
208    }
209
210    /// Create a bucket with object_lock
211    /// ## params
212    /// - object_lock: prevents objects from being deleted.
213    /// Required to support retention and legal hold.
214    /// Can only be enabled at bucket creation.
215    /// ## Example
216    /// ```rust
217    /// use minio_rsc::client::BucketArgs;
218    /// # use minio_rsc::Minio;
219    /// # async fn example(minio: Minio){
220    /// minio.make_bucket(BucketArgs::new("bucket"), true).await;
221    /// minio.make_bucket("bucket", false).await;
222    /// # }
223    /// ```
224    pub async fn make_bucket<B>(&self, bucket: B, object_lock: bool) -> Result<String>
225    where
226        B: Into<BucketArgs>,
227    {
228        let bucket: BucketArgs = bucket.into();
229        let region = &bucket.region.unwrap_or(self.region().to_string());
230        let body = format!("<CreateBucketConfiguration><LocationConstraint>{}</LocationConstraint></CreateBucketConfiguration>",region);
231        self.executor(Method::PUT)
232            .bucket_name(bucket.name)
233            .headers_merge2(bucket.extra_headers)
234            .apply(|e| {
235                if object_lock {
236                    e.header("x-amz-bucket-object-lock-enabled", "true")
237                } else {
238                    e
239                }
240            })
241            .body(body)
242            .send_ok()
243            .await
244            .map(|res| {
245                let location = res.headers().get(header::LOCATION);
246                if let Some(loc) = location {
247                    if let Ok(loc) = loc.to_str() {
248                        return Ok(loc.to_string());
249                    }
250                }
251                Err(res.into())
252            })?
253    }
254
255    /// Remove an **empty** bucket.
256    /// If the operation succeeds, return [Ok] otherwise [Error]
257    /// ## Example
258    /// ```rust
259    /// use minio_rsc::client::BucketArgs;
260    /// # use minio_rsc::Minio;
261    /// # async fn example(minio: Minio){
262    /// minio.remove_bucket(BucketArgs::new("bucket")).await;
263    /// minio.remove_bucket("bucket").await;
264    /// # }
265    /// ```
266    pub async fn remove_bucket<B>(&self, bucket: B) -> Result<()>
267    where
268        B: Into<BucketArgs>,
269    {
270        let bucket: BucketArgs = bucket.into();
271        self._bucket_executor(bucket, Method::DELETE)
272            .send_ok()
273            .await
274            .map(|_| ())
275    }
276
277    get_attr!(get_bucket_cors, "cors", CORSConfiguration);
278    set_attr!(set_bucket_cors, "cors", CORSConfiguration);
279    del_attr!(del_bucket_cors, "cors");
280
281    #[rustfmt::skip]
282    get_attr!(get_bucket_encryption,"encryption",ServerSideEncryptionConfiguration);
283    #[rustfmt::skip]
284    set_attr!(set_bucket_encryption, "encryption", ServerSideEncryptionConfiguration);
285    del_attr!(del_bucket_encryption, "encryption");
286
287    #[rustfmt::skip]
288    get_attr!(get_public_access_block, "publicAccessBlock", PublicAccessBlockConfiguration);
289    #[rustfmt::skip]
290    set_attr!(set_public_access_block, "publicAccessBlock", PublicAccessBlockConfiguration);
291    del_attr!(del_public_access_block, "publicAccessBlock");
292
293    /// Get [Option]<[Tags]> of a bucket.
294    /// Note: return [None] if bucket had not set tagging or delete tagging.
295    /// ## Example
296    /// ```rust
297    /// use minio_rsc::client::BucketArgs;
298    /// use minio_rsc::client::Tags;
299    /// # use minio_rsc::{Minio, error::Result};
300    /// # async fn example(minio: Minio) -> Result<()> {
301    /// let tags:Option<Tags> = minio.get_bucket_tags(BucketArgs::new("bucket")).await?;
302    /// let tags:Option<Tags> = minio.get_bucket_tags("bucket").await?;
303    /// # Ok(())}
304    /// ```
305    pub async fn get_bucket_tags<B>(&self, bucket: B) -> Result<Option<Tags>>
306    where
307        B: Into<BucketArgs>,
308    {
309        let bucket: BucketArgs = bucket.into();
310        let res = self
311            ._bucket_executor(bucket, Method::GET)
312            .query("tagging", "")
313            .send_xml_ok::<Tags>()
314            .await;
315        match res {
316            Ok(tags) => Ok(Some(tags)),
317            Err(Error::S3Error(s)) if s.code == "NoSuchTagSet" => Ok(None),
318            Err(err) => Err(err),
319        }
320    }
321
322    set_attr!(set_bucket_tags, "tagging", Tags);
323    del_attr!(del_bucket_tags, "tagging");
324
325    get_attr!(get_bucket_versioning, "versioning", VersioningConfiguration);
326    set_attr!(set_bucket_versioning, "versioning", VersioningConfiguration);
327
328    get_attr!(get_object_lock_config, "object-lock", ObjectLockConfig);
329    set_attr!(set_object_lock_config, "object-lock", ObjectLockConfig);
330
331    /// Delete [ObjectLockConfig] of a bucket.
332    /// ## Example
333    /// ```rust
334    /// use minio_rsc::client::BucketArgs;
335    /// # use minio_rsc::{Minio, error::Result};
336    /// # async fn example(minio: Minio) -> Result<()> {
337    /// minio.del_object_lock_config("bucket").await?;
338    /// # Ok(())}
339    /// ```
340    pub async fn del_object_lock_config<B>(&self, bucket: B) -> Result<()>
341    where
342        B: Into<BucketArgs>,
343    {
344        let config = ObjectLockConfig::default();
345        self.set_object_lock_config(bucket, config).await
346    }
347}