Skip to content

Commit 69932a0

Browse files
committed
Move status functionality out of lib
no longer needed, makes lib/ slimmer Signed-off-by: Jakob Naucke <jnaucke@redhat.com> Assisted-by: Opus 4.6
1 parent 50244a2 commit 69932a0

6 files changed

Lines changed: 102 additions & 98 deletions

File tree

lib/src/lib.rs

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ pub mod reference_values;
1010
mod kopium;
1111
#[allow(clippy::all)]
1212
mod vendor_kopium;
13-
use k8s_openapi::jiff::Timestamp;
1413
pub use kopium::approvedimages::*;
1514
pub use kopium::attestationkeys::*;
1615
pub use kopium::ingresses as openshift_ingresses;
@@ -26,88 +25,9 @@ pub use vendor_kopium::virtualmachineinstances;
2625
pub use vendor_kopium::virtualmachines;
2726

2827
use anyhow::{Context, Result, anyhow};
29-
use conditions::*;
30-
use k8s_openapi::apimachinery::pkg::apis::meta::v1::{Condition, OwnerReference, Time};
28+
use k8s_openapi::apimachinery::pkg::apis::meta::v1::OwnerReference;
3129
use kube::{Api, Client, Resource};
3230

33-
#[macro_export]
34-
macro_rules! update_status {
35-
($api:ident, $name:expr, $status:expr) => {{
36-
let patch = kube::api::Patch::Merge(serde_json::json!({"status": $status}));
37-
$api.patch_status($name, &Default::default(), &patch).await
38-
.map_err(Into::<anyhow::Error>::into)
39-
}}
40-
}
41-
42-
pub fn condition_status(status: bool) -> String {
43-
match status {
44-
true => "True".to_string(),
45-
false => "False".to_string(),
46-
}
47-
}
48-
49-
pub trait Conditions {
50-
fn conditions(&self) -> &Option<Vec<Condition>>;
51-
}
52-
53-
impl Conditions for TrustedExecutionClusterStatus {
54-
fn conditions(&self) -> &Option<Vec<Condition>> {
55-
&self.conditions
56-
}
57-
}
58-
59-
impl Conditions for AttestationKeyStatus {
60-
fn conditions(&self) -> &Option<Vec<Condition>> {
61-
&self.conditions
62-
}
63-
}
64-
65-
impl Conditions for ApprovedImageStatus {
66-
fn conditions(&self) -> &Option<Vec<Condition>> {
67-
&self.conditions
68-
}
69-
}
70-
71-
pub fn transition_time<S: Conditions>(
72-
existing_status: &Option<S>,
73-
type_: &str,
74-
new_status: &str,
75-
) -> Time {
76-
let get = |s: &S| s.conditions().clone();
77-
let conditions = existing_status.as_ref().and_then(get);
78-
let find = |c: &Condition| type_ == c.type_ && new_status == c.status;
79-
let existing = conditions.and_then(|cs| cs.into_iter().find(find));
80-
let time = existing.map(|c| c.last_transition_time);
81-
time.unwrap_or(Time(Timestamp::now()))
82-
}
83-
84-
pub fn committed_condition(
85-
reason: &str,
86-
generation: Option<i64>,
87-
existing_status: &Option<ApprovedImageStatus>,
88-
) -> Condition {
89-
let status = condition_status(reason == COMMITTED_REASON);
90-
let type_ = COMMITTED_CONDITION;
91-
Condition {
92-
type_: type_.to_string(),
93-
reason: reason.to_string(),
94-
message: match reason {
95-
NOT_COMMITTED_REASON_COMPUTING => "Computation is ongoing. Check jobs for progress.",
96-
NOT_COMMITTED_REASON_NO_DIGEST => {
97-
"Image did not specify a digest. \
98-
Only images with a digest are supported to avoid ambiguity."
99-
}
100-
NOT_COMMITTED_REASON_PENDING => "Pod is pending, check pods for details",
101-
NOT_COMMITTED_REASON_FAILED => "Computation failed, check operator log for details",
102-
_ => "",
103-
}
104-
.to_string(),
105-
last_transition_time: transition_time(existing_status, type_, &status),
106-
status,
107-
observed_generation: generation,
108-
}
109-
}
110-
11131
/// Generate an OwnerReference for any Kubernetes resource
11232
pub fn generate_owner_reference<T: Resource<DynamicType = ()>>(
11333
object: &T,

operator/src/attestation_key_register.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@ use std::{collections::BTreeMap, sync::Arc, time::Duration};
3131

3232
use trusted_cluster_operator_lib::conditions::ATTESTATION_KEY_MACHINE_APPROVE;
3333
use trusted_cluster_operator_lib::endpoints::*;
34-
use trusted_cluster_operator_lib::{AttestationKey, AttestationKeyStatus, Machine, update_status};
34+
use trusted_cluster_operator_lib::{AttestationKey, AttestationKeyStatus, Machine};
3535

3636
use crate::conditions::attestation_key_approved_condition;
3737
use crate::trustee;
38-
use operator::{
39-
ControllerError, TLS_DIR, controller_error_policy, create_or_info_if_exists, read_certificate,
40-
upsert_condition,
41-
};
38+
use operator::{ControllerError, TLS_DIR, controller_error_policy};
39+
use operator::{create_or_info_if_exists, read_certificate, update_status, upsert_condition};
4240

4341
/// Shared context for the three attestation-key controllers.
4442
/// Stores give local cache access to avoid repeated API-server reads.
@@ -243,7 +241,7 @@ async fn approve_ak(ak: &AttestationKey, machine: &Machine, ctx: &AkContextData)
243241

244242
if changed {
245243
let status = AttestationKeyStatus { conditions };
246-
update_status!(aks, &name, status)?;
244+
update_status(&aks, &name, status).await?;
247245
info!("Approved attestation key {name}");
248246
}
249247

operator/src/conditions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
// SPDX-License-Identifier: MIT
44

55
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
6+
use operator::{condition_status, transition_time};
7+
use trusted_cluster_operator_lib::conditions::*;
68
use trusted_cluster_operator_lib::{AttestationKeyStatus, TrustedExecutionClusterStatus};
7-
use trusted_cluster_operator_lib::{condition_status, conditions::*, transition_time};
89

910
pub fn known_trustee_address_condition(
1011
known: bool,

operator/src/lib.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ use k8s_openapi::api::core::v1::{Secret, SecretVolumeSource, Volume, VolumeMount
1414
use k8s_openapi::apimachinery::pkg::apis::meta::v1::{Condition, Time};
1515
use k8s_openapi::jiff::Timestamp;
1616
use kube::Resource;
17+
use kube::api::Patch;
1718
use kube::runtime::reflector::{self, Store};
1819
use kube::runtime::watcher::watcher;
1920
use kube::{Api, Client, runtime::controller::Action};
2021
use log::{info, warn};
22+
use serde::Serialize;
2123
use std::fmt::{Debug, Display};
2224
use std::{sync::Arc, time::Duration};
2325
use tokio::time::timeout;
26+
use trusted_cluster_operator_lib::{ApprovedImageStatus, AttestationKeyStatus};
27+
use trusted_cluster_operator_lib::{TrustedExecutionClusterStatus, conditions::*};
2428

2529
// Re-export common functions from the lib
2630
pub use trusted_cluster_operator_lib::generate_owner_reference;
@@ -31,6 +35,84 @@ pub enum ControllerError {
3135
Anyhow(#[from] anyhow::Error),
3236
}
3337

38+
pub async fn update_status<S: Serialize, K>(api: &Api<K>, name: &str, status: S) -> Result<()>
39+
where
40+
K: Resource<DynamicType = ()> + serde::de::DeserializeOwned + Clone + Debug,
41+
{
42+
let patch = Patch::Merge(serde_json::json!({"status": status}));
43+
api.patch_status(name, &Default::default(), &patch).await?;
44+
Ok(())
45+
}
46+
47+
pub fn condition_status(status: bool) -> String {
48+
match status {
49+
true => "True".to_string(),
50+
false => "False".to_string(),
51+
}
52+
}
53+
54+
pub trait Conditions {
55+
fn conditions(&self) -> &Option<Vec<Condition>>;
56+
}
57+
58+
impl Conditions for TrustedExecutionClusterStatus {
59+
fn conditions(&self) -> &Option<Vec<Condition>> {
60+
&self.conditions
61+
}
62+
}
63+
64+
impl Conditions for AttestationKeyStatus {
65+
fn conditions(&self) -> &Option<Vec<Condition>> {
66+
&self.conditions
67+
}
68+
}
69+
70+
impl Conditions for ApprovedImageStatus {
71+
fn conditions(&self) -> &Option<Vec<Condition>> {
72+
&self.conditions
73+
}
74+
}
75+
76+
pub fn transition_time<S: Conditions>(
77+
existing_status: &Option<S>,
78+
type_: &str,
79+
new_status: &str,
80+
) -> Time {
81+
let get = |s: &S| s.conditions().clone();
82+
let conditions = existing_status.as_ref().and_then(get);
83+
let find = |c: &Condition| type_ == c.type_ && new_status == c.status;
84+
let existing = conditions.and_then(|cs| cs.into_iter().find(find));
85+
let time = existing.map(|c| c.last_transition_time);
86+
time.unwrap_or(Time(Timestamp::now()))
87+
}
88+
89+
pub fn committed_condition(
90+
reason: &str,
91+
generation: Option<i64>,
92+
existing_status: &Option<ApprovedImageStatus>,
93+
) -> Condition {
94+
let status = condition_status(reason == COMMITTED_REASON);
95+
let type_ = COMMITTED_CONDITION;
96+
Condition {
97+
type_: type_.to_string(),
98+
reason: reason.to_string(),
99+
message: match reason {
100+
NOT_COMMITTED_REASON_COMPUTING => "Computation is ongoing. Check jobs for progress.",
101+
NOT_COMMITTED_REASON_NO_DIGEST => {
102+
"Image did not specify a digest. \
103+
Only images with a digest are supported to avoid ambiguity."
104+
}
105+
NOT_COMMITTED_REASON_PENDING => "Pod is pending, check pods for details",
106+
NOT_COMMITTED_REASON_FAILED => "Computation failed, check operator log for details",
107+
_ => "",
108+
}
109+
.to_string(),
110+
last_transition_time: transition_time(existing_status, type_, &status),
111+
status,
112+
observed_generation: generation,
113+
}
114+
}
115+
34116
pub fn controller_error_policy<R, E: Display, C>(_obj: Arc<R>, error: &E, _ctx: Arc<C>) -> Action {
35117
log::error!("{error}");
36118
Action::requeue(Duration::from_secs(60))

operator/src/main.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use kube::runtime::watcher;
1717
use kube::{Api, Client};
1818
use log::{error, info, warn};
1919

20-
use operator::{generate_owner_reference, upsert_condition};
20+
use operator::{generate_owner_reference, update_status, upsert_condition};
2121
use trusted_cluster_operator_lib::{TrustedExecutionCluster, TrustedExecutionClusterStatus};
22-
use trusted_cluster_operator_lib::{conditions::*, images::*, update_status};
22+
use trusted_cluster_operator_lib::{conditions::*, images::*};
2323

2424
mod attestation_key_register;
2525
mod conditions;
@@ -96,8 +96,9 @@ async fn reconcile(
9696
let uninstall_condition =
9797
installed_condition(uninstalling_reason, generation, existing_status);
9898
let changed = upsert_condition(&mut conditions, uninstall_condition);
99+
let status = TrustedExecutionClusterStatus { conditions };
99100
if changed {
100-
update_status!(clusters, name, TrustedExecutionClusterStatus { conditions })?;
101+
update_status(&clusters, name, status).await?;
101102
}
102103
return Ok(Action::await_change());
103104
}
@@ -115,8 +116,9 @@ async fn reconcile(
115116
let non_unique_condition =
116117
installed_condition(NOT_INSTALLED_REASON_NON_UNIQUE, generation, existing_status);
117118
let changed = upsert_condition(&mut conditions, non_unique_condition);
119+
let status = TrustedExecutionClusterStatus { conditions };
118120
if changed {
119-
update_status!(clusters, name, TrustedExecutionClusterStatus { conditions })?;
121+
update_status(&clusters, name, status).await?;
120122
}
121123
return Ok(Action::requeue(Duration::from_secs(60)));
122124
}
@@ -129,7 +131,7 @@ async fn reconcile(
129131
let status = TrustedExecutionClusterStatus {
130132
conditions: conditions.clone(),
131133
};
132-
update_status!(clusters, name, status)?;
134+
update_status(&clusters, name, status).await?;
133135
}
134136

135137
install_trustee_configuration(kube_client.clone(), &cluster).await?;
@@ -141,7 +143,7 @@ async fn reconcile(
141143
let changed = upsert_condition(&mut conditions, installed_condition);
142144
if changed {
143145
let status = TrustedExecutionClusterStatus { conditions };
144-
update_status!(clusters, name, status)?;
146+
update_status(&clusters, name, status).await?;
145147
}
146148
Ok(Action::await_change())
147149
}

operator/src/reference_values.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use std::{collections::BTreeMap, sync::Arc, time::Duration};
3232

3333
use crate::COMPONENT_VERSION;
3434
use crate::trustee::{self, get_image_pcrs};
35-
use operator::{ControllerError, upsert_condition};
36-
use operator::{controller_error_policy, controller_info, create_or_info_if_exists};
35+
use operator::{ControllerError, committed_condition, upsert_condition};
36+
use operator::{controller_error_policy, controller_info, create_or_info_if_exists, update_status};
3737
use trusted_cluster_operator_lib::{conditions::*, reference_values::*, *};
3838

3939
const JOB_LABEL_KEY: &str = "kind";
@@ -135,7 +135,7 @@ async fn job_reconcile(job: Arc<Job>, client: Arc<Client>) -> Result<Action, Con
135135
let committed = committed_condition(INSTALLED_REASON, image.metadata.generation, &None);
136136
let conditions = Some(vec![committed]);
137137
let image_status = ApprovedImageStatus { conditions };
138-
update_status!(approved_images, &resource_name, image_status)?;
138+
update_status(&approved_images, &resource_name, image_status).await?;
139139

140140
let jobs: Api<Job> = Api::default_namespaced(kube_client.clone());
141141
// Foreground deletion: Delete the pod too
@@ -318,7 +318,8 @@ async fn image_add_reconcile(
318318
let changed = upsert_condition(&mut conditions, committed);
319319
if changed {
320320
let images: Api<ApprovedImage> = Api::default_namespaced(client);
321-
update_status!(images, &name, ApprovedImageStatus { conditions })
321+
update_status(&images, &name, ApprovedImageStatus { conditions })
322+
.await
322323
.map_err(|e| finalizer::Error::<ControllerError>::ApplyFailed(e.into()))?;
323324
}
324325
Ok(action)

0 commit comments

Comments
 (0)