diff options
-rw-r--r-- | src/builder.rs | 166 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/rep.rs | 8 |
3 files changed, 76 insertions, 99 deletions
diff --git a/src/builder.rs b/src/builder.rs index ba300af..05576f4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -9,7 +9,7 @@ use std::iter::Peekable; // Third party use serde::Serialize; -use serde_json::{self, map::Map, Number, Value}; +use serde_json::{self, map::Map, Value}; use url::form_urlencoded; // Ours @@ -335,8 +335,6 @@ impl ContainerListOptionsBuilder { pub struct ContainerOptions { pub name: Option<String>, params: HashMap<&'static str, Value>, - params_list: HashMap<&'static str, Vec<String>>, - params_hash: HashMap<String, Vec<HashMap<String, String>>>, } /// Function to insert a JSON value into a tree where the desired @@ -385,8 +383,6 @@ impl ContainerOptions { body_members.insert("HostConfig".to_string(), Value::Object(Map::new())); let mut body = Value::Object(body_members); self.parse_from(&self.params, &mut body); - self.parse_from(&self.params_list, &mut body); - self.parse_from(&self.params_hash, &mut body); body } @@ -410,23 +406,14 @@ impl ContainerOptions { pub struct ContainerOptionsBuilder { name: Option<String>, params: HashMap<&'static str, Value>, - params_list: HashMap<&'static str, Vec<String>>, - params_hash: HashMap<String, Vec<HashMap<String, String>>>, } impl ContainerOptionsBuilder { pub(crate) fn new(image: &str) -> Self { let mut params = HashMap::new(); - let params_list = HashMap::new(); - let params_hash = HashMap::new(); params.insert("Image", Value::String(image.to_owned())); - ContainerOptionsBuilder { - name: None, - params, - params_list, - params_hash, - } + ContainerOptionsBuilder { name: None, params } } pub fn name( @@ -441,12 +428,40 @@ impl ContainerOptionsBuilder { &mut self, volumes: Vec<&str>, ) -> &mut Self { - for v in volumes { - self.params_list - .entry("HostConfig.Binds") - .or_insert_with(Vec::new) - .push(v.to_owned()); + self.params.insert("HostConfig.Binds", json!(volumes)); + self + } + + pub fn expose( + &mut self, + srcport: u32, + protocol: &str, + hostport: u32, + ) -> &mut Self { + let mut exposedport: HashMap<String, String> = HashMap::new(); + exposedport.insert("HostPort".to_string(), hostport.to_string()); + + /* The idea here is to go thought the 'old' port binds + * and to apply them to the local 'binding' variable, + * add the bind we want and replace the 'old' value */ + let mut binding: HashMap<String, Value> = HashMap::new(); + for (key, val) in self + .params + .get("HostConfig.PortBindings") + .unwrap_or(&mut json!(null)) + .as_object() + .unwrap_or(&mut Map::new()) + .iter() + { + binding.insert(key.to_string(), json!(val)); } + binding.insert( + format!("{}/{}", srcport, protocol), + json!(vec![exposedport]), + ); + + self.params + .insert("HostConfig.PortBindings", json!(binding)); self } @@ -454,12 +469,7 @@ impl ContainerOptionsBuilder { &mut self, links: Vec<&str>, ) -> &mut Self { - for link in links { - self.params_list - .entry("HostConfig.Links") - .or_insert_with(Vec::new) - .push(link.to_owned()); - } + self.params.insert("HostConfig.Links", json!(links)); self } @@ -467,8 +477,7 @@ impl ContainerOptionsBuilder { &mut self, memory: u64, ) -> &mut Self { - self.params - .insert("HostConfig.Memory", Value::Number(Number::from(memory))); + self.params.insert("HostConfig.Memory", json!(memory)); self } @@ -476,13 +485,7 @@ impl ContainerOptionsBuilder { &mut self, labels: &HashMap<&str, &str>, ) -> &mut Self { - let mut json_labels = Map::new(); - for (k, v) in labels { - json_labels.insert(k.to_string(), Value::String(v.to_string())); - } - - self.params.insert("Labels", Value::Object(json_labels)); - + self.params.insert("Labels", json!(labels)); self } @@ -490,13 +493,7 @@ impl ContainerOptionsBuilder { &mut self, hosts: Vec<&str>, ) -> &mut Self { - for host in hosts { - self.params_list - .entry("HostConfig.ExtraHosts") - .or_insert_with(Vec::new) - .push(host.to_owned()); - } - + self.params.insert("HostConfig.ExtraHosts", json!(hosts)); self } @@ -504,12 +501,7 @@ impl ContainerOptionsBuilder { &mut self, volumes: Vec<&str>, ) -> &mut Self { - for volume in volumes { - self.params_list - .entry("HostConfig.VolumesFrom") - .or_insert_with(Vec::new) - .push(volume.to_owned()); - } + self.params.insert("HostConfig.VolumesFrom", json!(volumes)); self } @@ -517,10 +509,7 @@ impl ContainerOptionsBuilder { &mut self, network: &str, ) -> &mut Self { - if !network.is_empty() { - self.params - .insert("HostConfig.NetworkMode", Value::String(network.to_owned())); - } + self.params.insert("HostConfig.NetworkMode", json!(network)); self } @@ -528,12 +517,7 @@ impl ContainerOptionsBuilder { &mut self, envs: Vec<&str>, ) -> &mut Self { - for env in envs { - self.params_list - .entry("Env") - .or_insert_with(Vec::new) - .push(env.to_owned()); - } + self.params.insert("Env", json!(envs)); self } @@ -541,12 +525,7 @@ impl ContainerOptionsBuilder { &mut self, cmds: Vec<&str>, ) -> &mut Self { - for cmd in cmds { - self.params_list - .entry("Cmd") - .or_insert_with(Vec::new) - .push(cmd.to_owned()); - } + self.params.insert("Cmd", json!(cmds)); self } @@ -554,10 +533,7 @@ impl ContainerOptionsBuilder { &mut self, entrypoint: &str, ) -> &mut Self { - if !entrypoint.is_empty() { - self.params - .insert("Entrypoint", Value::String(entrypoint.to_owned())); - } + self.params.insert("Entrypoint", json!(entrypoint)); self } @@ -565,12 +541,7 @@ impl ContainerOptionsBuilder { &mut self, capabilities: Vec<&str>, ) -> &mut Self { - for c in capabilities { - self.params_list - .entry("HostConfig.CapAdd") - .or_insert_with(Vec::new) - .push(c.to_owned()); - } + self.params.insert("HostConfig.CapAdd", json!(capabilities)); self } @@ -578,12 +549,7 @@ impl ContainerOptionsBuilder { &mut self, devices: Vec<HashMap<String, String>>, ) -> &mut Self { - for d in devices { - self.params_hash - .entry("HostConfig.Devices".to_string()) - .or_insert_with(Vec::new) - .push(d); - } + self.params.insert("HostConfig.Devices", json!(devices)); self } @@ -591,12 +557,8 @@ impl ContainerOptionsBuilder { &mut self, log_driver: &str, ) -> &mut Self { - if !log_driver.is_empty() { - self.params.insert( - "HostConfig.LogConfig.Type", - Value::String(log_driver.to_owned()), - ); - } + self.params + .insert("HostConfig.LogConfig.Type", json!(log_driver)); self } @@ -605,16 +567,12 @@ impl ContainerOptionsBuilder { name: &str, maximum_retry_count: u64, ) -> &mut Self { - if !name.is_empty() { - self.params.insert( - "HostConfig.RestartPolicy.Name", - Value::String(name.to_owned()), - ); - } + self.params + .insert("HostConfig.RestartPolicy.Name", json!(name)); if name == "on-failure" { self.params.insert( "HostConfig.RestartPolicy.MaximumRetryCount", - Value::Number(Number::from(maximum_retry_count)), + json!(maximum_retry_count), ); } self @@ -624,8 +582,6 @@ impl ContainerOptionsBuilder { ContainerOptions { name: self.name.clone(), params: self.params.clone(), - params_list: self.params_list.clone(), - params_hash: self.params_hash.clone(), } } } @@ -1273,6 +1229,26 @@ mod tests { ); } + #[test] + fn container_options_expose() { + let options = ContainerOptionsBuilder::new("test_image") + .expose(80, "tcp", 8080) + .build(); + assert_eq!( + r#"{"HostConfig":{"PortBindings":{"80/tcp":[{"HostPort":"8080"}]}},"Image":"test_image"}"#, + options.serialize().unwrap() + ); + // try exposing two + let options = ContainerOptionsBuilder::new("test_image") + .expose(80, "tcp", 8080) + .expose(81, "tcp", 8081) + .build(); + assert_eq!( + r#"{"HostConfig":{"PortBindings":{"80/tcp":[{"HostPort":"8080"}],"81/tcp":[{"HostPort":"8081"}]}},"Image":"test_image"}"#, + options.serialize().unwrap() + ); + } + /// Test container options that are nested 3 levels deep. #[test] fn container_options_nested() { @@ -29,6 +29,7 @@ extern crate url; #[macro_use] extern crate serde_derive; extern crate serde; +#[macro_use] extern crate serde_json; extern crate tokio; @@ -114,8 +114,8 @@ pub struct NetworkSettings { pub ip_address: String, #[serde(rename = "IPPrefixLen")] pub ip_prefix_len: u64, - pub mac_address: String, /* pub PortMapping: Option<???>, - * pub Ports: Option<???> */ + pub mac_address: String, + pub ports: Option<HashMap<String, Option<Vec<HashMap<String, String>>>>>, pub networks: HashMap<String, NetworkEntry>, } @@ -152,7 +152,7 @@ pub struct HostConfig { pub memory_swap: Option<i64>, pub network_mode: String, pub pid_mode: Option<String>, - // pub PortBindings: ??? + pub port_bindings: Option<HashMap<String, Vec<HashMap<String, String>>>>, pub privileged: bool, pub publish_all_ports: bool, pub readonly_rootfs: Option<bool>, /* pub RestartPolicy: ??? @@ -171,7 +171,7 @@ pub struct Config { pub domainname: String, pub entrypoint: Option<Vec<String>>, pub env: Option<Vec<String>>, - // ExposedPorts + pub exposed_ports: Option<HashMap<String, HashMap<String, String>>>, pub hostname: String, pub image: String, pub labels: Option<HashMap<String, String>>, |