summaryrefslogtreecommitdiffstats
path: root/src/network.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/network.rs')
-rw-r--r--src/network.rs412
1 files changed, 412 insertions, 0 deletions
diff --git a/src/network.rs b/src/network.rs
new file mode 100644
index 0000000..6dd4eb3
--- /dev/null
+++ b/src/network.rs
@@ -0,0 +1,412 @@
+//! Create and manage user-defined networks that containers can be attached to.
+//!
+//! API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>
+
+use std::{
+ collections::{BTreeMap, HashMap},
+ hash::Hash,
+};
+
+use hyper::Body;
+use serde::{Deserialize, Serialize};
+use serde_json::{json, Value};
+use url::form_urlencoded;
+
+use crate::{
+ docker::Docker,
+ errors::{Error, Result},
+};
+
+/// Interface for docker network
+///
+/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>
+pub struct Networks<'docker> {
+ docker: &'docker Docker,
+}
+
+impl<'docker> Networks<'docker> {
+ /// Exports an interface for interacting with docker Networks
+ pub fn new(docker: &'docker Docker) -> Self {
+ Networks { docker }
+ }
+
+ /// List the docker networks on the current docker host
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkList>
+ pub async fn list(
+ &self,
+ opts: &NetworkListOptions,
+ ) -> Result<Vec<NetworkDetails>> {
+ let mut path = vec!["/networks".to_owned()];
+ if let Some(query) = opts.serialize() {
+ path.push(query);
+ }
+ self.docker.get_json(&path.join("?")).await
+ }
+
+ /// Returns a reference to a set of operations available to a specific network instance
+ pub fn get<S>(
+ &self,
+ id: S,
+ ) -> Network<'docker>
+ where
+ S: Into<String>,
+ {
+ Network::new(self.docker, id)
+ }
+
+ /// Create a new Network instance
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkCreate>
+ pub async fn create(
+ &self,
+ opts: &NetworkCreateOptions,
+ ) -> Result<NetworkCreateInfo> {
+ let body: Body = opts.serialize()?.into();
+ let path = vec!["/networks/create".to_owned()];
+
+ self.docker
+ .post_json(&path.join("?"), Some((body, mime::APPLICATION_JSON)))
+ .await
+ }
+}
+
+/// Interface for accessing and manipulating a docker network
+pub struct Network<'docker> {
+ docker: &'docker Docker,
+ id: String,
+}
+
+impl<'docker> Network<'docker> {
+ /// Exports an interface exposing operations against a network instance
+ pub fn new<S>(
+ docker: &'docker Docker,
+ id: S,
+ ) -> Self
+ where
+ S: Into<String>,
+ {
+ Network {
+ docker,
+ id: id.into(),
+ }
+ }
+
+ /// a getter for the Network id
+ pub fn id(&self) -> &str {
+ &self.id
+ }
+
+ /// Inspects the current docker network instance's details
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkInspect>
+ pub async fn inspect(&self) -> Result<NetworkDetails> {
+ self.docker
+ .get_json(&format!("/networks/{}", self.id)[..])
+ .await
+ }
+
+ /// Delete the network instance
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDelete>
+ pub async fn delete(&self) -> Result<()> {
+ self.docker
+ .delete(&format!("/networks/{}", self.id)[..])
+ .await?;
+ Ok(())
+ }
+
+ /// Connect container to network
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkConnect>
+ pub async fn connect(
+ &self,
+ opts: &ContainerConnectionOptions,
+ ) -> Result<()> {
+ self.do_connection("connect", opts).await
+ }
+
+ /// Disconnect container to network
+ ///
+ /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDisconnect>
+ pub async fn disconnect(
+ &self,
+ opts: &ContainerConnectionOptions,
+ ) -> Result<()> {
+ self.do_connection("disconnect", opts).await
+ }
+
+ async fn do_connection(
+ &self,
+ segment: &str,
+ opts: &ContainerConnectionOptions,
+ ) -> Result<()> {
+ let body: Body = opts.serialize()?.into();
+
+ self.docker
+ .post(
+ &format!("/networks/{}/{}", self.id, segment)[..],
+ Some((body, mime::APPLICATION_JSON)),
+ )
+ .await?;
+ Ok(())
+ }
+}
+
+/// Options for filtering networks list results
+#[derive(Default, Debug)]
+pub struct NetworkListOptions {
+ params: HashMap<&'static str, String>,
+}
+
+impl NetworkListOptions {
+ /// serialize options as a string. returns None if no options are defined
+ pub fn serialize(&self) -> Option<String> {
+ if self.params.is_empty() {
+ None
+ } else {
+ Some(
+ form_urlencoded::Serializer::new(String::new())
+ .extend_pairs(&self.params)
+ .finish(),
+ )
+ }
+ }
+}
+
+/// Interface for creating new docker network
+#[derive(Serialize, Debug)]
+pub struct NetworkCreateOptions {
+ params: HashMap<&'static str, Value>,
+}
+
+impl NetworkCreateOptions {
+ /// return a new instance of a builder for options
+ pub fn builder(name: &str) -> NetworkCreateOptionsBuilder {
+ NetworkCreateOptionsBuilder::new(name)
+ }
+
+ /// 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 serde_json::Map<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);
+ }
+ }
+}
+
+#[derive(Default)]
+pub struct NetworkCreateOptionsBuilder {
+ params: HashMap<&'static str, Value>,
+}
+
+impl NetworkCreateOptionsBuilder {
+ pub(crate) fn new(name: &str) -> Self {
+ let mut params = HashMap::new();
+ params.insert("Name", json!(name));
+ NetworkCreateOptionsBuilder { params }
+ }
+
+ pub fn driver(
+ &mut self,
+ name: &str,
+ ) -> &mut Self {
+ if !name.is_empty() {
+ self.params.insert("Driver", json!(name));
+ }
+ self
+ }
+
+ pub fn label(
+ &mut self,
+ labels: HashMap<String, String>,
+ ) -> &mut Self {
+ self.params.insert("Labels", json!(labels));
+ self
+ }
+
+ pub fn build(&self) -> NetworkCreateOptions {
+ NetworkCreateOptions {
+ params: self.params.clone(),
+ }
+ }
+}
+
+/// Interface for connect container to network
+#[derive(Serialize, Debug)]
+pub struct ContainerConnectionOptions {
+ params: HashMap<&'static str, Value>,
+}
+
+impl ContainerConnectionOptions {
+ /// 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(container_id: &str) -> ContainerConnectionOptionsBuilder {
+ ContainerConnectionOptionsBuilder::new(container_id)
+ }
+}
+
+#[derive(Default)]
+pub struct ContainerConnectionOptionsBuilder {
+ params: HashMap<&'static str, Value>,
+}
+
+impl ContainerConnectionOptionsBuilder {
+ pub(crate) fn new(container_id: &str) -> Self {
+ let mut params = HashMap::new();
+ params.insert("Container", json!(container_id));
+ ContainerConnectionOptionsBuilder { params }
+ }
+
+ pub fn aliases(
+ &mut self,
+ aliases: Vec<&str>,
+ ) -> &mut Self {
+ self.params
+ .insert("EndpointConfig", json!({ "Aliases": json!(aliases) }));
+ self
+ }
+
+ pub fn force(&mut self) -> &mut Self {
+ self.params.insert("Force", json!(true));
+ self
+ }
+
+ pub fn build(&self) -> ContainerConnectionOptions {
+ ContainerConnectionOptions {
+ params: self.params.clone(),
+ }
+ }
+}
+
+type PortDescription = HashMap<String, Option<Vec<HashMap<String, String>>>>;
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct NetworkSettings {
+ pub bridge: String,
+ pub gateway: String,
+ #[serde(rename = "IPAddress")]
+ pub ip_address: String,
+ #[serde(rename = "IPPrefixLen")]
+ pub ip_prefix_len: u64,
+ pub mac_address: String,
+ pub ports: Option<PortDescription>,
+ pub networks: HashMap<String, NetworkEntry>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct NetworkEntry {
+ #[serde(rename = "NetworkID")]
+ pub network_id: String,
+ #[serde(rename = "EndpointID")]
+ pub endpoint_id: String,
+ pub gateway: String,
+ #[serde(rename = "IPAddress")]
+ pub ip_address: String,
+ #[serde(rename = "IPPrefixLen")]
+ pub ip_prefix_len: u64,
+ #[serde(rename = "IPv6Gateway")]
+ pub ipv6_gateway: String,
+ #[serde(rename = "GlobalIPv6Address")]
+ pub global_ipv6_address: String,
+ #[serde(rename = "GlobalIPv6PrefixLen")]
+ pub global_ipv6_prefix_len: u64,
+ pub mac_address: String,
+ pub links: Option<Vec<String>>,
+ pub aliases: Option<Vec<String>>,
+ #[serde(rename = "IPAMConfig")]
+ pub ipam_config: Option<EndpointIPAMConfig>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[allow(clippy::upper_case_acronyms)]
+pub struct EndpointIPAMConfig {
+ #[serde(rename = "IPv4Address")]
+ pub ipv4_address: String,
+ #[serde(rename = "IPv6Address")]
+ pub ipv6_address: String,
+ #[serde(rename = "LinkLocalIPs")]
+ pub link_local_ips: Vec<String>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct Ipam {
+ pub driver: String,
+ pub config: Vec<HashMap<String, String>>,
+ pub options: Option<HashMap<String, String>>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct NetworkDetails {
+ pub name: String,
+ pub id: String,
+ pub scope: String,
+ pub driver: String,
+ #[serde(rename = "EnableIPv6")]
+ pub enable_ipv6: bool,
+ #[serde(rename = "IPAM")]
+ pub ipam: Ipam,
+ pub internal: bool,
+ pub attachable: bool,
+ pub containers: HashMap<String, NetworkContainerDetails>,
+ pub options: Option<HashMap<String, String>>,
+ pub labels: Option<HashMap<String, String>>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct NetworkContainerDetails {
+ #[serde(rename = "EndpointID")]
+ pub endpoint_id: String,
+ pub mac_address: String,
+ #[serde(rename = "IPv4Address")]
+ pub ipv4_address: String,
+ #[serde(rename = "IPv6Address")]
+ pub ipv6_address: String,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct NetworkCreateInfo {
+ pub id: String,
+ pub warning: String,
+}