From 973495a669e4a9f0882aa9f311801afb6176a476 Mon Sep 17 00:00:00 2001 From: Niel Drummond Date: Sat, 11 Jun 2022 13:42:32 +0100 Subject: [PATCH] Make chrono and time optional --- .circleci/config.yml | 2 +- Cargo.toml | 7 +- .../src/main/java/bollard/BollardCodegen.java | 6 +- .../src/main/resources/bollard/Cargo.mustache | 3 +- .../main/resources/bollard/models.mustache | 32 ++++++-- codegen/target/generated-sources/Cargo.toml | 3 +- codegen/target/generated-sources/README.md | 2 +- .../target/generated-sources/src/models.rs | 82 ++++++++++++------- dockerfiles/bin/run_integration_tests.sh | 2 +- examples/hoover.rs | 22 ++++- src/container.rs | 15 +++- src/docker.rs | 26 ++++-- src/read.rs | 1 - src/system.rs | 21 ++++- tests/service_test.rs | 1 - tests/system_test.rs | 9 +- tests/volume_test.rs | 2 +- 17 files changed, 170 insertions(+), 66 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 832dca83..d481eb68 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,7 +37,7 @@ jobs: - checkout - setup_remote_docker - run: docker build -t bollard . - - run: docker run -ti --rm bollard cargo test --target x86_64-unknown-linux-gnu --doc + - run: docker run -ti --rm bollard cargo test --features time --target x86_64-unknown-linux-gnu --doc test_clippy: docker: - image: docker:20.10.16 diff --git a/Cargo.toml b/Cargo.toml index 3b392b08..3ea909b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,14 @@ test_macos = [] # Enable rustls / ssl ssl = ["dirs-next", "hyper-rustls", "rustls", "rustls-native-certs", "rustls-pemfile", "webpki", "webpki-roots"] ct_logs = ["ssl", "ct-logs"] +chrono = ["dep:chrono", "bollard-stubs/chrono"] +time = ["dep:time", "bollard-stubs/time"] [dependencies] base64 = "0.13" -bollard-stubs = { version = "=1.42.0-rc.2", path = "codegen/target/generated-sources" } +bollard-stubs = { version = "=1.42.0-rc.2", path = "codegen/target/generated-sources", default-features = false } bytes = "1" +chrono = { version = "0.4", features = ["serde"], optional = true } ct-logs = { version = "0.9.0", optional = true } dirs-next = { version = "2.0", optional = true } futures-core = "0.3" @@ -45,7 +48,7 @@ serde_json = "1.0" serde_urlencoded = "0.7" tokio = { version = "1.7", features = ["time", "net", "io-util"] } thiserror = "1.0" -time = { version = "0.3", features = ["formatting", "parsing"] } +time = { version = "0.3", features = ["formatting", "parsing"], optional = true } tokio-util = { version = "0.7", features = ["codec"] } url = "2.2" webpki-roots = { version = "0.22", optional = true } diff --git a/codegen/src/main/java/bollard/BollardCodegen.java b/codegen/src/main/java/bollard/BollardCodegen.java index fd207061..616623f1 100644 --- a/codegen/src/main/java/bollard/BollardCodegen.java +++ b/codegen/src/main/java/bollard/BollardCodegen.java @@ -22,7 +22,7 @@ public class BollardCodegen extends RustServerCodegen { public BollardCodegen() { super(); - typeMapping.put("DateTime", "OffsetDateTime"); + typeMapping.put("DateTime", "BollardDate"); } // Declare custom additions to inline enums that are behaving differently @@ -124,10 +124,10 @@ public Map postProcessAllModels(Map objs) { } else if (prop.name.equals("_type")) { prop.name = "typ"; } - if (prop.dataFormat != null && (prop.dataFormat.equals("dateTime") || prop.datatype.equals("OffsetDateTime"))) { + if (prop.dataFormat != null && (prop.dataFormat.equals("dateTime") || prop.datatype.equals("BollardDate"))) { // set DateTime format on properties where appropriate prop.vendorExtensions.put("x-rustgen-is-datetime", true); - prop.datatype = "OffsetDateTime"; + prop.datatype = "BollardDate"; } if (prop.isEnum) { if (enumToString.contains(model.classname)) { diff --git a/codegen/src/main/resources/bollard/Cargo.mustache b/codegen/src/main/resources/bollard/Cargo.mustache index 3a242c4d..be6986f8 100644 --- a/codegen/src/main/resources/bollard/Cargo.mustache +++ b/codegen/src/main/resources/bollard/Cargo.mustache @@ -7,7 +7,8 @@ license = "Apache-2.0" edition = "2018" [dependencies] +chrono = { version = "0.4", features = ["serde"], optional = true } serde = { version = "1.0", features = ["derive"] } -time = { version = "0.3", features = ["formatting", "parsing"] } +time = { version = "0.3", features = ["formatting", "parsing"], optional = true } serde_with = "1.4" diff --git a/codegen/src/main/resources/bollard/models.mustache b/codegen/src/main/resources/bollard/models.mustache index 50bd5a82..76f7d1ee 100644 --- a/codegen/src/main/resources/bollard/models.mustache +++ b/codegen/src/main/resources/bollard/models.mustache @@ -9,8 +9,6 @@ use std::collections::HashMap; use std::default::Default; use std::hash::Hash; -use time::OffsetDateTime; - fn deserialize_nonoptional_vec<'de, D: Deserializer<'de>, T: DeserializeOwned>( d: D, ) -> Result, D::Error> { @@ -23,13 +21,21 @@ fn deserialize_nonoptional_map<'de, D: Deserializer<'de>, T: DeserializeOwned>( serde::Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or(HashMap::new())) } +#[cfg(feature = "time")] +pub type BollardDate = time::OffsetDateTime; +#[cfg(feature = "chrono")] +pub type BollardDate = chrono::DateTime; +#[cfg(not(any(feature = "chrono", feature = "time")))] +pub type BollardDate = String; + +#[cfg(feature = "time")] fn deserialize_timestamp<'de, D: Deserializer<'de>>( d: D -) -> Result, D::Error> { +) -> Result, D::Error> { let opt: Option = serde::Deserialize::deserialize(d)?; if let Some(s) = opt { Ok(Some( - OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) + time::OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?, )) } else { @@ -37,7 +43,15 @@ fn deserialize_timestamp<'de, D: Deserializer<'de>>( } } -fn serialize_timestamp(date: &Option, s: S) -> Result { +#[cfg(not(feature = "time"))] +fn deserialize_timestamp<'de, D: Deserializer<'de>>( + d: D +) -> Result, D::Error> { + serde::Deserialize::deserialize(d) +} + +#[cfg(feature = "time")] +fn serialize_timestamp(date: &Option, s: S) -> Result { match date { Some(inner) => Ok(s.serialize_str(&inner.format(&time::format_description::well_known::Rfc3339) .map_err(|e| serde::ser::Error::custom(format!("{:?}", e)))?)?), @@ -45,6 +59,14 @@ fn serialize_timestamp(date: &Option, s: S) -> Re } } +#[cfg(not(feature = "time"))] +fn serialize_timestamp(date: &Option, s: S) -> Result { + match date { + Some(inner) => s.serialize_some(inner), + None => s.serialize_none() + } +} + {{#models}}{{#model}} {{#description}}/// {{{description}}} {{/description}}{{#isEnum}}/// Enumeration of values. diff --git a/codegen/target/generated-sources/Cargo.toml b/codegen/target/generated-sources/Cargo.toml index 225cc8f2..31ad109c 100644 --- a/codegen/target/generated-sources/Cargo.toml +++ b/codegen/target/generated-sources/Cargo.toml @@ -7,7 +7,8 @@ license = "Apache-2.0" edition = "2018" [dependencies] +chrono = { version = "0.4", features = ["serde"], optional = true } serde = { version = "1.0", features = ["derive"] } -time = { version = "0.3", features = ["formatting", "parsing"] } +time = { version = "0.3", features = ["formatting", "parsing"], optional = true } serde_with = "1.4" diff --git a/codegen/target/generated-sources/README.md b/codegen/target/generated-sources/README.md index 2a14d4f0..3a157dd5 100644 --- a/codegen/target/generated-sources/README.md +++ b/codegen/target/generated-sources/README.md @@ -9,7 +9,7 @@ To see how to make this your own, look here: - API version: 1.42.0-rc.2 - Code generation suffix: 1.42.0-rc.2 -- Build date: 2022-06-11T11:56:09.243+01:00 +- Build date: 2022-06-11T13:13:57.645+01:00 This autogenerated project defines an API crate `bollard-stubs` which contains: * Data types representing the underlying data model. diff --git a/codegen/target/generated-sources/src/models.rs b/codegen/target/generated-sources/src/models.rs index 6367b04f..28b073f8 100644 --- a/codegen/target/generated-sources/src/models.rs +++ b/codegen/target/generated-sources/src/models.rs @@ -9,8 +9,6 @@ use std::collections::HashMap; use std::default::Default; use std::hash::Hash; -use time::OffsetDateTime; - fn deserialize_nonoptional_vec<'de, D: Deserializer<'de>, T: DeserializeOwned>( d: D, ) -> Result, D::Error> { @@ -23,13 +21,21 @@ fn deserialize_nonoptional_map<'de, D: Deserializer<'de>, T: DeserializeOwned>( serde::Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or(HashMap::new())) } +#[cfg(feature = "time")] +pub type BollardDate = time::OffsetDateTime; +#[cfg(feature = "chrono")] +pub type BollardDate = chrono::DateTime; +#[cfg(not(any(feature = "chrono", feature = "time")))] +pub type BollardDate = String; + +#[cfg(feature = "time")] fn deserialize_timestamp<'de, D: Deserializer<'de>>( d: D -) -> Result, D::Error> { +) -> Result, D::Error> { let opt: Option = serde::Deserialize::deserialize(d)?; if let Some(s) = opt { Ok(Some( - OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) + time::OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?, )) } else { @@ -37,7 +43,15 @@ fn deserialize_timestamp<'de, D: Deserializer<'de>>( } } -fn serialize_timestamp(date: &Option, s: S) -> Result { +#[cfg(not(feature = "time"))] +fn deserialize_timestamp<'de, D: Deserializer<'de>>( + d: D +) -> Result, D::Error> { + serde::Deserialize::deserialize(d) +} + +#[cfg(feature = "time")] +fn serialize_timestamp(date: &Option, s: S) -> Result { match date { Some(inner) => Ok(s.serialize_str(&inner.format(&time::format_description::well_known::Rfc3339) .map_err(|e| serde::ser::Error::custom(format!("{:?}", e)))?)?), @@ -45,6 +59,14 @@ fn serialize_timestamp(date: &Option, s: S) -> Re } } +#[cfg(not(feature = "time"))] +fn serialize_timestamp(date: &Option, s: S) -> Result { + match date { + Some(inner) => s.serialize_some(inner), + None => s.serialize_none() + } +} + /// Address represents an IPv4 or IPv6 IP address. #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] @@ -116,13 +138,13 @@ pub struct BuildCache { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, /// Date and time at which the build cache was last used in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. #[serde(rename = "LastUsedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub last_used_at: Option, + pub last_used_at: Option, #[serde(rename = "UsageCount")] #[serde(skip_serializing_if="Option::is_none")] @@ -195,13 +217,13 @@ pub struct ClusterInfo { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, /// Date and time at which the swarm was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -261,12 +283,12 @@ pub struct Config { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -1723,13 +1745,13 @@ pub struct HealthcheckResult { #[serde(rename = "Start")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub start: Option, + pub start: Option, /// Date and time at which this check ended in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. #[serde(rename = "End")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub end: Option, + pub end: Option, /// ExitCode meanings: - `0` healthy - `1` unhealthy - `2` reserved (considered unhealthy) - other values: error running probe #[serde(rename = "ExitCode")] @@ -2364,7 +2386,7 @@ pub struct ImageInspectMetadata { #[serde(rename = "LastTagTime")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub last_tag_time: Option, + pub last_tag_time: Option, } @@ -2965,7 +2987,7 @@ pub struct Network { #[serde(rename = "Created")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created: Option, + pub created: Option, #[serde(rename = "Scope")] #[serde(skip_serializing_if="Option::is_none")] @@ -3273,13 +3295,13 @@ pub struct Node { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, /// Date and time at which the node was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -4459,12 +4481,12 @@ pub struct Secret { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -4514,12 +4536,12 @@ pub struct Service { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -4597,7 +4619,7 @@ pub struct ServiceJobStatus { #[serde(rename = "LastExecution")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub last_execution: Option, + pub last_execution: Option, } @@ -4976,12 +4998,12 @@ pub struct ServiceUpdateStatus { #[serde(rename = "StartedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub started_at: Option, + pub started_at: Option, #[serde(rename = "CompletedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub completed_at: Option, + pub completed_at: Option, #[serde(rename = "Message")] #[serde(skip_serializing_if="Option::is_none")] @@ -5068,13 +5090,13 @@ pub struct Swarm { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, /// Date and time at which the swarm was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, #[serde(rename = "Spec")] #[serde(skip_serializing_if="Option::is_none")] @@ -6060,12 +6082,12 @@ pub struct Task { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, #[serde(rename = "UpdatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub updated_at: Option, + pub updated_at: Option, /// Name of the task. #[serde(rename = "Name")] @@ -6789,7 +6811,7 @@ pub struct TaskStatus { #[serde(rename = "Timestamp")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub timestamp: Option, + pub timestamp: Option, #[serde(rename = "State")] #[serde(skip_serializing_if="Option::is_none")] @@ -6886,7 +6908,7 @@ pub struct Volume { #[serde(rename = "CreatedAt")] #[serde(skip_serializing_if="Option::is_none")] #[serde(default, deserialize_with = "deserialize_timestamp", serialize_with = "serialize_timestamp")] - pub created_at: Option, + pub created_at: Option, /// Low-level details about the volume, provided by the volume driver. Details are returned as a map with key/value pairs: `{\"key\":\"value\",\"key2\":\"value2\"}`. The `Status` field is optional, and is omitted if the volume driver does not support this feature. #[serde(rename = "Status")] diff --git a/dockerfiles/bin/run_integration_tests.sh b/dockerfiles/bin/run_integration_tests.sh index 73c744ae..6fc3170d 100755 --- a/dockerfiles/bin/run_integration_tests.sh +++ b/dockerfiles/bin/run_integration_tests.sh @@ -20,4 +20,4 @@ docker push localhost:5000/hello-world:linux docker push localhost:5000/fussybeaver/uhttpd docker push localhost:5000/alpine docker swarm init -docker run -e RUST_LOG=bollard=debug -e REGISTRY_PASSWORD -e REGISTRY_HTTP_ADDR=localhost:5000 -v /var/run/docker.sock:/var/run/docker.sock -ti --rm bollard cargo test -- --test-threads 1 +docker run -e RUST_LOG=bollard=debug -e REGISTRY_PASSWORD -e REGISTRY_HTTP_ADDR=localhost:5000 -v /var/run/docker.sock:/var/run/docker.sock -ti --rm bollard cargo test -- --tests --test-threads 1 diff --git a/examples/hoover.rs b/examples/hoover.rs index 947833e0..62c83fe3 100644 --- a/examples/hoover.rs +++ b/examples/hoover.rs @@ -5,8 +5,6 @@ use bollard::{ container::PruneContainersOptions, image::PruneImagesOptions, network::PruneNetworksOptions, volume::PruneVolumesOptions, }; -use time::{Duration, OffsetDateTime}; - use std::collections::HashMap; const THRESHOLD_DAYS: i64 = 90; @@ -15,8 +13,24 @@ const THRESHOLD_DAYS: i64 = 90; async fn main() -> Result<(), Box> { let docker = Docker::connect_with_socket_defaults().unwrap(); - let date = OffsetDateTime::now_utc() - Duration::days(THRESHOLD_DAYS); - let timestamp = &date.unix_timestamp().to_string()[..]; + #[cfg(feature = "time")] + let timestamp = { + let date = time::OffsetDateTime::now_utc() - time::Duration::days(THRESHOLD_DAYS); + &date.unix_timestamp().to_string()[..] + }; + + #[cfg(feature = "chrono")] + let timestamp = { + let date = Utc::now() - Duration::days(THRESHOLD_DAYS); + &date.timestamp().to_string()[..] + }; + + #[cfg(not(any(feature = "time", feature = "chrono")))] + let timestamp = { + use std::convert::TryInto; + let date = std::time::SystemTime::now() - std::time::Duration::from_secs((THRESHOLD_DAYS * 86400).try_into().unwrap()); + &date.duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_secs().to_string()[..] + }; let mut prune_filters = HashMap::new(); prune_filters.insert("until", vec![timestamp]); diff --git a/src/container.rs b/src/container.rs index 0e6d0556..5f97a15e 100644 --- a/src/container.rs +++ b/src/container.rs @@ -5,7 +5,6 @@ use http::header::{CONNECTION, CONTENT_TYPE, UPGRADE}; use http::request::Builder; use hyper::{body::Bytes, Body, Method}; use serde::Serialize; -use time::OffsetDateTime; use tokio::io::AsyncWrite; use tokio_util::codec::FramedRead; @@ -737,16 +736,26 @@ pub struct StorageStats { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[allow(missing_docs)] pub struct Stats { + #[cfg(feature = "time")] #[serde( deserialize_with = "crate::docker::deserialize_rfc3339", serialize_with = "crate::docker::serialize_rfc3339" )] - pub read: OffsetDateTime, + pub read: time::OffsetDateTime, + #[cfg(feature = "time")] #[serde( deserialize_with = "crate::docker::deserialize_rfc3339", serialize_with = "crate::docker::serialize_rfc3339" )] - pub preread: OffsetDateTime, + pub preread: time::OffsetDateTime, + #[cfg(feature = "chrono")] + pub read: chrono::DateTime, + #[cfg(feature = "chrono")] + pub preread: chrono::DateTime, + #[cfg(not(any(feature = "chrono", feature = "time")))] + pub read: String, + #[cfg(not(any(feature = "chrono", feature = "time")))] + pub preread: String, pub num_procs: u32, pub pids_stats: PidsStats, pub network: Option, diff --git a/src/docker.rs b/src/docker.rs index 40f504d8..bd563ab9 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -29,7 +29,6 @@ use hyper_rustls::HttpsConnector; use hyperlocal::UnixConnector; #[cfg(feature = "ssl")] use rustls::sign::{CertifiedKey, RsaSigningKey}; -use time::OffsetDateTime; use tokio::io::{split, AsyncRead, AsyncWrite}; use tokio_util::codec::FramedRead; @@ -187,16 +186,18 @@ where ) } +#[cfg(feature = "time")] pub fn deserialize_rfc3339<'de, D: serde::Deserializer<'de>>( d: D, -) -> Result { +) -> Result { let s: String = serde::Deserialize::deserialize(d)?; - OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) + time::OffsetDateTime::parse(&s, &time::format_description::well_known::Rfc3339) .map_err(|e| serde::de::Error::custom(format!("{:?}", e))) } +#[cfg(feature = "time")] pub fn serialize_rfc3339( - date: &OffsetDateTime, + date: &time::OffsetDateTime, s: S, ) -> Result { s.serialize_str( @@ -206,8 +207,9 @@ pub fn serialize_rfc3339( ) } +#[cfg(feature = "time")] pub(crate) fn serialize_as_timestamp( - opt: &Option, + opt: &Option, s: S, ) -> Result where @@ -219,6 +221,20 @@ where } } +#[cfg(feature = "chrono")] +pub(crate) fn serialize_as_timestamp( + opt: &Option, + s: S, +) -> Result +where + S: serde::Serializer, +{ + match opt { + Some(t) => s.serialize_str(&format!("{}.{}", t.timestamp(), t.timestamp_subsec_nanos())), + None => s.serialize_str(""), + } +} + #[derive(Debug)] /// --- /// diff --git a/src/read.rs b/src/read.rs index ff57c656..8983158d 100644 --- a/src/read.rs +++ b/src/read.rs @@ -348,7 +348,6 @@ mod tests { #[test] fn json_decode_lacking_newline() { - env_logger::try_init().unwrap(); let mut buf = BytesMut::from(&b"{}"[..]); let mut codec: JsonLineDecoder> = JsonLineDecoder::new(); diff --git a/src/system.rs b/src/system.rs index 5b10ea5a..0a3c02a3 100644 --- a/src/system.rs +++ b/src/system.rs @@ -5,7 +5,6 @@ use http::request::Builder; use hyper::{Body, Method}; use serde::ser::Serialize; use serde_json::value::Value; -use time::OffsetDateTime; use std::collections::HashMap; use std::hash::Hash; @@ -121,11 +120,27 @@ where T: Into + Eq + Hash + Serialize, { /// Show events created since this timestamp then stream new events. + #[cfg(feature = "chrono")] #[serde(serialize_with = "crate::docker::serialize_as_timestamp")] - pub since: Option, + pub since: Option>, /// Show events created until this timestamp then stop streaming. + #[cfg(feature = "chrono")] #[serde(serialize_with = "crate::docker::serialize_as_timestamp")] - pub until: Option, + pub until: Option>, + /// Show events created since this timestamp then stream new events. + #[cfg(feature = "time")] + #[serde(serialize_with = "crate::docker::serialize_as_timestamp")] + pub since: Option, + /// Show events created until this timestamp then stop streaming. + #[cfg(feature = "time")] + #[serde(serialize_with = "crate::docker::serialize_as_timestamp")] + pub until: Option, + /// Show events created since this timestamp then stream new events. + #[cfg(not(any(feature = "time", feature = "chrono")))] + pub since: Option, + /// Show events created until this timestamp then stop streaming. + #[cfg(not(any(feature = "time", feature = "chrono")))] + pub until: Option, /// A JSON encoded value of filters (a `map[string][]string`) to process on the event list. Available filters: /// - `config=` config name or ID /// - `container=` container name or ID diff --git a/tests/service_test.rs b/tests/service_test.rs index babc48f0..ebffc928 100644 --- a/tests/service_test.rs +++ b/tests/service_test.rs @@ -37,7 +37,6 @@ async fn service_create_test(docker: Docker) -> Result<(), Error> { } async fn service_list_test(docker: Docker) -> Result<(), Error> { - env_logger::init(); let image = if cfg!(windows) { format!("{}nanoserver/iis", registry_http_addr()) } else { diff --git a/tests/system_test.rs b/tests/system_test.rs index 5d1fb347..a1c7c13b 100644 --- a/tests/system_test.rs +++ b/tests/system_test.rs @@ -9,7 +9,6 @@ use futures_util::future; use futures_util::stream::select; use futures_util::stream::StreamExt; use futures_util::stream::TryStreamExt; -use time::OffsetDateTime; use tokio::runtime::Runtime; #[macro_use] @@ -71,6 +70,7 @@ async fn events_test(docker: Docker) -> Result<(), Error> { Ok(()) } +#[cfg(any(feature = "time", feature = "chrono"))] async fn events_until_forever_test(docker: Docker) -> Result<(), Error> { let image = if cfg!(windows) { format!("{}hello-world:nanoserver", registry_http_addr()) @@ -78,7 +78,10 @@ async fn events_until_forever_test(docker: Docker) -> Result<(), Error> { format!("{}hello-world:linux", registry_http_addr()) }; - let start_time = OffsetDateTime::now_utc(); + #[cfg(feature = "time")] + let start_time = time::OffsetDateTime::now_utc(); + #[cfg(feature = "chrono")] + let start_time = chrono::Utc::now(); let stream = docker.events(Some(EventsOptions:: { since: Some(start_time), @@ -161,7 +164,7 @@ fn integration_test_events() { } #[test] -#[cfg(not(windows))] +#[cfg(all(not(windows), any(feature = "chrono", feature = "time")))] fn integration_test_events_until_forever() { connect_to_docker_and_run!(events_until_forever_test); } diff --git a/tests/volume_test.rs b/tests/volume_test.rs index ef898261..6c904883 100644 --- a/tests/volume_test.rs +++ b/tests/volume_test.rs @@ -127,7 +127,7 @@ async fn prune_volumes_test(docker: Docker) -> Result<(), Error> { })) .await?; - assert_eq!(results.volumes, None); + assert_eq!(results.volumes, Some(vec![])); let mut list_volumes_filters = HashMap::new(); list_volumes_filters.insert("label", vec!["maintainer=bollard-maintainer"]);