From cb80052e8e3a65e01063ccc17f7350aab032bc09 Mon Sep 17 00:00:00 2001 From: Jonas Pommerening Date: Thu, 1 Apr 2021 12:04:26 +0200 Subject: Allow multiple filters of same type and fix ExitCode filter name --- src/container.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/container.rs b/src/container.rs index 24c41d6..2b3ee84 100644 --- a/src/container.rs +++ b/src/container.rs @@ -504,14 +504,19 @@ impl ContainerListOptionsBuilder { &mut self, filters: Vec, ) -> &mut Self { - let mut param = HashMap::new(); + let mut param: HashMap<&str, Vec> = HashMap::new(); for f in filters { - match f { - ContainerFilter::ExitCode(c) => param.insert("exit", vec![c.to_string()]), - ContainerFilter::Status(s) => param.insert("status", vec![s]), - ContainerFilter::LabelName(n) => param.insert("label", vec![n]), - ContainerFilter::Label(n, v) => param.insert("label", vec![format!("{}={}", n, v)]), + let (key, value) = match f { + ContainerFilter::ExitCode(c) => ("exited", c.to_string()), + ContainerFilter::Status(s) => ("status", s), + ContainerFilter::LabelName(n) => ("label", n), + ContainerFilter::Label(n, v) => ("label", format!("{}={}", n, v)), }; + if let Some(values) = param.get_mut(key) { + values.push(value); + } else { + param.insert(key, vec![value]); + } } // structure is a a json encoded object mapping string keys to a list // of string values @@ -1409,6 +1414,7 @@ pub struct Exit { #[cfg(test)] mod tests { use super::*; + use crate::container::ContainerFilter::{ExitCode, Label, LabelName, Status}; #[test] fn container_options_simple() { @@ -1562,6 +1568,69 @@ mod tests { ); } + #[test] + fn container_list_options_multiple_labels() { + let options = ContainerListOptions::builder() + .filter(vec![ + Label("label1".to_string(), "value".to_string()), + LabelName("label2".to_string()), + ]) + .build(); + + let form = form_urlencoded::Serializer::new(String::new()) + .append_pair("filters", r#"{"label":["label1=value","label2"]}"#) + .finish(); + + assert_eq!(form, options.serialize().unwrap()) + } + + #[test] + fn container_list_options_exit_code() { + let options = ContainerListOptions::builder() + .filter(vec![ExitCode(0)]) + .build(); + + let form = form_urlencoded::Serializer::new(String::new()) + .append_pair("filters", r#"{"exited":["0"]}"#) + .finish(); + + assert_eq!(form, options.serialize().unwrap()) + } + + #[test] + fn container_list_options_status() { + let options = ContainerListOptions::builder() + .filter(vec![Status("running".to_string())]) + .build(); + + let form = form_urlencoded::Serializer::new(String::new()) + .append_pair("filters", r#"{"status":["running"]}"#) + .finish(); + + assert_eq!(form, options.serialize().unwrap()) + } + + #[test] + fn container_list_options_combined() { + let options = ContainerListOptions::builder() + .all() + .filter(vec![ + Label("label1".to_string(), "value".to_string()), + LabelName("label2".to_string()), + ExitCode(0), + Status("running".to_string()), + ]) + .build(); + + let serialized = options.serialize().unwrap(); + + assert!(serialized.contains("all=true")); + assert!(serialized.contains("filters=")); + assert!(serialized.contains("%22label%22%3A%5B%22label1%3Dvalue%22%2C%22label2%22%5D")); + assert!(serialized.contains("%22status%22%3A%5B%22running%22%5D")); + assert!(serialized.contains("%22exited%22%3A%5B%220%22%5D")); + } + #[cfg(feature = "chrono")] #[test] fn logs_options() { -- cgit v1.2.3