summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Schreiber <info@schrieveslaach.de>2019-09-14 11:07:09 +0200
committerDoug Tangren <d.tangren@gmail.com>2019-09-14 18:07:09 +0900
commit63ef2b3b66616055535d9ad43253de1df83ab527 (patch)
tree0f75b9ce94f1878c7249c42bc1807102bd4a583b
parent779ac244658d7641458ad669620c02f71037a8d3 (diff)
feat: use chrono to deserialize date times (#190)
-rw-r--r--CHANGELOG.md4
-rw-r--r--Cargo.toml3
-rw-r--r--examples/images.rs3
-rw-r--r--src/builder.rs40
-rw-r--r--src/rep.rs59
5 files changed, 107 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6320ce4..6809071 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.6.0
+
+* add chrono as an optional feature [#190](https://github.com/softprops/shiplift/pull/190)
+
# 0.5.0
* make tls an optional dependency [#130](https://github.com/softprops/shiplift/pull/130)
diff --git a/Cargo.toml b/Cargo.toml
index 6447b99..81f1c6d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ maintenance = { status = "actively-developed" }
base64 = "0.10"
byteorder = "1.3.1"
bytes = "0.4"
+chrono = { version = "0.4", optional = true, features = ["serde"] }
flate2 = "1.0"
futures = "0.1"
http = "0.1"
@@ -42,6 +43,6 @@ url = "1.7"
env_logger = "0.6"
[features]
-default = ["unix-socket", "tls"]
+default = ["chrono", "unix-socket", "tls"]
unix-socket = ["hyperlocal"]
tls = ["openssl", "hyper-openssl"]
diff --git a/examples/images.rs b/examples/images.rs
index de04ab9..7a8a094 100644
--- a/examples/images.rs
+++ b/examples/images.rs
@@ -10,8 +10,9 @@ fn main() {
.map(|images| {
for i in images {
println!(
- "{} {:?}",
+ "{} {} {:?}",
i.id,
+ i.created,
i.repo_tags.unwrap_or_else(|| vec!["none".into()])
);
}
diff --git a/src/builder.rs b/src/builder.rs
index ea9bd32..cb924ac 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1190,6 +1190,20 @@ impl LogsOptionsBuilder {
self
}
+ #[cfg(feature = "chrono")]
+ pub fn since<Tz>(
+ &mut self,
+ timestamp: &chrono::DateTime<Tz>,
+ ) -> &mut Self
+ where
+ Tz: chrono::TimeZone,
+ {
+ self.params
+ .insert("since", timestamp.timestamp().to_string());
+ self
+ }
+
+ #[cfg(not(feature = "chrono"))]
pub fn since(
&mut self,
timestamp: i64,
@@ -1712,6 +1726,32 @@ mod tests {
);
}
+ #[cfg(feature = "chrono")]
+ #[test]
+ fn logs_options() {
+ let timestamp = chrono::NaiveDateTime::from_timestamp(2_147_483_647, 0);
+ let since = chrono::DateTime::<chrono::Utc>::from_utc(timestamp, chrono::Utc);
+
+ let options = LogsOptionsBuilder::default()
+ .follow(true)
+ .stdout(true)
+ .stderr(true)
+ .timestamps(true)
+ .tail("all")
+ .since(&since)
+ .build();
+
+ let serialized = options.serialize().unwrap();
+
+ assert!(serialized.contains("follow=true"));
+ assert!(serialized.contains("stdout=true"));
+ assert!(serialized.contains("stderr=true"));
+ assert!(serialized.contains("timestamps=true"));
+ assert!(serialized.contains("tail=all"));
+ assert!(serialized.contains("since=2147483647"));
+ }
+
+ #[cfg(not(feature = "chrono"))]
#[test]
fn logs_options() {
let options = LogsOptionsBuilder::default()
diff --git a/src/rep.rs b/src/rep.rs
index d5771d9..80815da 100644
--- a/src/rep.rs
+++ b/src/rep.rs
@@ -1,5 +1,7 @@
//! Rust representations of docker json structures
+#[cfg(feature = "chrono")]
+use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -15,6 +17,10 @@ pub struct SearchResult {
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Image {
+ #[cfg(feature = "chrono")]
+ #[serde(deserialize_with = "datetime_from_unix_timestamp")]
+ pub created: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created: u64,
pub id: String,
pub parent_id: String,
@@ -31,6 +37,9 @@ pub struct ImageDetails {
pub author: String,
pub comment: String,
pub config: Config,
+ #[cfg(feature = "chrono")]
+ pub created: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created: String,
pub docker_version: String,
pub id: String,
@@ -43,6 +52,10 @@ pub struct ImageDetails {
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Container {
+ #[cfg(feature = "chrono")]
+ #[serde(deserialize_with = "datetime_from_unix_timestamp")]
+ pub created: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created: u64,
pub command: String,
pub id: String,
@@ -61,6 +74,9 @@ pub struct ContainerDetails {
pub app_armor_profile: String,
pub args: Vec<String>,
pub config: Config,
+ #[cfg(feature = "chrono")]
+ pub created: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created: String,
pub driver: String,
// pub ExecIDs: ??
@@ -96,6 +112,9 @@ pub struct Mount {
pub struct State {
pub error: String,
pub exit_code: u64,
+ #[cfg(feature = "chrono")]
+ pub finished_at: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub finished_at: String,
#[serde(rename = "OOMKilled")]
pub oom_killed: bool,
@@ -103,6 +122,9 @@ pub struct State {
pub pid: u64,
pub restarting: bool,
pub running: bool,
+ #[cfg(feature = "chrono")]
+ pub started_at: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub started_at: String,
}
@@ -420,6 +442,10 @@ pub struct ContainerCreateInfo {
#[serde(rename_all = "PascalCase")]
pub struct History {
pub id: String,
+ #[cfg(feature = "chrono")]
+ #[serde(deserialize_with = "datetime_from_unix_timestamp")]
+ pub created: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created: u64,
pub created_by: String,
}
@@ -441,7 +467,15 @@ pub struct Event {
pub status: Option<String>,
pub id: Option<String>,
pub from: Option<String>,
+ #[cfg(feature = "chrono")]
+ #[serde(deserialize_with = "datetime_from_unix_timestamp")]
+ pub time: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub time: u64,
+ #[cfg(feature = "chrono")]
+ #[serde(deserialize_with = "datetime_from_nano_timestamp", rename = "timeNano")]
+ pub time_nano: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
#[serde(rename = "timeNano")]
pub time_nano: u64,
}
@@ -476,6 +510,9 @@ pub struct Volumes {
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Volume {
+ #[cfg(feature = "chrono")]
+ pub created_at: DateTime<Utc>,
+ #[cfg(not(feature = "chrono"))]
pub created_at: String,
pub driver: String,
pub labels: Option<HashMap<String, String>>,
@@ -484,3 +521,25 @@ pub struct Volume {
pub options: Option<HashMap<String, String>>,
pub scope: String,
}
+
+#[cfg(feature = "chrono")]
+fn datetime_from_unix_timestamp<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+{
+ let timestamp = chrono::NaiveDateTime::from_timestamp(i64::deserialize(deserializer)?, 0);
+ Ok(DateTime::<Utc>::from_utc(timestamp, Utc))
+}
+
+#[cfg(feature = "chrono")]
+fn datetime_from_nano_timestamp<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+{
+ let timestamp_nano = u64::deserialize(deserializer)?;
+ let timestamp = chrono::NaiveDateTime::from_timestamp(
+ (timestamp_nano / 1_000_000_000) as i64,
+ (timestamp_nano % 1_000_000_000) as u32,
+ );
+ Ok(DateTime::<Utc>::from_utc(timestamp, Utc))
+}