Skip to content

Commit 4c39924

Browse files
committed
Handle creation of ConfidentialClusters
Previous setup had a watcher on cocl objects, but did nothing with it and just assumed one would be present. Instead, run installations when =1 cocl is present. Signed-off-by: Jakob Naucke <jnaucke@redhat.com>
1 parent ce62c1b commit 4c39924

File tree

3 files changed

+49
-61
lines changed

3 files changed

+49
-61
lines changed

operator/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
// Use in other crates is not an intended purpose.
1010

1111
use kube::{Client, runtime::controller::Action};
12-
use std::{fmt::Display, sync::Arc, time::Duration};
12+
use log::info;
13+
use std::fmt::{Debug, Display};
14+
use std::{sync::Arc, time::Duration};
1315

1416
#[derive(Clone)]
1517
pub struct RvContextData {
@@ -30,6 +32,13 @@ pub fn controller_error_policy<R, E: Display, C>(_obj: Arc<R>, error: &E, _ctx:
3032
Action::requeue(Duration::from_secs(60))
3133
}
3234

35+
pub async fn controller_info<T: Debug, E: Debug>(res: Result<T, E>) {
36+
match res {
37+
Ok(o) => info!("reconciled {o:?}"),
38+
Err(e) => info!("reconcile failed: {e:?}"),
39+
}
40+
}
41+
3342
#[macro_export]
3443
macro_rules! info_if_exists {
3544
($result:ident, $resource_type:literal, $resource_name:expr) => {

operator/src/main.rs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,61 +6,51 @@
66
use std::sync::Arc;
77
use std::time::Duration;
88

9-
use anyhow::{Result, bail};
9+
use anyhow::Result;
1010
use env_logger::Env;
1111
use futures_util::StreamExt;
1212
use kube::runtime::{
1313
controller::{Action, Controller},
1414
watcher,
1515
};
16-
use kube::{Api, Client, api::ListParams};
17-
18-
use log::{error, info};
19-
use thiserror::Error;
16+
use kube::{Api, Client};
17+
use log::{error, info, warn};
2018

2119
use crds::ConfidentialCluster;
2220
mod reference_values;
2321
mod trustee;
2422

25-
#[derive(Debug, Error)]
26-
enum Error {}
27-
28-
#[derive(Clone)]
29-
struct ContextData {
30-
#[allow(dead_code)]
31-
client: Client,
32-
}
33-
3423
const BOOT_IMAGE: &str = "quay.io/fedora/fedora-coreos:42.20250705.3.0";
3524

36-
async fn list_confidential_clusters(client: Client) -> anyhow::Result<ConfidentialCluster> {
37-
info!(
38-
"Listing ConfidentialClusters in namespace '{}'",
39-
client.default_namespace()
40-
);
41-
let api: Api<ConfidentialCluster> = Api::default_namespaced(client.clone());
42-
let lp = ListParams::default();
43-
let list = api.list(&lp).await?;
44-
match list.items.len() {
45-
0 => bail!("No confidential cluster resource found"),
46-
1 => {
47-
let item = &list.items[0];
48-
info!(
49-
"Found ConfidentialCluster: {}",
50-
item.metadata.name.as_deref().unwrap_or("<no name>"),
51-
);
52-
Ok(item.clone())
53-
}
54-
_ => bail!("too many confidential cluster resources defined in the namespace"),
25+
async fn reconcile(
26+
cocl: Arc<ConfidentialCluster>,
27+
client: Arc<Client>,
28+
) -> Result<Action, operator::ControllerError> {
29+
let name = cocl.metadata.name.as_deref().unwrap_or("<no name>");
30+
if cocl.metadata.deletion_timestamp.is_some() {
31+
info!("Registered deletion of ConfidentialCluster {name}");
32+
return Ok(Action::await_change());
33+
}
34+
let kube_client = Arc::unwrap_or_clone(client);
35+
36+
let cocls: Api<ConfidentialCluster> = Api::default_namespaced(kube_client.clone());
37+
let list = cocls.list(&Default::default()).await;
38+
let cocl_list = list.map_err(Into::<anyhow::Error>::into)?;
39+
if cocl_list.items.len() > 1 {
40+
let namespace = kube_client.default_namespace();
41+
warn!(
42+
"More than one ConfidentialCluster found in namespace {namespace}. \
43+
cocl-operator does not support more than one ConfidentialCluster. Requeueing...",
44+
);
45+
return Ok(Action::requeue(Duration::from_secs(60)));
5546
}
56-
}
5747

58-
async fn reconcile(_g: Arc<ConfidentialCluster>, _ctx: Arc<ContextData>) -> Result<Action, Error> {
59-
Ok(Action::requeue(Duration::from_secs(300)))
48+
info!("Setting up ConfidentialCluster {name}");
49+
install_trustee_configuration(kube_client, &cocl).await?;
50+
Ok(Action::await_change())
6051
}
6152

62-
async fn install_trustee_configuration(client: Client) -> Result<()> {
63-
let cocl = list_confidential_clusters(client.clone()).await?;
53+
async fn install_trustee_configuration(client: Client, cocl: &ConfidentialCluster) -> Result<()> {
6454
let trustee_namespace = cocl.spec.trustee.namespace.clone();
6555

6656
match trustee::generate_kbs_auth_public_key(
@@ -99,7 +89,7 @@ async fn install_trustee_configuration(client: Client) -> Result<()> {
9989
let rv_ctx = operator::RvContextData {
10090
client: client.clone(),
10191
trustee_namespace: trustee_namespace.clone(),
102-
pcrs_compute_image: cocl.spec.pcrs_compute_image,
92+
pcrs_compute_image: cocl.spec.pcrs_compute_image.clone(),
10393
rv_map: cocl.spec.trustee.reference_values.clone(),
10494
};
10595
reference_values::launch_rv_job_controller(rv_ctx.clone()).await;
@@ -185,22 +175,14 @@ async fn install_trustee_configuration(client: Client) -> Result<()> {
185175
async fn main() -> Result<()> {
186176
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
187177

188-
let client = Client::try_default().await?;
189-
let context = Arc::new(ContextData {
190-
client: client.clone(),
191-
});
178+
let kube_client = Client::try_default().await?;
192179
info!("Confidential clusters operator",);
193-
let cl = Api::<ConfidentialCluster>::default_namespaced(client.clone());
180+
let cl = Api::<ConfidentialCluster>::default_namespaced(kube_client.clone());
194181

195-
tokio::spawn(install_trustee_configuration(client.clone()));
182+
let client = Arc::new(kube_client);
196183
Controller::new(cl, watcher::Config::default())
197-
.run::<_, ContextData>(reconcile, operator::controller_error_policy, context)
198-
.for_each(|res| async move {
199-
match res {
200-
Ok(o) => info!("reconciled {o:?}"),
201-
Err(e) => info!("reconcile failed: {e:?}"),
202-
}
203-
})
184+
.run::<_, Client>(reconcile, operator::controller_error_policy, client)
185+
.for_each(operator::controller_info)
204186
.await;
205187

206188
Ok(())

operator/src/reference_values.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ use serde::Deserialize;
2828
use std::{collections::BTreeMap, path::PathBuf, sync::Arc, time::Duration};
2929

3030
use crate::trustee::{self, get_image_pcrs};
31-
use operator::{ControllerError, RvContextData, controller_error_policy, info_if_exists};
31+
use operator::{
32+
ControllerError, RvContextData, controller_error_policy, controller_info, info_if_exists,
33+
};
3234
use rv_store::*;
3335

3436
const JOB_LABEL_KEY: &str = "kind";
@@ -165,7 +167,7 @@ async fn job_reconcile(job: Arc<Job>, ctx: Arc<RvContextData>) -> Result<Action,
165167
jobs.delete(name, &DeleteParams::default())
166168
.await
167169
.map_err(Into::<anyhow::Error>::into)?;
168-
trustee::recompute_reference_values(Arc::<RvContextData>::unwrap_or_clone(ctx)).await?;
170+
trustee::recompute_reference_values(Arc::unwrap_or_clone(ctx)).await?;
169171
Ok(Action::await_change())
170172
}
171173

@@ -178,12 +180,7 @@ pub async fn launch_rv_job_controller(ctx: RvContextData) {
178180
tokio::spawn(
179181
Controller::new(jobs, watcher)
180182
.run(job_reconcile, controller_error_policy, Arc::new(ctx))
181-
.for_each(|res| async move {
182-
match res {
183-
Ok(o) => info!("reconciled {o:?}"),
184-
Err(e) => info!("reconcile failed: {e:?}"),
185-
}
186-
}),
183+
.for_each(controller_info),
187184
);
188185
}
189186

0 commit comments

Comments
 (0)