diff options
author | Marc Schreiber <schrieveslaach@online.de> | 2018-12-22 11:30:16 +0100 |
---|---|---|
committer | doug tangren <d.tangren@gmail.com> | 2018-12-22 19:30:16 +0900 |
commit | e27b98daccf405027a0e1d5f72fe1ec6fd8ec8c7 (patch) | |
tree | 0b51f02d7aafdb308f85bff032cb95b7a24007a6 /src | |
parent | 6b5f0c0f9ddfac9c052210c5dbf3224020646127 (diff) |
feat: create, list, and delete volumes (#138)
Diffstat (limited to 'src')
-rw-r--r-- | src/builder.rs | 69 | ||||
-rw-r--r-- | src/lib.rs | 90 | ||||
-rw-r--r-- | src/rep.rs | 25 | ||||
-rw-r--r-- | src/tty.rs | 4 |
4 files changed, 183 insertions, 5 deletions
diff --git a/src/builder.rs b/src/builder.rs index ceabc28..7f6f26d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1238,6 +1238,75 @@ 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() -> VolumeCreateOptionsBuilder { + VolumeCreateOptionsBuilder::new() + } +} + +#[derive(Default)] +pub struct VolumeCreateOptionsBuilder { + params: HashMap<&'static str, Value>, +} + +impl VolumeCreateOptionsBuilder { + pub(crate) fn new() -> Self { + let params = HashMap::new(); + VolumeCreateOptionsBuilder { params } + } + + pub fn name( + &mut self, + name: &str, + ) -> &mut Self { + self.params.insert("Name", json!(name)); + self + } + + pub fn labels( + &mut self, + labels: &HashMap<&str, &str>, + ) -> &mut Self { + self.params.insert("Labels", json!(labels)); + self + } + + 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; @@ -686,6 +687,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`, @@ -795,6 +875,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, +} @@ -93,7 +93,7 @@ impl Decoder for TtyDecoder { 0 => { return Err(Error::InvalidResponse( "Unsupported stream of type stdin".to_string(), - )) + )); } 1 => StreamType::StdOut, 2 => StreamType::StdErr, @@ -101,7 +101,7 @@ impl Decoder for TtyDecoder { return Err(Error::InvalidResponse(format!( "Unsupported stream of type {}", n - ))) + ))); } }; |