digitalocean_api/api/
volume.rs

1use super::region::Region;
2use super::snapshot::Snapshot;
3use super::{ApiLinks, ApiMeta};
4use super::{HasPagination, HasResponse, HasValue};
5use crate::method::{Create, Delete, Get, List};
6use crate::request::Request;
7use crate::request::{SnapshotRequest, VolumeRequest};
8use crate::{ROOT_URL, STATIC_URL_ERROR};
9use chrono::{DateTime, Utc};
10use getset::{Getters, Setters};
11use serde::Deserialize;
12use serde::Serialize;
13use std::fmt::Display;
14use url::Url;
15
16const VOLUME_SEGMENT: &str = "volumes";
17const SNAPSHOTS_SEGMENT: &str = "snapshots";
18
19/// Block Storage volumes provide expanded storage capacity for your Droplets
20/// and can be moved between Droplets within a specific region. Volumes
21/// function as raw block devices, meaning they appear to the operating system
22/// as locally attached storage which can be formatted using any file system
23/// supported by the OS. They may be created in sizes from 1GiB to 16TiB.
24///
25/// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#block-storage)
26#[derive(Deserialize, Serialize, Debug, Clone, Getters, Setters)]
27#[get = "pub"]
28pub struct Volume {
29    /// The unique identifier for the Block Storage volume.
30    id: String,
31
32    /// The region that the Block Storage volume is located in. When setting a
33    /// region, the value should be the slug identifier for the region. When
34    /// you query a Block Storage volume, the entire region object will be
35    /// returned.
36    region: Region,
37
38    /// An array containing the IDs of the Droplets the volume is attached to.
39    /// Note that at this time, a volume can only be attached to a single
40    /// Droplet.
41    droplet_ids: Vec<usize>,
42
43    /// A human-readable name for the Block Storage volume. Must be lowercase
44    /// and be composed only of numbers, letters and "-", up to a limit of 64
45    /// characters.
46    name: String,
47
48    /// An optional free-form text field to describe a Block Storage volume.
49    description: String,
50
51    /// The size of the Block Storage volume in GiB (1024^3).
52    size_gigabytes: f32,
53
54    /// A time value given in ISO8601 combined date and time format that
55    /// represents when the Block Storage volume was created.
56    created_at: DateTime<Utc>,
57}
58
59impl Volume {
60    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-block-storage-volumes)
61    pub fn list() -> VolumeRequest<List, Vec<Volume>> {
62        let mut url = ROOT_URL.clone();
63        url.path_segments_mut()
64            .expect(STATIC_URL_ERROR)
65            .push(VOLUME_SEGMENT);
66
67        Request::new(url)
68    }
69
70    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#create-a-new-block-storage-volume)
71    pub fn create<S>(name: S, size_gigabytes: usize) -> VolumeRequest<Create, Volume>
72    where
73        S: AsRef<str> + Serialize + Display,
74    {
75        let mut url = ROOT_URL.clone();
76        url.path_segments_mut()
77            .expect(STATIC_URL_ERROR)
78            .push(VOLUME_SEGMENT);
79
80        let mut req = Request::new(url);
81        req.set_body(json!({
82            "name": name,
83            "size_gigabytes": size_gigabytes,
84        }));
85        req
86    }
87    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-block-storage-volume)
88    pub fn get<S: AsRef<str> + Serialize + Display>(id: S) -> VolumeRequest<Get, Volume> {
89        let mut url = ROOT_URL.clone();
90        url.path_segments_mut()
91            .expect(STATIC_URL_ERROR)
92            .push(VOLUME_SEGMENT)
93            .push(id.as_ref());
94
95        Request::new(url)
96    }
97    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-block-storage-volume-by-name)
98    pub fn get_by_name<S>(name: S, region: S) -> VolumeRequest<Get, Volume>
99    where
100        S: AsRef<str> + Serialize + Display,
101    {
102        let mut url = ROOT_URL.clone();
103        url.path_segments_mut()
104            .expect(STATIC_URL_ERROR)
105            .push(VOLUME_SEGMENT);
106
107        url.query_pairs_mut()
108            .append_pair("name", name.as_ref())
109            .append_pair("region", region.as_ref());
110
111        Request::new(url)
112    }
113    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#delete-a-block-storage-volume)
114    pub fn delete<S: AsRef<str> + Serialize + Display>(id: S) -> VolumeRequest<Delete, ()> {
115        let mut url = ROOT_URL.clone();
116        url.path_segments_mut()
117            .expect(STATIC_URL_ERROR)
118            .push(VOLUME_SEGMENT)
119            .push(id.as_ref());
120
121        Request::new(url)
122    }
123    /// [Digital Ocean Documentation.](hhttps://developers.digitalocean.com/documentation/v2/#delete-a-block-storage-volume-by-name)
124    pub fn delete_by_name<S>(name: S, region: S) -> VolumeRequest<Delete, ()>
125    where
126        S: AsRef<str> + Serialize + Display,
127    {
128        let mut url = ROOT_URL.clone();
129        url.path_segments_mut()
130            .expect(STATIC_URL_ERROR)
131            .push(VOLUME_SEGMENT);
132
133        url.query_pairs_mut()
134            .append_pair("name", name.as_ref())
135            .append_pair("region", region.as_ref());
136
137        Request::new(url)
138    }
139}
140
141impl VolumeRequest<List, Vec<Volume>> {
142    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-block-storage-volumes)
143    pub fn region<S: AsRef<str> + Serialize + Display>(mut self, region: S) -> Self {
144        self.url_mut()
145            .query_pairs_mut()
146            .append_pair("region", region.as_ref());
147
148        self
149    }
150}
151
152impl VolumeRequest<Get, Volume> {
153    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-snapshots-for-a-volume)
154    pub fn snapshots(mut self) -> SnapshotRequest<List, Vec<Snapshot>> {
155        self.url_mut()
156            .path_segments_mut()
157            .expect(STATIC_URL_ERROR)
158            .push(SNAPSHOTS_SEGMENT);
159
160        self.transmute()
161    }
162
163    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#create-snapshot-from-a-volume)
164    pub fn snapshot<S>(mut self, name: S) -> SnapshotRequest<Create, Snapshot>
165    where
166        S: AsRef<str> + Serialize + Display,
167    {
168        self.url_mut()
169            .path_segments_mut()
170            .expect(STATIC_URL_ERROR)
171            .push(SNAPSHOTS_SEGMENT);
172
173        self.set_body(json!({ "name": name }));
174
175        self.transmute()
176    }
177}
178
179impl VolumeRequest<Create, Volume> {
180    /// An optional free-form text field to describe a Block Storage volume.
181    ///
182    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#block-storage)
183    pub fn description<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
184        self.body_mut()["description"] = json!(val);
185        self
186    }
187
188    /// The region where the Block Storage volume will be created. When setting
189    /// a region, the value should be the slug identifier for the region. When
190    /// you query a Block Storage volume, the entire region object will be
191    /// returned.
192    ///
193    /// **Note:** Should not be specified with a `snapshot_id`.
194    ///
195    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#block-storage)
196    pub fn region<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
197        self.body_mut()["region"] = json!(val);
198        self
199    }
200
201    /// The unique identifier for the volume snapshot from which to create the
202    /// volume.
203    ///
204    /// **Note:** Should not be specified with a `region_id`.
205    ///
206    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#block-storage)
207    pub fn snapshot_id<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
208        self.body_mut()["snapshot_id"] = json!(val);
209        self
210    }
211}
212
213/// Response type returned from Digital Ocean.
214#[derive(Deserialize, Serialize, Debug, Clone)]
215pub struct VolumeListResponse {
216    volumes: Vec<Volume>,
217    links: ApiLinks,
218    meta: ApiMeta,
219}
220
221impl HasResponse for Vec<Volume> {
222    type Response = VolumeListResponse;
223}
224
225impl HasPagination for VolumeListResponse {
226    fn next_page(&self) -> Option<Url> {
227        self.links.next()
228    }
229}
230
231impl HasValue for VolumeListResponse {
232    type Value = Vec<Volume>;
233
234    fn value(self) -> Vec<Volume> {
235        self.volumes
236    }
237}
238
239/// Response type returned from Digital Ocean.
240#[derive(Deserialize, Serialize, Debug, Clone)]
241pub struct VolumeResponse {
242    volume: Volume,
243}
244
245impl HasResponse for Volume {
246    type Response = VolumeResponse;
247}
248
249impl HasValue for VolumeResponse {
250    type Value = Volume;
251
252    fn value(self) -> Volume {
253        self.volume
254    }
255}