Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

- Internal operator refactoring: introduce a build() step in the reconciler that
assembles all relevant Kubernetes resources before anything is applied ([#814]).
- The RBAC ServiceAccount and RoleBinding are now built with the operator-rs `v2::rbac`
functions and carry the full set of recommended labels ([#821]).

[#814]: https://github.com/stackabletech/airflow-operator/pull/814
[#821]: https://github.com/stackabletech/airflow-operator/pull/821

## [26.7.0] - 2026-07-21

Expand Down
20 changes: 10 additions & 10 deletions Cargo.lock

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

56 changes: 28 additions & 28 deletions Cargo.nix

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ tokio = { version = "1.52", features = ["full"] }
tracing = "0.1"

[patch."https://github.com/stackabletech/operator-rs.git"]
# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" }
stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feat/smooth-operator/build-rbac" }
# stackable-operator = { path = "../operator-rs/crates/stackable-operator" }
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.

62 changes: 17 additions & 45 deletions rust/operator-binary/src/airflow_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ use snafu::{ResultExt, Snafu};
use stackable_operator::{
cli::OperatorEnvironmentOptions,
cluster_resources::ClusterResourceApplyStrategy,
commons::{random_secret_creation, rbac::build_rbac_resources},
commons::random_secret_creation,
k8s_openapi::api::core::v1::EnvVar,
kube::{
ResourceExt,
core::{DeserializeGuard, error_boundary},
runtime::controller::Action,
},
kvp::LabelError,
logging::controller::ReconcilerError,
shared::time::Duration,
status::condition::{
Expand All @@ -30,7 +28,7 @@ use strum::{EnumDiscriminants, IntoStaticStr};
use crate::{
controller::{ValidatedCluster, build, controller_name, operator_name, product_name},
crd::{
APP_NAME, AirflowClusterStatus, OPERATOR_NAME,
AirflowClusterStatus, OPERATOR_NAME,
internal_secret::{
FERNET_KEY_SECRET_KEY, INTERNAL_SECRET_SECRET_KEY, JWT_SECRET_SECRET_KEY,
},
Expand Down Expand Up @@ -58,21 +56,6 @@ pub enum Error {
source: stackable_operator::cluster_resources::Error,
},

#[snafu(display("failed to patch service account"))]
ApplyServiceAccount {
source: stackable_operator::cluster_resources::Error,
},

#[snafu(display("failed to patch role binding: {source}"))]
ApplyRoleBinding {
source: stackable_operator::cluster_resources::Error,
},

#[snafu(display("failed to build RBAC objects"))]
BuildRBACObjects {
source: stackable_operator::commons::rbac::Error,
},

#[snafu(display("failed to build the Kubernetes resources"))]
BuildResources { source: build::Error },

Expand Down Expand Up @@ -101,9 +84,6 @@ pub enum Error {
source: crate::controller::validate::Error,
},

#[snafu(display("failed to build label"))]
BuildLabel { source: LabelError },

#[snafu(display("AirflowCluster object is invalid"))]
InvalidAirflowCluster {
source: error_boundary::InvalidObject,
Expand Down Expand Up @@ -159,33 +139,25 @@ pub async fn reconcile_airflow(
&airflow.spec.object_overrides,
);

let required_labels = cluster_resources
.get_required_labels()
.context(BuildLabelSnafu)?;

let (rbac_sa, rbac_rolebinding) =
build_rbac_resources(airflow, APP_NAME, required_labels).context(BuildRBACObjectsSnafu)?;

// The ServiceAccount name is deterministic on the built object, so the build step does not
// depend on the applied ServiceAccount.
let service_account_name = rbac_sa.name_any();

cluster_resources
.add(client, rbac_sa)
.await
.context(ApplyServiceAccountSnafu)?;
cluster_resources
.add(client, rbac_rolebinding)
.await
.context(ApplyRoleBindingSnafu)?;

let resources =
build::build(&validated_cluster, &service_account_name).context(BuildResourcesSnafu)?;
let resources = build::build(&validated_cluster).context(BuildResourcesSnafu)?;

let mut ss_cond_builder = StatefulSetConditionBuilder::default();

// Apply order is: StatefulSets last (a changed mounted ConfigMap/Secret
// must exist first, else Pods restart -- commons-operator#111).
// must exist first, else Pods restart -- commons-operator#111). The ServiceAccount comes
// first because the Pods reference it at creation time.
for service_account in resources.service_accounts {
cluster_resources
.add(client, service_account)
.await
.context(ApplyResourceSnafu)?;
}
for role_binding in resources.role_bindings {
cluster_resources
.add(client, role_binding)
.await
.context(ApplyResourceSnafu)?;
}
for service in resources.services {
cluster_resources
.add(client, service)
Expand Down
Loading
Loading