Skip to content

Commit fe094af

Browse files
committed
fix: move compute_proxy_hosts to validate as no async call required
1 parent e8bee8b commit fe094af

3 files changed

Lines changed: 63 additions & 59 deletions

File tree

rust/operator-binary/src/controller.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,20 +369,21 @@ pub async fn reconcile_nifi(
369369
.await
370370
.context(DereferenceSnafu)?;
371371

372-
// validate (no client required)
372+
// validate (no Kubernetes API calls required)
373373
let validated = validate::validate(
374374
nifi,
375375
&dereferenced_objects,
376376
&ctx.operator_environment,
377377
&ctx.product_config,
378+
&client.kubernetes_cluster_info,
378379
)
379380
.context(ValidateClusterSnafu)?;
380381

381382
let resolved_product_image = validated.image;
382383
let authentication_config = validated.authentication_config;
383384
let authorization_config = validated.authorization_config;
384385
let validated_config = validated.validated_role_config;
385-
let proxy_hosts = dereferenced_objects.proxy_hosts;
386+
let proxy_hosts = validated.proxy_hosts;
386387

387388
tracing::info!("Checking for sensitive key configuration");
388389
check_or_generate_sensitive_key(client, nifi)

rust/operator-binary/src/controller/dereference.rs

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@
33
//! Fetches all Kubernetes objects referenced by the NifiCluster spec and returns
44
//! them in [`DereferencedObjects`].
55
6-
use std::collections::HashSet;
7-
86
use snafu::{OptionExt, ResultExt, Snafu};
97
use stackable_operator::client::Client;
108

119
use crate::{
12-
crd::{HTTPS_PORT, v1alpha1},
13-
reporting_task,
10+
crd::v1alpha1,
1411
security::{
1512
authentication::{self, DereferencedAuthenticationClasses},
1613
authorization::{self as authorization_mod, DereferencedAuthorization},
@@ -27,11 +24,6 @@ pub enum Error {
2724

2825
#[snafu(display("failed to dereference NiFi authorization config"))]
2926
DereferenceAuthorization { source: authorization_mod::Error },
30-
31-
#[snafu(display("failed to build reporting task service name"))]
32-
ReportingTask {
33-
source: crate::reporting_task::Error,
34-
},
3527
}
3628

3729
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -40,11 +32,6 @@ type Result<T, E = Error> = std::result::Result<T, E>;
4032
pub struct DereferencedObjects {
4133
pub authentication_classes: DereferencedAuthenticationClasses,
4234
pub authorization: DereferencedAuthorization,
43-
/// Comma-separated NiFi proxy hosts, or `"*"` if
44-
/// `spec.clusterConfig.hostHeaderCheck.allowAll` is set. Computed here so all remote
45-
/// lookups live in one place; previously this ran once per rolegroup inside the
46-
/// reconcile loop.
47-
pub proxy_hosts: String,
4835
}
4936

5037
/// Fetches all Kubernetes objects referenced from the [`v1alpha1::NifiCluster`] spec.
@@ -70,49 +57,8 @@ pub async fn dereference(
7057
.await
7158
.context(DereferenceAuthorizationSnafu)?;
7259

73-
let proxy_hosts = compute_proxy_hosts(client, nifi)?;
74-
7560
Ok(DereferencedObjects {
7661
authentication_classes,
7762
authorization,
78-
proxy_hosts,
7963
})
8064
}
81-
82-
fn compute_proxy_hosts(client: &Client, nifi: &v1alpha1::NifiCluster) -> Result<String> {
83-
let host_header_check = &nifi.spec.cluster_config.host_header_check;
84-
85-
if host_header_check.allow_all {
86-
tracing::info!(
87-
"spec.clusterConfig.hostHeaderCheck.allowAll is set to true. All proxy hosts will be allowed."
88-
);
89-
if !host_header_check.additional_allowed_hosts.is_empty() {
90-
tracing::info!(
91-
"spec.clusterConfig.hostHeaderCheck.additionalAllowedHosts is ignored and only '*' is added to the allow-list."
92-
)
93-
}
94-
return Ok("*".to_string());
95-
}
96-
97-
// Address and port are injected from the listener volume during the prepare container
98-
let mut proxy_hosts = HashSet::from([
99-
"${env:LISTENER_DEFAULT_ADDRESS}:${env:LISTENER_DEFAULT_PORT_HTTPS}".to_string(),
100-
]);
101-
proxy_hosts.extend(host_header_check.additional_allowed_hosts.iter().cloned());
102-
103-
// Reporting task only exists for NiFi 1.x
104-
if nifi.spec.image.product_version().starts_with("1.") {
105-
let reporting_task_service_name = reporting_task::build_reporting_task_fqdn_service_name(
106-
nifi,
107-
&client.kubernetes_cluster_info,
108-
)
109-
.context(ReportingTaskSnafu)?;
110-
111-
proxy_hosts.insert(format!("{reporting_task_service_name}:{HTTPS_PORT}"));
112-
}
113-
114-
let mut proxy_hosts = Vec::from_iter(proxy_hosts);
115-
proxy_hosts.sort();
116-
117-
Ok(proxy_hosts.join(","))
118-
}

rust/operator-binary/src/controller/validate.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
//! The validate step in the NifiCluster controller
22
//!
3-
//! Synchronously validates inputs that don't require a Kubernetes client. Produces
3+
//! Synchronously validates inputs that don't require Kubernetes API calls. Produces
44
//! [`ValidatedInputs`], consumed by the rest of `reconcile_nifi`.
55
6+
use std::collections::HashSet;
7+
68
use product_config::ProductConfigManager;
79
use snafu::{OptionExt, ResultExt, Snafu};
810
use stackable_operator::{
911
cli::OperatorEnvironmentOptions,
1012
commons::product_image_selection::{self, ResolvedProductImage},
1113
product_config_utils::ValidatedRoleConfigByPropertyKind,
14+
utils::cluster_info::KubernetesClusterInfo,
1215
};
1316
use strum::{EnumDiscriminants, IntoStaticStr};
1417

1518
use crate::{
1619
config::{self, validated_product_config},
1720
controller::dereference::DereferencedObjects,
18-
crd::v1alpha1,
21+
crd::{HTTPS_PORT, v1alpha1},
22+
reporting_task,
1923
security::{
2024
authentication::{self, NifiAuthenticationConfig},
2125
authorization::ResolvedNifiAuthorizationConfig,
@@ -42,6 +46,11 @@ pub enum Error {
4246
#[snafu(source(from(config::Error, Box::new)))]
4347
source: Box<config::Error>,
4448
},
49+
50+
#[snafu(display("failed to build reporting task service name"))]
51+
ReportingTask {
52+
source: crate::reporting_task::Error,
53+
},
4554
}
4655

4756
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -52,6 +61,11 @@ pub struct ValidatedInputs {
5261
pub authentication_config: NifiAuthenticationConfig,
5362
pub authorization_config: ResolvedNifiAuthorizationConfig,
5463
pub validated_role_config: ValidatedRoleConfigByPropertyKind,
64+
/// Comma-separated NiFi proxy hosts, or `"*"` if
65+
/// `spec.clusterConfig.hostHeaderCheck.allowAll` is set. Computed here so all derived
66+
/// inputs live in one place; previously this ran once per rolegroup inside the
67+
/// reconcile loop.
68+
pub proxy_hosts: String,
5569
}
5670

5771
/// Validates the cluster spec and the dereferenced inputs.
@@ -60,6 +74,7 @@ pub fn validate(
6074
dereferenced_objects: &DereferencedObjects,
6175
operator_environment: &OperatorEnvironmentOptions,
6276
product_config: &ProductConfigManager,
77+
cluster_info: &KubernetesClusterInfo,
6378
) -> Result<ValidatedInputs> {
6479
let image = nifi
6580
.spec
@@ -88,10 +103,52 @@ pub fn validate(
88103
)
89104
.context(ProductConfigLoadFailedSnafu)?;
90105

106+
let proxy_hosts = compute_proxy_hosts(nifi, cluster_info)?;
107+
91108
Ok(ValidatedInputs {
92109
image,
93110
authentication_config,
94111
authorization_config,
95112
validated_role_config,
113+
proxy_hosts,
96114
})
97115
}
116+
117+
fn compute_proxy_hosts(
118+
nifi: &v1alpha1::NifiCluster,
119+
cluster_info: &KubernetesClusterInfo,
120+
) -> Result<String> {
121+
let host_header_check = &nifi.spec.cluster_config.host_header_check;
122+
123+
if host_header_check.allow_all {
124+
tracing::info!(
125+
"spec.clusterConfig.hostHeaderCheck.allowAll is set to true. All proxy hosts will be allowed."
126+
);
127+
if !host_header_check.additional_allowed_hosts.is_empty() {
128+
tracing::info!(
129+
"spec.clusterConfig.hostHeaderCheck.additionalAllowedHosts is ignored and only '*' is added to the allow-list."
130+
)
131+
}
132+
return Ok("*".to_string());
133+
}
134+
135+
// Address and port are injected from the listener volume during the prepare container
136+
let mut proxy_hosts = HashSet::from([
137+
"${env:LISTENER_DEFAULT_ADDRESS}:${env:LISTENER_DEFAULT_PORT_HTTPS}".to_string(),
138+
]);
139+
proxy_hosts.extend(host_header_check.additional_allowed_hosts.iter().cloned());
140+
141+
// Reporting task only exists for NiFi 1.x
142+
if nifi.spec.image.product_version().starts_with("1.") {
143+
let reporting_task_service_name =
144+
reporting_task::build_reporting_task_fqdn_service_name(nifi, cluster_info)
145+
.context(ReportingTaskSnafu)?;
146+
147+
proxy_hosts.insert(format!("{reporting_task_service_name}:{HTTPS_PORT}"));
148+
}
149+
150+
let mut proxy_hosts = Vec::from_iter(proxy_hosts);
151+
proxy_hosts.sort();
152+
153+
Ok(proxy_hosts.join(","))
154+
}

0 commit comments

Comments
 (0)