Permalink
Browse files

feat: create, list, and delete volumes

  • Loading branch information...
schrieveslaach committed Dec 14, 2018
1 parent 79d65c2 commit 2b7541fc0467f8372280bfe36b4e51829b58f75c
Showing with 233 additions and 3 deletions.
  1. +23 −0 examples/volumecreate.rs
  2. +23 −0 examples/volumedelete.rs
  3. +21 −0 examples/volumes.rs
  4. +54 −0 src/builder.rs
  5. +87 −3 src/lib.rs
  6. +25 −0 src/rep.rs
@@ -0,0 +1,23 @@
extern crate shiplift;
extern crate tokio;

use shiplift::builder::VolumeCreateOptions;
use shiplift::Docker;
use std::env;
use tokio::prelude::Future;

fn main() {
let docker = Docker::new();
let volumes = docker.volumes();

let volume_name = env::args()
.nth(1)
.expect("You need to specify an volume name");

let fut = volumes
.create(&VolumeCreateOptions::builder(volume_name.as_ref()).build())
.map(|info| println!("{:?}", info))
.map_err(|e| eprintln!("Error: {}", e));

tokio::run(fut);
}
@@ -0,0 +1,23 @@
extern crate shiplift;
extern crate tokio;

use shiplift::Docker;
use std::env;
use tokio::prelude::Future;

fn main() {
let docker = Docker::new();
let volumes = docker.volumes();

let volume_name = env::args()
.nth(1)
.expect("You need to specify an volume name");

let fut = volumes
.get(&volume_name)
.delete()
.map(|info| println!("{:?}", info))
.map_err(|e| eprintln!("Error: {}", e));

tokio::run(fut);
}
@@ -0,0 +1,21 @@
extern crate shiplift;
extern crate tokio;

use shiplift::Docker;
use tokio::prelude::Future;

fn main() {
let docker = Docker::new();
let volumes = docker.volumes();

let fut = volumes
.list()
.map(|volumes| {
for v in volumes {
println!("volume -> {:#?}", v)
}
})
.map_err(|e| eprintln!("Error: {}", e));;

tokio::run(fut);
}
@@ -1213,6 +1213,60 @@ impl ContainerConnectionOptions {
}
}

/// Interface for creating volumes
#[derive(Serialize)]
pub struct VolumeCreateOptions {
params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptions {
/// serialize options as a string. returns None if no options are defined
pub fn serialize(&self) -> Result<String> {
serde_json::to_string(&self.params).map_err(Error::from)
}

pub fn parse_from<'a, K, V>(
&self,
params: &'a HashMap<K, V>,
body: &mut BTreeMap<String, Value>,
) where
&'a HashMap<K, V>: IntoIterator,
K: ToString + Eq + Hash,
V: Serialize,
{
for (k, v) in params.iter() {
let key = k.to_string();
let value = serde_json::to_value(v).unwrap();

body.insert(key, value);
}
}

/// return a new instance of a builder for options
pub fn builder(name: &str) -> VolumeCreateOptionsBuilder {
VolumeCreateOptionsBuilder::new(name)
}
}

#[derive(Default)]
pub struct VolumeCreateOptionsBuilder {
params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptionsBuilder {
pub(crate) fn new(name: &str) -> Self {
let mut params = HashMap::new();
params.insert("Name", json!(name));
VolumeCreateOptionsBuilder { params }
}

pub fn build(&self) -> VolumeCreateOptions {
VolumeCreateOptions {
params: self.params.clone(),
}
}
}

#[cfg(test)]
mod tests {
use super::ContainerOptionsBuilder;
@@ -56,6 +56,7 @@ pub use builder::{
BuildOptions, ContainerConnectionOptions, ContainerFilter, ContainerListOptions,
ContainerOptions, EventsOptions, ExecContainerOptions, ImageFilter, ImageListOptions,
LogsOptions, NetworkCreateOptions, NetworkListOptions, PullOptions, RmContainerOptions,
VolumeCreateOptions,
};
pub use errors::Error;
use futures::{future::Either, Future, IntoFuture, Stream};
@@ -68,12 +69,12 @@ use hyperlocal::UnixConnector;
use mime::Mime;
use openssl::ssl::{SslConnector, SslFiletype, SslMethod};
use read::StreamReader;
use rep::Image as ImageRep;
use rep::{
Change, Container as ContainerRep, ContainerCreateInfo, ContainerDetails, Event, Exit, History,
ImageDetails, Info, SearchResult, Stats, Status, Top, Version,
Image as ImageRep, ImageDetails, Info, NetworkCreateInfo, NetworkDetails as NetworkInfo,
SearchResult, Stats, Status, Top, Version, Volume as VolumeRep, VolumeCreateInfo,
Volumes as VolumesRep,
};
use rep::{NetworkCreateInfo, NetworkDetails as NetworkInfo};
use serde_json::Value;
use std::borrow::Cow;
use std::env;
@@ -671,6 +672,85 @@ impl<'a, 'b> Network<'a, 'b> {
}
}

/// Interface for docker volumes
pub struct Volumes<'a> {
docker: &'a Docker,
}

impl<'a> Volumes<'a> {
/// Exports an interface for interacting with docker volumes
pub fn new(docker: &'a Docker) -> Volumes<'a> {
Volumes { docker }
}

pub fn create(
&self,
opts: &VolumeCreateOptions,
) -> impl Future<Item = VolumeCreateInfo, Error = Error> {
let data = match opts.serialize() {
Ok(data) => data,
Err(e) => return Either::A(futures::future::err(e)),
};

let bytes = data.into_bytes();
let path = vec!["/volumes/create".to_owned()];

Either::B(
self.docker
.post_json(&path.join("?"), Some((bytes, mime::APPLICATION_JSON))),
)
}

/// Lists the docker volumes on the current docker host
pub fn list(&self) -> impl Future<Item = Vec<VolumeRep>, Error = Error> {
let path = vec!["/volumes".to_owned()];

self.docker
.get_json::<VolumesRep>(&path.join("?"))
.map(|volumes: VolumesRep| match volumes.volumes {
Some(volumes) => volumes.clone(),
None => vec![],
})
}

/// Returns a reference to a set of operations available for a named volume
pub fn get<'b>(
&self,
name: &'b str,
) -> Volume<'a, 'b> {
Volume::new(self.docker, name)
}
}

/// Interface for accessing and manipulating a named docker volume
pub struct Volume<'a, 'b> {
docker: &'a Docker,
name: Cow<'b, str>,
}

impl<'a, 'b> Volume<'a, 'b> {
/// Exports an interface for operations that may be performed against a named volume
pub fn new<S>(
docker: &'a Docker,
name: S,
) -> Volume<'a, 'b>
where
S: Into<Cow<'b, str>>,
{
Volume {
docker,
name: name.into(),
}
}

/// Deletes a volume
pub fn delete(&self) -> impl Future<Item = (), Error = Error> {
self.docker
.delete(&format!("/volumes/{}", self.name)[..])
.map(|_| ())
}
}

// https://docs.docker.com/reference/api/docker_remote_api_v1.17/
impl Docker {
/// constructs a new Docker instance for a docker host listening at a url specified by an env var `DOCKER_HOST`,
@@ -780,6 +860,10 @@ impl Docker {
Networks::new(self)
}

pub fn volumes(&self) -> Volumes {
Volumes::new(self)
}

/// Returns version information associated with the docker daemon
pub fn version(&self) -> impl Future<Item = Version, Error = Error> {
self.get_json("/version")
@@ -456,3 +456,28 @@ pub enum Status {
Untagged(String),
Deleted(String),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumeCreateInfo {
pub name: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Volumes {
pub volumes: Option<Vec<Volume>>,
pub warnings: Option<Vec<String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Volume {
pub created_at: String,
pub driver: String,
pub labels: Option<HashMap<String, String>>,
pub name: String,
pub mountpoint: String,
pub options: Option<HashMap<String, String>>,
pub scope: String,
}

0 comments on commit 2b7541f

Please sign in to comment.