digitalocean_api/api/
image.rs

1use super::{ApiLinks, ApiMeta};
2use super::{HasPagination, HasResponse, HasValue};
3use crate::method::{Delete, Get, List, Update};
4use crate::request::ImageRequest;
5use crate::request::Request;
6use crate::{ROOT_URL, STATIC_URL_ERROR};
7use chrono::{DateTime, Utc};
8use getset::{Getters, Setters};
9use serde::Deserialize;
10use serde::Serialize;
11use std::fmt::Display;
12use url::Url;
13
14const IMAGES_SEGMENT: &str = "images";
15
16/// Images in DigitalOcean may refer to one of a few different kinds of objects.
17///
18/// An image may refer to a snapshot that has been taken of a Droplet instance.
19/// It may also mean an image representing an automatic backup of a Droplet.
20/// The third category that it can represent is a public Linux distribution or
21/// application image that is used as a base to create Droplets.
22///
23/// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#domains)
24#[derive(Deserialize, Serialize, Debug, Clone, Getters, Setters)]
25#[get = "pub"]
26pub struct Image {
27    /// A unique number that can be used to identify and reference a specific
28    /// image.
29    id: usize,
30
31    /// The display name that has been given to an image. This is what is shown
32    /// in the control panel and is generally a descriptive title for the image
33    /// in question.
34    name: String,
35
36    /// The kind of image, describing the duration of how long the image is
37    /// stored. This is either "snapshot" or "backup".
38    ///
39    /// *Note:* Since `type` is a keyword in Rust `kind` is used instead.
40    #[serde(rename = "type")]
41    kind: String,
42    // 'type' is reserved in Rust.
43    /// This attribute describes the base distribution used for this image.
44    distribution: String,
45
46    /// A uniquely identifying string that is associated with each of the
47    /// DigitalOcean-provided public images. These can be used to reference
48    /// a public image as an alternative to the numeric id.
49    slug: Option<String>,
50
51    /// This is a boolean value that indicates whether the image in question
52    /// is public or not. An image that is public is available to all accounts.
53    /// A non-public image is only accessible from your account.
54    public: bool,
55
56    /// This attribute is an array of the regions that the image is available
57    /// in. The regions are represented by their identifying slug values.
58    regions: Vec<String>,
59
60    /// The minimum 'disk' required for a size to use this image.
61    min_disk_size: usize,
62
63    /// The size of the image in gigabytes.
64    size_gigabytes: Option<f32>,
65
66    /// A time value given in ISO8601 combined date and time format that
67    /// represents when the Image was created.
68    created_at: DateTime<Utc>,
69}
70
71impl Image {
72    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-images)
73    pub fn list() -> ImageRequest<List, Vec<Image>> {
74        let mut url = ROOT_URL.clone();
75        url.path_segments_mut()
76            .expect(STATIC_URL_ERROR)
77            .push(IMAGES_SEGMENT);
78
79        Request::new(url)
80    }
81
82    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-distribution-images)
83    pub fn distributions() -> ImageRequest<List, Vec<Image>> {
84        let mut url = ROOT_URL.clone();
85        url.path_segments_mut()
86            .expect(STATIC_URL_ERROR)
87            .push(IMAGES_SEGMENT);
88
89        url.query_pairs_mut().append_pair("type", "distribution");
90
91        Request::new(url)
92    }
93
94    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-application-images)
95    pub fn applications() -> ImageRequest<List, Vec<Image>> {
96        let mut url = ROOT_URL.clone();
97        url.path_segments_mut()
98            .expect(STATIC_URL_ERROR)
99            .push(IMAGES_SEGMENT);
100
101        url.query_pairs_mut().append_pair("type", "application");
102
103        Request::new(url)
104    }
105
106    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-a-user-s-images)
107    pub fn user() -> ImageRequest<List, Vec<Image>> {
108        let mut url = ROOT_URL.clone();
109        url.path_segments_mut()
110            .expect(STATIC_URL_ERROR)
111            .push(IMAGES_SEGMENT);
112
113        url.query_pairs_mut().append_pair("private", "true");
114
115        Request::new(url)
116    }
117
118    /// `id` is either an `id` (numeric) or a `slug` (string).
119    ///
120    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-image-by-id)
121    pub fn get<S: Display>(id: S) -> ImageRequest<Get, Image> {
122        let mut url = ROOT_URL.clone();
123        url.path_segments_mut()
124            .expect(STATIC_URL_ERROR)
125            .push(IMAGES_SEGMENT)
126            .push(&format!("{id}"));
127
128        Request::new(url)
129    }
130
131    /// `id` is either an `id` (numeric) or a `slug` (string).
132    ///
133    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#update-an-image)
134    pub fn update<S: Display>(id: S) -> ImageRequest<Update, Image> {
135        let mut url = ROOT_URL.clone();
136        url.path_segments_mut()
137            .expect(STATIC_URL_ERROR)
138            .push(IMAGES_SEGMENT)
139            .push(&format!("{id}"));
140
141        Request::new(url)
142    }
143
144    /// `id` is either an `id` (numeric) or a `slug` (string).
145    ///
146    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#delete-an-image)
147    pub fn delete<S: Display>(id: S) -> ImageRequest<Delete, ()> {
148        let mut url = ROOT_URL.clone();
149        url.path_segments_mut()
150            .expect(STATIC_URL_ERROR)
151            .push(IMAGES_SEGMENT)
152            .push(&format!("{id}"));
153
154        Request::new(url)
155    }
156}
157
158impl ImageRequest<Update, Image> {
159    /// The new name that you would like to use for the image.
160    ///
161    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#images)
162    pub fn name<S: Display + Serialize>(mut self, val: S) -> ImageRequest<Update, Image> {
163        self.body_mut()["name"] = json!(val);
164        self
165    }
166}
167
168/// Response type returned from Digital Ocean.
169#[derive(Deserialize, Serialize, Debug, Clone)]
170pub struct ImageResponse {
171    image: Image,
172}
173
174impl HasResponse for Image {
175    type Response = ImageResponse;
176}
177
178impl HasValue for ImageResponse {
179    type Value = Image;
180
181    fn value(self) -> Image {
182        self.image
183    }
184}
185
186/// Response type returned from Digital Ocean.
187#[derive(Deserialize, Serialize, Debug, Clone)]
188pub struct ImageListResponse {
189    images: Vec<Image>,
190    links: ApiLinks,
191    meta: ApiMeta,
192}
193
194impl HasResponse for Vec<Image> {
195    type Response = ImageListResponse;
196}
197
198impl HasPagination for ImageListResponse {
199    fn next_page(&self) -> Option<Url> {
200        self.links.next()
201    }
202}
203
204impl HasValue for ImageListResponse {
205    type Value = Vec<Image>;
206
207    fn value(self) -> Vec<Image> {
208        self.images
209    }
210}