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}