Skip to content

Commit e67c895

Browse files
authored
Merge pull request #126 from cgwalters/status-version
Add version and timestamp to image status fields
2 parents 6c0b7f3 + d3d07c5 commit e67c895

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

lib/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ rust-version = "1.64.0"
1212
anyhow = "1.0"
1313
camino = { version = "1.0.4", features = ["serde1"] }
1414
ostree-ext = "0.12"
15+
chrono = { version = "0.4.23", features = ["serde"] }
1516
clap = { version= "4.2", features = ["derive"] }
1617
clap_mangen = { version = "0.2", optional = true }
1718
cap-std-ext = "3"
1819
hex = "^0.4"
1920
fn-error-context = "0.2.0"
2021
gvariant = "0.4.0"
2122
indicatif = "0.17.0"
22-
k8s-openapi = { version = "0.18.0", features = ["v1_25"] }
23+
k8s-openapi = { version = "0.18.0", features = ["v1_25", "schemars"] }
2324
kube = { version = "0.83.0", features = ["runtime", "derive"] }
2425
libc = "^0.2"
2526
liboverdrop = "0.1.0"
@@ -29,7 +30,7 @@ openssl = "^0.10"
2930
nix = { version = "0.27", features = ["ioctl"] }
3031
regex = "1.7.1"
3132
rustix = { "version" = "0.38", features = ["thread", "fs", "system", "process"] }
32-
schemars = "0.8.6"
33+
schemars = { version = "0.8.6", features = ["chrono"] }
3334
serde = { features = ["derive"], version = "1.0.125" }
3435
serde_json = "1.0.64"
3536
serde_yaml = "0.9.17"

lib/src/spec.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! The definition for host system state.
22
3+
use k8s_openapi::apimachinery::pkg::apis::meta::v1 as k8smeta;
34
use kube::CustomResource;
45
use schemars::JsonSchema;
56
use serde::{Deserialize, Serialize};
@@ -54,6 +55,10 @@ pub struct ImageReference {
5455
pub struct ImageStatus {
5556
/// The currently booted image
5657
pub image: ImageReference,
58+
/// The version string, if any
59+
pub version: Option<String>,
60+
/// The build timestamp, if any
61+
pub timestamp: Option<k8smeta::Time>,
5762
/// The digest of the fetched image (e.g. sha256:a0...);
5863
pub image_digest: String,
5964
}

lib/src/status.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ use std::collections::VecDeque;
33
use crate::spec::{BootEntry, Host, HostSpec, HostStatus, ImageStatus};
44
use crate::spec::{ImageReference, ImageSignature};
55
use anyhow::{Context, Result};
6+
use k8s_openapi::apimachinery::pkg::apis::meta::v1 as k8smeta;
67
use ostree::glib;
78
use ostree_container::OstreeImageReference;
89
use ostree_ext::container as ostree_container;
910
use ostree_ext::keyfileext::KeyFileExt;
11+
use ostree_ext::oci_spec;
1012
use ostree_ext::ostree;
1113
use ostree_ext::sysroot::SysrootLock;
1214

@@ -87,6 +89,22 @@ pub(crate) struct Deployments {
8789
pub(crate) other: VecDeque<ostree::Deployment>,
8890
}
8991

92+
fn try_deserialize_timestamp(t: &str) -> Option<k8smeta::Time> {
93+
match chrono::DateTime::parse_from_rfc3339(t).context("Parsing timestamp") {
94+
Ok(t) => Some(k8smeta::Time(t.with_timezone(&chrono::Utc))),
95+
Err(e) => {
96+
tracing::warn!("Invalid timestamp in image: {:#}", e);
97+
None
98+
}
99+
}
100+
}
101+
102+
pub(crate) fn labels_of_config(
103+
config: &oci_spec::image::ImageConfiguration,
104+
) -> Option<&std::collections::HashMap<String, String>> {
105+
config.config().as_ref().and_then(|c| c.labels().as_ref())
106+
}
107+
90108
fn boot_entry_from_deployment(
91109
sysroot: &SysrootLock,
92110
deployment: &ostree::Deployment,
@@ -98,9 +116,23 @@ fn boot_entry_from_deployment(
98116
let csum = deployment.csum();
99117
let incompatible = crate::utils::origin_has_rpmostree_stuff(origin);
100118
let imgstate = ostree_container::store::query_image_commit(repo, &csum)?;
119+
let config = imgstate.configuration.as_ref();
120+
let labels = config.and_then(labels_of_config);
121+
let timestamp = labels
122+
.and_then(|l| {
123+
l.get(oci_spec::image::ANNOTATION_CREATED)
124+
.map(|s| s.as_str())
125+
})
126+
.and_then(try_deserialize_timestamp);
127+
128+
let version = config
129+
.and_then(ostree_container::version_for_config)
130+
.map(ToOwned::to_owned);
101131
(
102132
Some(ImageStatus {
103133
image,
134+
version,
135+
timestamp,
104136
image_digest: imgstate.manifest_digest,
105137
}),
106138
incompatible,

0 commit comments

Comments
 (0)