summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Schreiber <schrieveslaach@online.de>2018-12-22 11:30:16 +0100
committerdoug tangren <d.tangren@gmail.com>2018-12-22 19:30:16 +0900
commite27b98daccf405027a0e1d5f72fe1ec6fd8ec8c7 (patch)
tree0b51f02d7aafdb308f85bff032cb95b7a24007a6 /src
parent6b5f0c0f9ddfac9c052210c5dbf3224020646127 (diff)
feat: create, list, and delete volumes (#138)
Diffstat (limited to 'src')
-rw-r--r--src/builder.rs69
-rw-r--r--src/lib.rs90
-rw-r--r--src/rep.rs25
-rw-r--r--src/tty.rs4
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;
diff --git a/src/lib.rs b/src/lib.rs
index 2c7c0da..595157b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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")
diff --git a/src/rep.rs b/src/rep.rs
index 5327db5..5317d83 100644
--- a/src/rep.rs
+++ b/src/rep.rs
@@ -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,
+}
diff --git a/src/tty.rs b/src/tty.rs
index a1c1865..a0c5146 100644
--- a/src/tty.rs
+++ b/src/tty.rs
@@ -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
- )))
+ )));
}
};