@@ -14,13 +14,17 @@ use k8s_openapi::api::core::v1::{Secret, SecretVolumeSource, Volume, VolumeMount
1414use k8s_openapi:: apimachinery:: pkg:: apis:: meta:: v1:: { Condition , Time } ;
1515use k8s_openapi:: jiff:: Timestamp ;
1616use kube:: Resource ;
17+ use kube:: api:: Patch ;
1718use kube:: runtime:: reflector:: { self , Store } ;
1819use kube:: runtime:: watcher:: watcher;
1920use kube:: { Api , Client , runtime:: controller:: Action } ;
2021use log:: { info, warn} ;
22+ use serde:: Serialize ;
2123use std:: fmt:: { Debug , Display } ;
2224use std:: { sync:: Arc , time:: Duration } ;
2325use 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
2630pub 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+
34116pub 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 ) )
0 commit comments