Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ All notable changes to this project will be documented in this file.
- Set `maxSurge=1` and `maxUnavailable=0` on the OPA DaemonSet rolling update strategy to eliminate
availability gaps during rolling updates ([#819]).
- Document Helm deployed RBAC permissions and remove unnecessary permissions ([#820]).
- Internal operator refactoring: introduce dereference() and validate() steps in the reconciler ([#836]).

[#818]: https://github.com/stackabletech/opa-operator/pull/818
[#819]: https://github.com/stackabletech/opa-operator/pull/819
[#820]: https://github.com/stackabletech/opa-operator/pull/820
[#830]: https://github.com/stackabletech/opa-operator/pull/830
[#831]: https://github.com/stackabletech/opa-operator/pull/831
[#836]: https://github.com/stackabletech/opa-operator/pull/836

## [26.3.0] - 2026-03-16

Expand Down
18 changes: 9 additions & 9 deletions Cargo.nix

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

18 changes: 9 additions & 9 deletions crate-hashes.json

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

98 changes: 35 additions & 63 deletions rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use stackable_operator::{
cli::OperatorEnvironmentOptions,
cluster_resources::{ClusterResourceApplyStrategy, ClusterResources},
commons::{
product_image_selection::{self, ResolvedProductImage},
product_image_selection::ResolvedProductImage,
rbac::build_rbac_resources,
secret_class::{
SecretClassVolume, SecretClassVolumeProvisionParts, SecretClassVolumeScope,
Expand Down Expand Up @@ -54,7 +54,6 @@ use stackable_operator::{
kvp::{LabelError, Labels, ObjectLabels},
logging::controller::ReconcilerError,
memory::{BinaryMultiple, MemoryQuantity},
product_config_utils::{transform_all_roles_to_config, validate_all_roles_and_groups_config},
product_logging::{
self,
framework::{
Expand Down Expand Up @@ -89,6 +88,9 @@ use crate::{
},
};

mod dereference;
mod validate;

pub const OPA_CONTROLLER_NAME: &str = "opacluster";
pub const OPA_FULL_CONTROLLER_NAME: &str = concatcp!(OPA_CONTROLLER_NAME, '.', OPERATOR_NAME);

Expand Down Expand Up @@ -230,11 +232,6 @@ pub enum Error {
source: stackable_operator::client::Error,
},

#[snafu(display("invalid product config"))]
InvalidProductConfig {
source: stackable_operator::product_config_utils::Error,
},

#[snafu(display("object is missing metadata to build owner reference"))]
ObjectMissingMetadataForOwnerRef {
source: stackable_operator::builder::meta::Error,
Expand All @@ -248,11 +245,6 @@ pub enum Error {
source: stackable_operator::cluster_resources::Error,
},

#[snafu(display("failed to transform configs"))]
ProductConfigTransform {
source: stackable_operator::product_config_utils::Error,
},

#[snafu(display("failed to resolve and merge config for role and role group"))]
FailedToResolveConfig { source: crate::crd::Error },

Expand Down Expand Up @@ -332,14 +324,15 @@ pub enum Error {
source: builder::pod::container::Error,
},

#[snafu(display("failed to resolve product image"))]
ResolveProductImage {
source: product_image_selection::Error,
},

#[snafu(display("failed to build service"))]
BuildService { source: service::Error },

#[snafu(display("failed to dereference resources"))]
Dereference { source: dereference::Error },

#[snafu(display("failed to validate cluster"))]
ValidateCluster { source: validate::Error },

#[snafu(display("failed to build TLS volume"))]
TlsVolumeBuild {
source: builder::pod::volume::SecretOperatorVolumeSourceBuilderError,
Expand Down Expand Up @@ -448,15 +441,21 @@ pub async fn reconcile_opa(
let opa_ref = ObjectRef::from_obj(opa);

let client = &ctx.client;
let resolved_product_image = opa
.spec
.image
.resolve(
CONTAINER_IMAGE_BASE_NAME,
&ctx.operator_environment.image_repository,
crate::built_info::PKG_VERSION,
)
.context(ResolveProductImageSnafu)?;

// dereference (client required)
let dereferenced_objects = dereference::dereference(client, opa)
Comment thread
adwk67 marked this conversation as resolved.
Outdated
.await
.context(DereferenceSnafu)?;

// validate (no client required)
let validated = validate::validate(
opa,
&dereferenced_objects,
&ctx.operator_environment,
&ctx.product_config,
)
.context(ValidateClusterSnafu)?;

let opa_role = OpaRole::Server;

let mut cluster_resources = ClusterResources::new(
Expand All @@ -469,36 +468,14 @@ pub async fn reconcile_opa(
)
.context(FailedToCreateClusterResourcesSnafu)?;

let validated_config = validate_all_roles_and_groups_config(
&resolved_product_image.product_version,
&transform_all_roles_to_config(
opa,
&[(
opa_role.to_string(),
(
vec![
PropertyNameKind::File(CONFIG_FILE.to_string()),
PropertyNameKind::Env,
PropertyNameKind::Cli,
],
opa.spec.servers.clone(),
),
)]
.into(),
)
.context(ProductConfigTransformSnafu)?,
&ctx.product_config,
false,
false,
)
.context(InvalidProductConfigSnafu)?;
let role_server_config = validated_config
let role_server_config = validated
.validated_role_config
.get(&opa_role.to_string())
.map(Cow::Borrowed)
.unwrap_or_default();

let server_role_service =
build_server_role_service(opa, &resolved_product_image).context(BuildServiceSnafu)?;
build_server_role_service(opa, &validated.image).context(BuildServiceSnafu)?;
// required for discovery config map later
let server_role_service = cluster_resources
.add(client, server_role_service)
Expand Down Expand Up @@ -534,20 +511,15 @@ pub async fn reconcile_opa(
.merged_config(&opa_role, &rolegroup)
.context(FailedToResolveConfigSnafu)?;

let rg_configmap = build_server_rolegroup_config_map(
opa,
&resolved_product_image,
&rolegroup,
&merged_config,
)?;
let rg_service = build_rolegroup_headless_service(opa, &resolved_product_image, &rolegroup)
let rg_configmap =
build_server_rolegroup_config_map(opa, &validated.image, &rolegroup, &merged_config)?;
let rg_service = build_rolegroup_headless_service(opa, &validated.image, &rolegroup)
.context(BuildServiceSnafu)?;
let rg_metrics_service = build_rolegroup_metrics_service(opa, &validated.image, &rolegroup)
.context(BuildServiceSnafu)?;
let rg_metrics_service =
build_rolegroup_metrics_service(opa, &resolved_product_image, &rolegroup)
.context(BuildServiceSnafu)?;
let rg_daemonset = build_server_rolegroup_daemonset(
opa,
&resolved_product_image,
&validated.image,
&opa_role,
&rolegroup,
rolegroup_config,
Expand Down Expand Up @@ -610,7 +582,7 @@ pub async fn reconcile_opa(
for discovery_cm in build_discovery_configmaps(
opa,
opa,
&resolved_product_image,
&validated.image,
&server_role_service,
&client.kubernetes_cluster_info,
)
Expand Down
27 changes: 27 additions & 0 deletions rust/operator-binary/src/controller/dereference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! The dereference step in the OpaCluster controller
//!
//! Fetches all Kubernetes objects referenced by the OpaCluster spec and returns them in
//! [`DereferencedObjects`]. This is currently scaffolding — no objects are dereferenced yet.
//! Follow-up work might move existing inline lookups (e.g. the `user_info_fetcher` Secrets and
Comment thread
adwk67 marked this conversation as resolved.
Outdated
//! SecretClasses) through here.

use snafu::Snafu;
use stackable_operator::client::Client;

use crate::crd::v1alpha2;

#[derive(Snafu, Debug)]
pub enum Error {}

type Result<T, E = Error> = std::result::Result<T, E>;

/// Kubernetes objects referenced from the OpaCluster spec, already fetched.
pub struct DereferencedObjects {}

/// Fetches all Kubernetes objects referenced from the [`v1alpha2::OpaCluster`] spec.
pub async fn dereference(
_client: &Client,
_opa: &v1alpha2::OpaCluster,
) -> Result<DereferencedObjects> {
Ok(DereferencedObjects {})
}
Loading
Loading