diff options
Diffstat (limited to 'src/builder.rs')
-rw-r--r-- | src/builder.rs | 233 |
1 files changed, 231 insertions, 2 deletions
diff --git a/src/builder.rs b/src/builder.rs index 6971be9..982b3ba 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,13 +1,17 @@ //! Interfaces for building various structures -use crate::{errors::Error, Result}; +use crate::{ + errors::Error, + rep::{EndpointSpec, Mode, NetworkAttachmentConfig, RollbackConfig, TaskSpec, UpdateConfig}, + Result, +}; use serde::Serialize; use serde_json::{self, json, map::Map, Value}; use std::{ cmp::Eq, collections::{BTreeMap, HashMap}, hash::Hash, - iter::{IntoIterator, Peekable}, + iter::{IntoIterator, Iterator, Peekable}, time::Duration, }; use url::form_urlencoded; @@ -1771,6 +1775,231 @@ impl ExecResizeOptionsBuilder { } } +//################################################################################ +// Services +//################################################################################ + +/// Options for filtering services list results +#[derive(Default, Debug)] +pub struct ServiceListOptions { + params: HashMap<&'static str, String>, +} + +impl ServiceListOptions { + /// return a new instance of a builder for options + pub fn builder() -> ServiceListOptionsBuilder { + ServiceListOptionsBuilder::default() + } + + /// 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(), + ) + } + } +} + +/// Filter options for services listings +pub enum ServiceFilter { + Id(String), + Label(String), + ReplicatedMode, + GlobalMode, + Name(String), +} + +/// Builder interface for `ServicesListOptions` +#[derive(Default)] +pub struct ServiceListOptionsBuilder { + params: HashMap<&'static str, String>, +} + +impl ServiceListOptionsBuilder { + pub fn filter( + &mut self, + filters: Vec<ServiceFilter>, + ) -> &mut Self { + let mut param = HashMap::new(); + for f in filters { + match f { + ServiceFilter::Id(i) => param.insert("id", vec![i]), + ServiceFilter::Label(l) => param.insert("label", vec![l]), + ServiceFilter::ReplicatedMode => { + param.insert("mode", vec!["replicated".to_string()]) + } + ServiceFilter::GlobalMode => param.insert("mode", vec!["global".to_string()]), + ServiceFilter::Name(n) => param.insert("name", vec![n.to_string()]), + }; + } + // structure is a a json encoded object mapping string keys to a list + // of string values + self.params + .insert("filters", serde_json::to_string(¶m).unwrap()); + self + } + + pub fn enable_status(&mut self) -> &mut Self { + self.params.insert("status", "true".to_owned()); + self + } + + pub fn build(&self) -> ServiceListOptions { + ServiceListOptions { + params: self.params.clone(), + } + } +} + +#[derive(Default, Debug)] +pub struct ServiceOptions { + auth: Option<RegistryAuth>, + params: HashMap<&'static str, Value>, +} + +impl ServiceOptions { + /// return a new instance of a builder for options + pub fn builder() -> ServiceOptionsBuilder { + ServiceOptionsBuilder::default() + } + + /// 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(crate) fn auth_header(&self) -> Option<String> { + self.auth.clone().map(|a| a.serialize()) + } +} + +#[derive(Default)] +pub struct ServiceOptionsBuilder { + auth: Option<RegistryAuth>, + params: HashMap<&'static str, Result<Value>>, +} + +impl ServiceOptionsBuilder { + pub fn name<S>( + &mut self, + name: S, + ) -> &mut Self + where + S: AsRef<str>, + { + self.params.insert("Name", Ok(json!(name.as_ref()))); + self + } + + pub fn labels<I>( + &mut self, + labels: I, + ) -> &mut Self + where + I: IntoIterator<Item = (String, String)>, + { + self.params.insert( + "Labels", + Ok(json!(labels + .into_iter() + .collect::<HashMap<String, String>>())), + ); + self + } + + pub fn task_template( + &mut self, + spec: &TaskSpec, + ) -> &mut Self { + self.params.insert("TaskTemplate", to_json_value(spec)); + self + } + + pub fn mode( + &mut self, + mode: &Mode, + ) -> &mut Self { + self.params.insert("Mode", to_json_value(mode)); + self + } + + pub fn update_config( + &mut self, + conf: &UpdateConfig, + ) -> &mut Self { + self.params.insert("UpdateConfig", to_json_value(conf)); + self + } + + pub fn rollback_config( + &mut self, + conf: &RollbackConfig, + ) -> &mut Self { + self.params.insert("RollbackConfig", to_json_value(conf)); + self + } + + pub fn networks<I>( + &mut self, + networks: I, + ) -> &mut Self + where + I: IntoIterator<Item = NetworkAttachmentConfig>, + { + self.params.insert( + "Networks", + to_json_value( + networks + .into_iter() + .collect::<Vec<NetworkAttachmentConfig>>(), + ), + ); + self + } + + pub fn endpoint_spec( + &mut self, + spec: &EndpointSpec, + ) -> &mut Self { + self.params.insert("EndpointSpec", to_json_value(spec)); + self + } + + pub fn auth( + &mut self, + auth: RegistryAuth, + ) -> &mut Self { + self.auth = Some(auth); + self + } + + pub fn build(&mut self) -> Result<ServiceOptions> { + let params = std::mem::take(&mut self.params); + let mut new_params = HashMap::new(); + for (k, v) in params.into_iter() { + new_params.insert(k, v?); + } + Ok(ServiceOptions { + auth: self.auth.take(), + params: new_params, + }) + } +} + +fn to_json_value<T>(value: T) -> Result<Value> +where + T: Serialize, +{ + Ok(serde_json::to_value(value)?) +} + +//################################################################################ + #[cfg(test)] mod tests { use super::{ContainerOptionsBuilder, LogsOptionsBuilder, RegistryAuth}; |