Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/stackable-operator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.

### Changed

- Update the end-of-support warning message ([#1103])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally wouldn't add a new changelog entry, but just add this PR number to Add end-of-support checker.
EOS was never released, this change might confuse users, as they will not see the change.
Not blocking this PR though

- BREAKING: `ProductOperatorRun` was renamed to `RunArguments` ([#1096]).
- BREAKING: The `disable_crd_maintenance` field was moved from `RunArguments` into `MaintenanceOptions`.
The CLI interface is unchanged ([#1096]).
Expand All @@ -26,6 +27,7 @@ All notable changes to this project will be documented in this file.
[#1096]: https://github.com/stackabletech/operator-rs/pull/1096
[#1098]: https://github.com/stackabletech/operator-rs/pull/1098
[#1101]: https://github.com/stackabletech/operator-rs/pull/1101
[#1103]: https://github.com/stackabletech/operator-rs/pull/1103

## [0.98.0] - 2025-09-22

Expand Down
2 changes: 1 addition & 1 deletion crates/stackable-operator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ webhook = ["dep:stackable-webhook"]
[dependencies]
stackable-certs = { path = "../stackable-certs", optional = true }
stackable-operator-derive = { path = "../stackable-operator-derive" }
stackable-shared = { path = "../stackable-shared" }
stackable-shared = { path = "../stackable-shared", features = ["chrono", "time"]}
stackable-telemetry = { path = "../stackable-telemetry", optional = true, features = ["clap"] }
stackable-versioned = { path = "../stackable-versioned", optional = true }
stackable-webhook = { path = "../stackable-webhook", optional = true }
Expand Down
42 changes: 22 additions & 20 deletions crates/stackable-operator/src/eos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ pub enum Error {
}

pub struct EndOfSupportChecker {
datetime: DateTime<Utc>,
built_datetime: DateTime<Utc>,
eos_datetime: DateTime<Utc>,
interval: Duration,
disabled: bool,
}
Expand All @@ -90,7 +91,7 @@ impl EndOfSupportChecker {

// Parse the built-time from the RFC2822-encoded string when this is compiled as a release
// build. If this is a debug/dev build, use the current datetime instead.
let mut datetime = if cfg!(debug_assertions) {
let built_datetime = if cfg!(debug_assertions) {
Utc::now()
} else {
DateTime::parse_from_rfc2822(built_time)
Expand All @@ -99,10 +100,11 @@ impl EndOfSupportChecker {
};

// Add the support duration to the built date. This marks the end-of-support date.
datetime += *support_duration;
let eos_datetime = built_datetime + *support_duration;

Ok(Self {
datetime,
built_datetime,
eos_datetime,
interval,
disabled,
})
Expand All @@ -125,37 +127,37 @@ impl EndOfSupportChecker {
// TODO: Add way to stop from the outside
// The first tick ticks immediately.
interval.tick().await;
let now = Utc::now();

tracing::info_span!(
"checking end-of-support state",
eos.interval = self.interval.to_string(),
eos.now = now.to_rfc3339(),
);

// Continue the loop and wait for the next tick to run the check again.
if !self.is_eos() {
if now <= self.eos_datetime {
continue;
}

self.emit_warning();
self.emit_warning(now);
}
}

/// Emits the end-of-support warning.
#[instrument(level = Level::DEBUG, skip(self))]
fn emit_warning(&self) {
fn emit_warning(&self, now: DateTime<Utc>) {
let built_datetime = self.built_datetime.to_rfc3339();
let build_age = Duration::try_from(now - self.built_datetime)
.expect("time delta of now and built datetime must not be less than 0")
.to_string();

tracing::warn!(
eos.date = self.datetime.to_rfc3339(),
"the operator reached end-of-support"
eos.built.datetime = built_datetime,
eos.build.age = build_age,
Comment on lines +156 to +157
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is built vs build intentional?

"This operator version was built on {built_datetime} ({build_age} days ago) and may has reached end-of-support. \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"This operator version was built on {built_datetime} ({build_age} days ago) and may has reached end-of-support. \
"This operator version was built on {built_datetime} ({build_age} days ago) and may have reached end-of-support. \

Running unsupported versions may contain security vulnerabilities. \
Please upgrade to a supported version as soon as possible."
);
}

/// Returns if the operator is considered as end-of-support based on the built-time and the
/// support duration.
#[instrument(level = Level::DEBUG, skip(self), fields(eos.now))]
fn is_eos(&self) -> bool {
let now = Utc::now();

tracing::Span::current().record("eos.now", now.to_rfc3339());

now > self.datetime
}
}
8 changes: 8 additions & 0 deletions crates/stackable-shared/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file.

## Unreleased

### Added

- Add conversion implementations between `Duration` and `chrono::TimeDelta` ([#1103]).

[#1103]: https://github.com/stackabletech/operator-rs/pull/1103

## [0.0.2] - 2025-08-21

### Added
Expand Down
4 changes: 3 additions & 1 deletion crates/stackable-shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ edition.workspace = true
repository.workspace = true

[features]
full = ["time"]
full = ["chrono", "time"]
default = ["time"]

chrono = ["dep:chrono"]
time = ["dep:time"]

[dependencies]
chrono = { workspace = true, optional = true }
k8s-openapi.workspace = true
kube.workspace = true
schemars.workspace = true
Expand Down
18 changes: 18 additions & 0 deletions crates/stackable-shared/src/time/chrono_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use crate::time::Duration;

impl TryFrom<chrono::TimeDelta> for Duration {
type Error = chrono::OutOfRangeError;

fn try_from(value: chrono::TimeDelta) -> Result<Self, Self::Error> {
let std_duration = value.to_std()?;
Ok(Self::from(std_duration))
}
}

impl TryFrom<Duration> for chrono::TimeDelta {
type Error = chrono::OutOfRangeError;

fn try_from(value: Duration) -> Result<Self, Self::Error> {
chrono::TimeDelta::from_std(value.into())
}
}
3 changes: 3 additions & 0 deletions crates/stackable-shared/src/time/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
mod duration;
mod serde_impl;

#[cfg(feature = "chrono")]
mod chrono_impl;

#[cfg(feature = "time")]
mod time_impl;

Expand Down
Loading