From 90ac2af9576d0b7ffad41f18d15957edf5529158 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:48:10 +0100 Subject: [PATCH 01/11] Add ReadonlyRootfs flag for containers and ability to resize TTY --- src/api/container.rs | 14 ++++++++++++++ src/opts/container.rs | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/api/container.rs b/src/api/container.rs index 04b3e71..3085a93 100644 --- a/src/api/container.rs +++ b/src/api/container.rs @@ -171,6 +171,20 @@ impl Container { .map(|_| ()) }} + api_doc! { Container => Resize + | + /// Resize the TTY for a container + pub async fn resize(&self, width: u16, height: u16) -> Result<()> { + self.docker + .post_string( + &format!("/containers/{}/resize?w={width}&h={height}", self.id), + Payload::empty(), + Headers::none() + ) + .await + .map(|_| ()) + }} + api_doc! { Container => Pause | /// Pause the container instance. diff --git a/src/opts/container.rs b/src/opts/container.rs index 0ef099c..c17f460 100644 --- a/src/opts/container.rs +++ b/src/opts/container.rs @@ -524,6 +524,11 @@ impl ContainerCreateOptsBuilder { security_options => "HostConfig.SecurityOpt" ); + impl_field!( + /// Mount the container's root filesystem as read only. + readonly_rootfs: bool => "HostConfig.ReadonlyRootfs" + ); + impl_vec_field!( /// Specify any bind mounts, taking the form of `/some/host/path:/some/container/path` volumes => "HostConfig.Binds" From 50e18370f2c57a26137960ec3bba386d47f19b37 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 18:44:23 +0100 Subject: [PATCH 02/11] Fix failing test and add test for ReadonlyRootfs --- src/opts/container.rs | 9 ++++++++- tests/container_tests.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/opts/container.rs b/src/opts/container.rs index c17f460..cdf6e1b 100644 --- a/src/opts/container.rs +++ b/src/opts/container.rs @@ -527,7 +527,7 @@ impl ContainerCreateOptsBuilder { impl_field!( /// Mount the container's root filesystem as read only. readonly_rootfs: bool => "HostConfig.ReadonlyRootfs" - ); + ); impl_vec_field!( /// Specify any bind mounts, taking the form of `/some/host/path:/some/container/path` @@ -864,6 +864,13 @@ mod tests { r#"{"HostConfig":{"AutoRemove":true,"NetworkMode":"host","Privileged":true},"Image":"test_image"}"# ); + test_case!( + ContainerCreateOptsBuilder::default() + .image("test_image") + .readonly_rootfs(true), + r#"{"HostConfig":{"ReadonlyRootfs":true},"Image":"test_image"}"# + ); + test_case!( ContainerCreateOptsBuilder::default() .image("test_image") diff --git a/tests/container_tests.rs b/tests/container_tests.rs index b8ee2ce..13d2828 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -508,7 +508,7 @@ async fn container_top() { let top_result = container.top(None).await; assert!(top_result.is_ok()); - assert!(top_result.unwrap().processes.unwrap_or_default()[0].contains(&DEFAULT_CMD.to_string())); + assert!(top_result.unwrap().processes.unwrap_or_default()[0][0].contains(&DEFAULT_CMD.to_string())); cleanup_container(&docker, container_name).await; } From af7942ae83da2ed391ae307e9b2e17c94e8e9d2b Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 19:31:54 +0100 Subject: [PATCH 03/11] Fix clippy lints and make tests run again and run on podman --- src/api/image.rs | 2 +- src/api/mod.rs | 2 +- src/opts/mod.rs | 7 +++---- tests/common.rs | 8 ++++++-- tests/container_tests.rs | 6 ++---- tests/docker_tests.rs | 8 +++++++- tests/image_tests.rs | 11 +++++++---- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/api/image.rs b/src/api/image.rs index 0248698..dd34e9f 100644 --- a/src/api/image.rs +++ b/src/api/image.rs @@ -89,7 +89,7 @@ impl Image { let headers = opts .auth_header() .map(|auth| Headers::single(AUTH_HEADER, auth)) - .unwrap_or_else(Headers::default); + .unwrap_or_default(); self.docker .post_string(&ep, Payload::empty(), Some(headers)) diff --git a/src/api/mod.rs b/src/api/mod.rs index 609dd38..9b695da 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -28,7 +28,7 @@ pub mod swarm; #[cfg_attr(docsrs, doc(cfg(feature = "swarm")))] pub mod task; -pub use {container::*, exec::*, image::*, network::*, system::*, volume::*}; +pub use {container::*, exec::*, image::*, network::*, volume::*}; #[cfg(feature = "swarm")] #[cfg_attr(docsrs, doc(cfg(feature = "swarm")))] diff --git a/src/opts/mod.rs b/src/opts/mod.rs index 4e9d4ec..9142fb0 100644 --- a/src/opts/mod.rs +++ b/src/opts/mod.rs @@ -129,8 +129,7 @@ mod tests { #[cfg(feature = "chrono")] #[test] fn logs_options() { - let timestamp = chrono::NaiveDateTime::from_timestamp_opt(2_147_483_647, 0); - let since = chrono::DateTime::::from_utc(timestamp.unwrap(), chrono::Utc); + let timestamp = chrono::DateTime::from_timestamp(2_147_483_647, 0).unwrap(); let options = LogsOptsBuilder::default() .follow(true) @@ -138,7 +137,7 @@ mod tests { .stderr(true) .timestamps(true) .all() - .since(&since) + .since(×tamp) .build(); let serialized = options.serialize().unwrap(); @@ -150,7 +149,7 @@ mod tests { assert!(serialized.contains("tail=all")); assert!(serialized.contains("since=2147483647")); - let options = LogsOptsBuilder::default().n_lines(5).until(&since).build(); + let options = LogsOptsBuilder::default().n_lines(5).until(×tamp).build(); let serialized = options.serialize().unwrap(); diff --git a/tests/common.rs b/tests/common.rs index 44bed52..ca05eb4 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -3,8 +3,12 @@ use std::env; use std::path::PathBuf; -pub use docker_api::{api, conn, models, models::ImageBuildChunk, opts, Docker}; -pub use futures_util::{StreamExt, TryStreamExt}; +pub use docker_api::{api, models, models::ImageBuildChunk, opts, Docker}; +pub use futures_util::StreamExt; +#[cfg(test)] +pub use futures_util::TryStreamExt; +#[cfg(test)] +pub use docker_api::conn; pub use tempfile::TempDir; pub const DEFAULT_IMAGE: &str = "ubuntu:latest"; diff --git a/tests/container_tests.rs b/tests/container_tests.rs index 13d2828..abc1c08 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -677,12 +677,11 @@ async fn container_attach() { let _ = container.start().await; let mut multiplexer = container.attach().await.unwrap(); - while let Some(chunk) = multiplexer.next().await { + if let Some(chunk) = multiplexer.next().await { match chunk { Ok(TtyChunk::StdOut(chunk)) => { let logs = String::from_utf8_lossy(&chunk); assert_eq!(logs, "123456\r\n"); - break; } chunk => { eprintln!("invalid chunk {chunk:?}"); @@ -713,12 +712,11 @@ async fn container_attach() { let _ = container.start().await; let mut multiplexer = container.attach().await.unwrap(); - while let Some(chunk) = multiplexer.next().await { + if let Some(chunk) = multiplexer.next().await { match chunk { Ok(TtyChunk::StdOut(chunk)) => { let logs = String::from_utf8_lossy(&chunk); assert_eq!(logs, "123456\n"); - break; } chunk => { eprintln!("invalid chunk {chunk:?}"); diff --git a/tests/docker_tests.rs b/tests/docker_tests.rs index fbf4f23..4ea24e2 100644 --- a/tests/docker_tests.rs +++ b/tests/docker_tests.rs @@ -10,9 +10,15 @@ async fn docker_info() { let info_result = docker.info().await; assert!(info_result.is_ok()); let info_data = info_result.unwrap(); + + let hostname = match info_data.default_runtime { + Some(runtime) if runtime == "crun" => "localhost.localdomain".to_string(), + _ => gethostname::gethostname().into_string().unwrap(), + }; + assert_eq!( info_data.name.unwrap(), - gethostname::gethostname().into_string().unwrap() + hostname ); } diff --git a/tests/image_tests.rs b/tests/image_tests.rs index 1577325..7fd5b19 100644 --- a/tests/image_tests.rs +++ b/tests/image_tests.rs @@ -2,9 +2,11 @@ mod common; use common::{ create_base_image, get_image_full_id, init_runtime, opts, tempdir_with_dockerfile, StreamExt, - TryStreamExt, DEFAULT_IMAGE, + DEFAULT_IMAGE, }; +use futures_util::TryStreamExt; + #[tokio::test] async fn image_create_inspect_delete() { let docker = init_runtime(); @@ -41,7 +43,8 @@ async fn image_inspect() { .repo_tags .as_ref() .unwrap() - .contains(&format!("{image_name}:latest"))); + .iter() + .any(|tag| tag.contains(&format!("{image_name}:latest")))); assert!(image.delete().await.is_ok()); } @@ -61,7 +64,7 @@ async fn image_history() { println!("{history_data:#?}"); assert!(history_data .iter() - .any(|item| item.tags.iter().any(|t| t == DEFAULT_IMAGE))); + .any(|item| item.tags.iter().any(|t| t.contains(DEFAULT_IMAGE)))); } #[tokio::test] @@ -89,7 +92,7 @@ async fn image_tag() { .expect("image inspect data") .repo_tags .expect("repo tags") - .contains(&new_tag)); + .iter().any(|tag| tag.contains(&new_tag))); //cleanup let _ = image.delete().await; From 8799cffda8b6ed2e36877513f8c6c3a44b5276b8 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 19:36:37 +0100 Subject: [PATCH 04/11] Fix formatting --- src/opts/mod.rs | 5 ++++- tests/common.rs | 4 ++-- tests/container_tests.rs | 4 +++- tests/docker_tests.rs | 5 +---- tests/image_tests.rs | 3 ++- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/opts/mod.rs b/src/opts/mod.rs index 9142fb0..f303704 100644 --- a/src/opts/mod.rs +++ b/src/opts/mod.rs @@ -149,7 +149,10 @@ mod tests { assert!(serialized.contains("tail=all")); assert!(serialized.contains("since=2147483647")); - let options = LogsOptsBuilder::default().n_lines(5).until(×tamp).build(); + let options = LogsOptsBuilder::default() + .n_lines(5) + .until(×tamp) + .build(); let serialized = options.serialize().unwrap(); diff --git a/tests/common.rs b/tests/common.rs index ca05eb4..52786df 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -3,12 +3,12 @@ use std::env; use std::path::PathBuf; +#[cfg(test)] +pub use docker_api::conn; pub use docker_api::{api, models, models::ImageBuildChunk, opts, Docker}; pub use futures_util::StreamExt; #[cfg(test)] pub use futures_util::TryStreamExt; -#[cfg(test)] -pub use docker_api::conn; pub use tempfile::TempDir; pub const DEFAULT_IMAGE: &str = "ubuntu:latest"; diff --git a/tests/container_tests.rs b/tests/container_tests.rs index abc1c08..1003ddc 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -508,7 +508,9 @@ async fn container_top() { let top_result = container.top(None).await; assert!(top_result.is_ok()); - assert!(top_result.unwrap().processes.unwrap_or_default()[0][0].contains(&DEFAULT_CMD.to_string())); + assert!( + top_result.unwrap().processes.unwrap_or_default()[0][0].contains(&DEFAULT_CMD.to_string()) + ); cleanup_container(&docker, container_name).await; } diff --git a/tests/docker_tests.rs b/tests/docker_tests.rs index 4ea24e2..6cd6d87 100644 --- a/tests/docker_tests.rs +++ b/tests/docker_tests.rs @@ -16,10 +16,7 @@ async fn docker_info() { _ => gethostname::gethostname().into_string().unwrap(), }; - assert_eq!( - info_data.name.unwrap(), - hostname - ); + assert_eq!(info_data.name.unwrap(), hostname); } #[tokio::test] diff --git a/tests/image_tests.rs b/tests/image_tests.rs index 7fd5b19..0edd6d9 100644 --- a/tests/image_tests.rs +++ b/tests/image_tests.rs @@ -92,7 +92,8 @@ async fn image_tag() { .expect("image inspect data") .repo_tags .expect("repo tags") - .iter().any(|tag| tag.contains(&new_tag))); + .iter() + .any(|tag| tag.contains(&new_tag))); //cleanup let _ = image.delete().await; From aaa642f16f15c4f70c5e374f609e7a3eaa8853a5 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 20:26:05 +0100 Subject: [PATCH 05/11] Fix containers_top --- tests/container_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/container_tests.rs b/tests/container_tests.rs index 1003ddc..f4b2638 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -509,7 +509,7 @@ async fn container_top() { let top_result = container.top(None).await; assert!(top_result.is_ok()); assert!( - top_result.unwrap().processes.unwrap_or_default()[0][0].contains(&DEFAULT_CMD.to_string()) + top_result.unwrap().processes.unwrap_or_default()[0].contains(&DEFAULT_CMD.to_string()) ); cleanup_container(&docker, container_name).await; From b151f01cdf0ba2952897dce7516cc7f31e25120c Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:05:02 +0100 Subject: [PATCH 06/11] The tests are very race-y so lets limit the jobs to one --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cadb323..c1713ff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -47,5 +47,5 @@ jobs: - name: Test run: | docker pull ubuntu:latest - cargo test --all-features --all-targets + cargo test --all-features --all-targets -j1 cargo test --doc From 5611f29ff97fa763b5effc39a7807e31a4f46f22 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:05:46 +0100 Subject: [PATCH 07/11] Remove useless docker_info logic that prevents using Podman or a remote docker socket --- tests/docker_tests.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/docker_tests.rs b/tests/docker_tests.rs index 6cd6d87..013721d 100644 --- a/tests/docker_tests.rs +++ b/tests/docker_tests.rs @@ -9,14 +9,6 @@ async fn docker_info() { let info_result = docker.info().await; assert!(info_result.is_ok()); - let info_data = info_result.unwrap(); - - let hostname = match info_data.default_runtime { - Some(runtime) if runtime == "crun" => "localhost.localdomain".to_string(), - _ => gethostname::gethostname().into_string().unwrap(), - }; - - assert_eq!(info_data.name.unwrap(), hostname); } #[tokio::test] From 671681ca3a2f3980243fd9d79047585c906ae0e7 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:06:09 +0100 Subject: [PATCH 08/11] Add podman support for container_top --- tests/container_tests.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/container_tests.rs b/tests/container_tests.rs index f4b2638..f2612e1 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -501,6 +501,13 @@ async fn container_stats() { async fn container_top() { let docker = init_runtime(); + let version = docker.version().await.unwrap(); + let is_podman = version + .components + .unwrap_or_default() + .iter() + .any(|component| component.name == "Podman Engine"); + let container_name = "test-top-container"; let container = create_base_container(&docker, container_name, None).await; @@ -508,9 +515,15 @@ async fn container_top() { let top_result = container.top(None).await; assert!(top_result.is_ok()); - assert!( - top_result.unwrap().processes.unwrap_or_default()[0].contains(&DEFAULT_CMD.to_string()) - ); + + if is_podman { + assert!(top_result.unwrap().processes.unwrap_or_default()[0][0] + .contains(&DEFAULT_CMD.to_string())); + } else { + assert!( + top_result.unwrap().processes.unwrap_or_default()[0].contains(&DEFAULT_CMD.to_string()) + ); + } cleanup_container(&docker, container_name).await; } From e2f696908c1774b58c46a0f760f623b7556da3eb Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Sat, 30 Mar 2024 16:23:29 +0100 Subject: [PATCH 09/11] Export TtyMultiplexer --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 730483c..a355841 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,9 @@ mod stream; pub mod conn { //! Connection related items pub(crate) use containers_api::conn::*; - pub use containers_api::conn::{Error, Transport, TtyChunk}; + pub use containers_api::conn::{ + tty::Multiplexer as TtyMultiplexer, Error, Transport, TtyChunk, + }; } pub mod docker; pub mod errors; From 2373c396dce520ab063c9779c24d6daee929b0b0 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 24 May 2024 16:14:11 +0200 Subject: [PATCH 10/11] Add support for seeing previous messages when attach()ing and fix clippy lints and tests --- examples/container.rs | 2 +- src/api/container.rs | 9 +++++++-- src/opts/container.rs | 25 ++++++++++++++----------- src/opts/image.rs | 10 ++++++---- tests/container_tests.rs | 4 ++-- tests/network_tests.rs | 3 +-- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/examples/container.rs b/examples/container.rs index 0d5b2de..0d29ac4 100644 --- a/examples/container.rs +++ b/examples/container.rs @@ -129,7 +129,7 @@ async fn main() -> Result<(), Box> { match opts.subcmd { Cmd::Attach { id } => { let container = docker.containers().get(&id); - let tty_multiplexer = container.attach().await?; + let tty_multiplexer = container.attach(false).await?; let (mut reader, _writer) = tty_multiplexer.split(); diff --git a/src/api/container.rs b/src/api/container.rs index 3085a93..278e12e 100644 --- a/src/api/container.rs +++ b/src/api/container.rs @@ -47,13 +47,18 @@ impl Container { /// The [`TtyMultiplexer`](TtyMultiplexer) implements Stream for returning Stdout and Stderr chunks. It also implements [`AsyncWrite`](futures_util::io::AsyncWrite) for writing to Stdin. /// /// The multiplexer can be split into its read and write halves with the [`split`](TtyMultiplexer::split) method - pub async fn attach(&self) -> Result { + pub async fn attach(&self, logs: bool) -> Result { let inspect = self.inspect().await?; + let logs = if logs { + 1 + } else { + 0 + }; let is_tty = inspect.config.and_then(|c| c.tty).unwrap_or_default(); stream::attach( self.docker.clone(), format!( - "/containers/{}/attach?stream=1&stdout=1&stderr=1&stdin=1", + "/containers/{}/attach?stream=1&stdout=1&stderr=1&stdin=1&logs={logs}", self.id ), Payload::empty(), diff --git a/src/opts/container.rs b/src/opts/container.rs index cdf6e1b..9767db1 100644 --- a/src/opts/container.rs +++ b/src/opts/container.rs @@ -15,6 +15,7 @@ use std::{ string::ToString, time::Duration, }; +use std::fmt::{Display, Formatter}; use serde::{Deserialize, Serialize}; use serde_json::{json, Map, Value}; @@ -331,9 +332,9 @@ impl FromStr for PublishPort { } } -impl ToString for PublishPort { - fn to_string(&self) -> String { - format!("{}/{}", self.port, self.protocol.as_ref()) +impl Display for PublishPort { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}/{}", self.port, self.protocol.as_ref()) } } @@ -388,15 +389,16 @@ pub enum IpcMode { Host, } -impl ToString for IpcMode { - fn to_string(&self) -> String { - match &self { +impl Display for IpcMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = match &self { IpcMode::None => String::from("none"), IpcMode::Private => String::from("private"), IpcMode::Shareable => String::from("shareable"), IpcMode::Container(id) => format!("container:{}", id), IpcMode::Host => String::from("host"), - } + }; + write!(f, "{}", str) } } @@ -408,12 +410,13 @@ pub enum PidMode { Host, } -impl ToString for PidMode { - fn to_string(&self) -> String { - match &self { +impl Display for PidMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = match &self { PidMode::Container(id) => format!("container:{}", id), PidMode::Host => String::from("host"), - } + }; + write!(f, "{}", str) } } diff --git a/src/opts/image.rs b/src/opts/image.rs index 26e9a66..bfc1273 100644 --- a/src/opts/image.rs +++ b/src/opts/image.rs @@ -3,6 +3,7 @@ use std::{ path::{Path, PathBuf}, string::ToString, }; +use std::fmt::Display; use containers_api::opts::{Filter, FilterItem}; use containers_api::url::encoded_pairs; @@ -370,16 +371,17 @@ pub enum ImageName { Digest { image: String, digest: String }, } -impl ToString for ImageName { - fn to_string(&self) -> String { - match &self { +impl Display for ImageName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = match &self { ImageName::Tag { image, tag } => match tag { Some(tag) => format!("{image}:{tag}"), None => image.to_owned(), }, ImageName::Id(id) => id.to_owned(), ImageName::Digest { image, digest } => format!("{image}@{digest}"), - } + }; + write!(f, "{}", str) } } diff --git a/tests/container_tests.rs b/tests/container_tests.rs index f2612e1..0ceefda 100644 --- a/tests/container_tests.rs +++ b/tests/container_tests.rs @@ -691,7 +691,7 @@ async fn container_attach() { let _ = container.start().await; - let mut multiplexer = container.attach().await.unwrap(); + let mut multiplexer = container.attach(false).await.unwrap(); if let Some(chunk) = multiplexer.next().await { match chunk { Ok(TtyChunk::StdOut(chunk)) => { @@ -726,7 +726,7 @@ async fn container_attach() { let _ = container.start().await; - let mut multiplexer = container.attach().await.unwrap(); + let mut multiplexer = container.attach(false).await.unwrap(); if let Some(chunk) = multiplexer.next().await { match chunk { Ok(TtyChunk::StdOut(chunk)) => { diff --git a/tests/network_tests.rs b/tests/network_tests.rs index 2490cb2..c963871 100644 --- a/tests/network_tests.rs +++ b/tests/network_tests.rs @@ -187,8 +187,7 @@ async fn network_connect_disconnect() { .unwrap() .networks .unwrap() - .get(network_name) - .is_some()); + .contains_key(network_name)); let _ = network.delete().await; let _ = container.delete().await; From 188d1513dc70c06fedfa7f7664a53936ad18d251 Mon Sep 17 00:00:00 2001 From: not-jan <61017633+not-jan@users.noreply.github.com> Date: Fri, 24 May 2024 16:19:54 +0200 Subject: [PATCH 11/11] Formatting --- src/opts/container.rs | 2 +- src/opts/image.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opts/container.rs b/src/opts/container.rs index 9767db1..be173ed 100644 --- a/src/opts/container.rs +++ b/src/opts/container.rs @@ -6,6 +6,7 @@ use containers_api::{ impl_str_field, impl_url_bool_field, impl_url_str_field, impl_vec_field, }; +use std::fmt::{Display, Formatter}; use std::net::SocketAddr; use std::{ collections::HashMap, @@ -15,7 +16,6 @@ use std::{ string::ToString, time::Duration, }; -use std::fmt::{Display, Formatter}; use serde::{Deserialize, Serialize}; use serde_json::{json, Map, Value}; diff --git a/src/opts/image.rs b/src/opts/image.rs index bfc1273..3bec582 100644 --- a/src/opts/image.rs +++ b/src/opts/image.rs @@ -1,9 +1,9 @@ +use std::fmt::Display; use std::{ collections::HashMap, path::{Path, PathBuf}, string::ToString, }; -use std::fmt::Display; use containers_api::opts::{Filter, FilterItem}; use containers_api::url::encoded_pairs;