use super::region::Region;
use super::snapshot::Snapshot;
use super::{ApiLinks, ApiMeta};
use super::{HasPagination, HasResponse, HasValue};
use crate::method::{Create, Delete, Get, List};
use crate::request::Request;
use crate::request::{SnapshotRequest, VolumeRequest};
use crate::{ROOT_URL, STATIC_URL_ERROR};
use chrono::{DateTime, Utc};
use getset::{Getters, Setters};
use serde::Serialize;
use std::fmt::Display;
use url::Url;
const VOLUME_SEGMENT: &str = "volumes";
const SNAPSHOTS_SEGMENT: &str = "snapshots";
#[derive(Deserialize, Serialize, Debug, Clone, Getters, Setters)]
#[get = "pub"]
pub struct Volume {
id: String,
region: Region,
droplet_ids: Vec<usize>,
name: String,
description: String,
size_gigabytes: f32,
created_at: DateTime<Utc>
}
impl Volume {
pub fn list() -> VolumeRequest<List, Vec<Volume>> {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT);
Request::new(url)
}
pub fn create<S>(name: S, size_gigabytes: usize) -> VolumeRequest<Create, Volume>
where S: AsRef<str> + Serialize + Display {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT);
let mut req = Request::new(url);
req.set_body(json!({
"name": name,
"size_gigabytes": size_gigabytes,
}));
req
}
pub fn get<S: AsRef<str> + Serialize + Display>(id: S) -> VolumeRequest<Get, Volume> {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT)
.push(id.as_ref());
Request::new(url)
}
pub fn get_by_name<S>(name: S, region: S) -> VolumeRequest<Get, Volume>
where S: AsRef<str> + Serialize + Display {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT);
url.query_pairs_mut()
.append_pair("name", name.as_ref())
.append_pair("region", region.as_ref());
Request::new(url)
}
pub fn delete<S: AsRef<str> + Serialize + Display>(id: S) -> VolumeRequest<Delete, ()> {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT)
.push(id.as_ref());
Request::new(url)
}
pub fn delete_by_name<S>(name: S, region: S) -> VolumeRequest<Delete, ()>
where S: AsRef<str> + Serialize + Display {
let mut url = ROOT_URL.clone();
url.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(VOLUME_SEGMENT);
url.query_pairs_mut()
.append_pair("name", name.as_ref())
.append_pair("region", region.as_ref());
Request::new(url)
}
}
impl VolumeRequest<List, Vec<Volume>> {
pub fn region<S: AsRef<str> + Serialize + Display>(mut self, region: S) -> Self {
self.url_mut()
.query_pairs_mut()
.append_pair("region", region.as_ref());
self
}
}
impl VolumeRequest<Get, Volume> {
pub fn snapshots(mut self) -> SnapshotRequest<List, Vec<Snapshot>> {
self.url_mut()
.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(SNAPSHOTS_SEGMENT);
self.transmute()
}
pub fn snapshot<S>(mut self, name: S) -> SnapshotRequest<Create, Snapshot>
where S: AsRef<str> + Serialize + Display {
self.url_mut()
.path_segments_mut()
.expect(STATIC_URL_ERROR)
.push(SNAPSHOTS_SEGMENT);
self.set_body(json!({ "name": name }));
self.transmute()
}
}
impl VolumeRequest<Create, Volume> {
pub fn description<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
self.body_mut()["description"] = json!(val);
self
}
pub fn region<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
self.body_mut()["region"] = json!(val);
self
}
pub fn snapshot_id<S: AsRef<str> + Serialize + Display>(mut self, val: S) -> Self {
self.body_mut()["snapshot_id"] = json!(val);
self
}
}
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct VolumeListResponse {
volumes: Vec<Volume>,
links: ApiLinks,
meta: ApiMeta
}
impl HasResponse for Vec<Volume> {
type Response = VolumeListResponse;
}
impl HasPagination for VolumeListResponse {
fn next_page(&self) -> Option<Url> {
self.links.next()
}
}
impl HasValue for VolumeListResponse {
type Value = Vec<Volume>;
fn value(self) -> Vec<Volume> {
self.volumes
}
}
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct VolumeResponse {
volume: Volume
}
impl HasResponse for Volume {
type Response = VolumeResponse;
}
impl HasValue for VolumeResponse {
type Value = Volume;
fn value(self) -> Volume {
self.volume
}
}