diff --git a/src/docker.rs b/src/docker.rs index 1b7f6038..970f26c3 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -268,6 +268,17 @@ impl Docker { .await } + pub(crate) async fn post_with_headers<'a, H>( + &self, + endpoint: &str, + body: Option<(Body, Mime)>, + headers: Option, + ) -> Result where H: IntoIterator + 'a{ + self.transport + .request(Method::POST, endpoint, body, headers) + .await + } + pub(crate) async fn put( &self, endpoint: &str, diff --git a/src/image.rs b/src/image.rs index 6df8cb71..61c18029 100644 --- a/src/image.rs +++ b/src/image.rs @@ -202,6 +202,20 @@ impl<'docker> Images<'docker> { Box::pin(self.docker.stream_post_into(path.join("?"), None, headers)) } + pub async fn push(&self, image : &str, push_options : &PushOptions) -> Result<()> { + let mut path = vec![format!("/images/{}/push", image)]; + if let Some(query) = push_options.serialize() { + path.push(query) + } + + let headers = push_options + .auth_header() + .map(|a| iter::once(("X-Registry-Auth", a))); + + let _ = self.docker.post_with_headers(&path.join("?"), None, headers).await?; + Ok(()) + } + /// exports a collection of named images, /// either by name, name:tag, or image id, into a tarball /// @@ -768,6 +782,61 @@ impl ImageListOptionsBuilder { } } +#[derive(Default, Debug)] +pub struct PushOptions { + auth: Option, + params: HashMap<&'static str, String>, +} + +impl PushOptions { + + pub fn builder() -> PushOptionsBuilder { + PushOptionsBuilder::default() + } + + fn serialize(&self) -> Option { + if self.params.is_empty() { + None + } else { + Some( + form_urlencoded::Serializer::new(String::new()) + .extend_pairs(&self.params) + .finish(), + ) + } + } + + fn auth_header(&self) -> Option { + self.auth.clone().map(|a| a.serialize()) + } +} + +#[derive(Default)] +pub struct PushOptionsBuilder { + auth: Option, + params: HashMap<&'static str, String>, +} + +impl PushOptionsBuilder { + + pub fn tag(&mut self, t: String) -> &mut Self { + self.params.insert("tag", t); + self + } + + pub fn auth(&mut self, auth: RegistryAuth) -> &mut Self { + self.auth = Some(auth); + self + } + + pub fn build(&mut self) -> PushOptions { + PushOptions { + auth: self.auth.take(), + params: self.params.clone(), + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SearchResult { pub description: String,