Skip to content

Commit 62464b9

Browse files
sbernauerTechassi
andauthored
fix: Correctly migrate SECRET_KEY from 26.3 setups (#754)
* fix: Correctly migrate SECRET_KEY from 26.3 setups * changelog * Link to remove issue * Use serde(rename) * Improve changelog with migration note * Update rust/operator-binary/src/controller.rs Co-authored-by: Techassi <git@techassi.dev> * Add second TODO --------- Co-authored-by: Techassi <git@techassi.dev>
1 parent 3f3e1f9 commit 62464b9

19 files changed

Lines changed: 114 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
- Support setting `clientAuthenticationMethod` for OIDC authentication. The value is passed through to the Flask-AppBuilder config as `token_endpoint_auth_method` ([#719]).
1818
- BREAKING: Rename `EXPERIMENTAL_FILE_HEADER` and `EXPERIMENTAL_FILE_FOOTER` in `superset_config.py` for arbitrary Python code to `FILE_HEADER` and `FILE_FOOTER` ([#719], [#721]).
1919
- Use an internal Secret for the Superset `SECRET_KEY`.
20-
Going forward, the operator will automatically create the Secret in case it doesn't exist ([#722]).
21-
- BREAKING: The `.clusterConfig.credentialsSecret` field has been renamed to `.clusterConfig.credentialsSecretName` for consistency ([#722]).
20+
Going forward, the operator will automatically create the Secret in case it doesn't exist.
21+
If your `credentialsSecret` at the time of upgrading points at a Secret with `connection.secretKey`, we will automatically migrate your existing `SECRET_KEY` to avoid interruptions ([#722], [#754]).
2222
- BREAKING: Implement generic database connection.
2323
This means you need to replace your simple database connection string with a typed struct.
2424
This struct is consistent between different CRDs, so that you can easily copy/paste it between stacklets.
25-
More information can be found in the [Superset database documentation](https://docs.stackable.tech/home/nightly/superset/usage-guide/database-connections) for details ([#722]).
25+
More information can be found in the [Superset database documentation](https://docs.stackable.tech/home/nightly/superset/usage-guide/database-connections) for details ([#722], [#754]).
2626
- Internal operator refactoring: introduce dereference() and validate() steps in the reconciler ([#731]).
2727
- test: Bump vector-aggregator to 0.55.0, replace /graphql call with gRPC call ([#735]).
2828
- BREAKING: Removed product-config machinery. This is a breaking change in terms of configuration.
@@ -39,6 +39,7 @@
3939
[#735]: https://github.com/stackabletech/superset-operator/pull/735
4040
[#738]: https://github.com/stackabletech/superset-operator/pull/738
4141
[#751]: https://github.com/stackabletech/superset-operator/pull/751
42+
[#754]: https://github.com/stackabletech/superset-operator/pull/754
4243

4344
## [26.3.0] - 2026-03-16
4445

docs/modules/superset/examples/getting_started/superset.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ spec:
1515
image:
1616
productVersion: 6.1.0
1717
clusterConfig:
18-
credentialsSecretName: superset-admin-credentials
18+
credentialsSecret: superset-admin-credentials
1919
metadataDatabase:
2020
postgresql:
2121
host: superset-postgresql

extra/crds.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ spec:
10231023
and `stopped` will take no effect until `reconciliationPaused` is set to false or removed.
10241024
type: boolean
10251025
type: object
1026-
credentialsSecretName:
1026+
credentialsSecret:
10271027
description: |-
10281028
The name of the Secret object containing the admin user credentials.
10291029
Read the
@@ -1108,7 +1108,7 @@ spec:
11081108
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
11091109
type: string
11101110
required:
1111-
- credentialsSecretName
1111+
- credentialsSecret
11121112
- metadataDatabase
11131113
type: object
11141114
image:

rust/operator-binary/src/controller.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use snafu::{ResultExt, Snafu};
99
use stackable_operator::{
1010
builder::meta::ObjectMetaBuilder,
1111
cli::OperatorEnvironmentOptions,
12+
client::Client,
1213
cluster_resources::ClusterResourceApplyStrategy,
1314
commons::{
1415
affinity::StackableAffinity,
@@ -17,6 +18,7 @@ use stackable_operator::{
1718
rbac::build_rbac_resources,
1819
resources::{NoRuntimeLimits, Resources},
1920
},
21+
k8s_openapi::api::core::v1::Secret,
2022
kube::{
2123
Resource, ResourceExt,
2224
api::ObjectMeta,
@@ -48,6 +50,7 @@ use stackable_operator::{
4850
},
4951
};
5052
use strum::{EnumDiscriminants, IntoStaticStr};
53+
use tracing::instrument;
5154

5255
use crate::{
5356
OPERATOR_NAME,
@@ -467,6 +470,22 @@ pub enum Error {
467470
CreateSecretKeySecret {
468471
source: random_secret_creation::Error,
469472
},
473+
474+
#[snafu(display("failed to retrieve credentials secret {secret_name:?}"))]
475+
RetrieveCredentialsSecret {
476+
source: stackable_operator::client::Error,
477+
secret_name: String,
478+
},
479+
480+
#[snafu(display("object is missing metadata to build owner reference"))]
481+
ObjectMissingMetadataForOwnerRef {
482+
source: stackable_operator::builder::meta::Error,
483+
},
484+
485+
#[snafu(display("failed to create SECRET_KEY secret from migrated value"))]
486+
CreateRandomSecret {
487+
source: stackable_operator::client::Error,
488+
},
470489
}
471490

472491
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -534,6 +553,10 @@ pub async fn reconcile_superset(
534553
.await
535554
.context(ApplyRoleBindingSnafu)?;
536555

556+
// TODO: Can be removed after SDP 26.7 is released (it's only a migration from 26.3 - 26.7)
557+
// (don't forget about the snafu Error variants).
558+
// Removal is tracked in https://github.com/stackabletech/superset-operator/issues/755
559+
migrate_legacy_secret_key_secret_from_26_3(superset, &validated, client).await?;
537560
create_random_secret_if_not_exists(
538561
&validated.cluster_config.secret_key_secret_name,
539562
INTERNAL_SECRET_SECRET_KEY,
@@ -692,6 +715,72 @@ pub async fn reconcile_superset(
692715
Ok(Action::await_change())
693716
}
694717

718+
// TODO: Can be removed after SDP 26.7 is released (it's only a migration from 26.3 - 26.7)
719+
// (don't forget about the snafu Error variants).
720+
// Removal is tracked in https://github.com/stackabletech/superset-operator/issues/755
721+
#[instrument(skip_all)]
722+
async fn migrate_legacy_secret_key_secret_from_26_3(
723+
superset: &SupersetCluster,
724+
validated: &ValidatedCluster,
725+
client: &Client,
726+
) -> Result<()> {
727+
let old_secret_name = &validated.cluster_config.credentials_secret_name;
728+
let new_secret_name = &validated.cluster_config.secret_key_secret_name;
729+
let secret_namespace = &validated.namespace;
730+
731+
let new_secret = client
732+
.get_opt::<Secret>(new_secret_name, secret_namespace.as_ref())
733+
.await
734+
.with_context(|_| RetrieveCredentialsSecretSnafu {
735+
secret_name: new_secret_name,
736+
})?;
737+
if new_secret.is_some() {
738+
tracing::debug!("SECRET_KEY Secret already exists, nothing to migrate");
739+
return Ok(());
740+
}
741+
742+
let old_secret = client
743+
.get_opt::<Secret>(old_secret_name, secret_namespace.as_ref())
744+
.await
745+
.with_context(|_| RetrieveCredentialsSecretSnafu {
746+
secret_name: old_secret_name,
747+
})?;
748+
let old_secret_key = old_secret
749+
.and_then(|secret| secret.data)
750+
// Note: We remove the key to take ownership
751+
.and_then(|mut data| data.remove("connections.secretKey"))
752+
.and_then(|key| String::from_utf8(key.0).ok());
753+
if let Some(old_secret_key) = old_secret_key {
754+
tracing::info!(
755+
old.secret.name = old_secret_name,
756+
old.secret.namespace = %secret_namespace,
757+
new.secret.name = new_secret_name,
758+
new.secret.namespace = %secret_namespace,
759+
"Migrating old SECRET_KEY to new Secret"
760+
);
761+
762+
let secret = Secret {
763+
metadata: ObjectMetaBuilder::new()
764+
.name(new_secret_name)
765+
.namespace(secret_namespace)
766+
.ownerreference_from_resource(superset, None, Some(true))
767+
.context(ObjectMissingMetadataForOwnerRefSnafu)?
768+
.build(),
769+
string_data: Some(BTreeMap::from([(
770+
INTERNAL_SECRET_SECRET_KEY.to_string(),
771+
old_secret_key,
772+
)])),
773+
..Secret::default()
774+
};
775+
client
776+
.create(&secret)
777+
.await
778+
.context(CreateRandomSecretSnafu)?;
779+
}
780+
781+
Ok(())
782+
}
783+
695784
pub fn error_policy(
696785
_obj: Arc<DeserializeGuard<SupersetCluster>>,
697786
error: &Error,

rust/operator-binary/src/controller/build/resource/config_map.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ mod tests {
9999
image:
100100
productVersion: 4.1.4
101101
clusterConfig:
102-
credentialsSecretName: superset-admin-credentials
102+
credentialsSecret: superset-admin-credentials
103103
metadataDatabase:
104104
postgresql:
105105
host: superset-postgresql

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ mod tests {
342342
image:
343343
productVersion: 4.1.4
344344
clusterConfig:
345-
credentialsSecretName: superset-admin-credentials
345+
credentialsSecret: superset-admin-credentials
346346
metadataDatabase:
347347
postgresql:
348348
host: superset-postgresql
@@ -399,7 +399,7 @@ mod tests {
399399
image:
400400
productVersion: 4.1.4
401401
clusterConfig:
402-
credentialsSecretName: superset-admin-credentials
402+
credentialsSecret: superset-admin-credentials
403403
metadataDatabase:
404404
postgresql:
405405
host: superset-postgresql

rust/operator-binary/src/crd/affinity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ mod tests {
4848
image:
4949
productVersion: 6.1.0
5050
clusterConfig:
51-
credentialsSecretName: superset-admin-credentials
51+
credentialsSecret: superset-admin-credentials
5252
metadataDatabase:
5353
postgresql:
5454
host: superset-postgresql

rust/operator-binary/src/crd/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ pub mod versioned {
244244
/// Read the
245245
/// [getting started guide first steps](DOCS_BASE_URL_PLACEHOLDER/superset/getting_started/first_steps)
246246
/// to find out more.
247+
// TODO: In the future rename this to `credentialsSecretName`
248+
#[serde(rename = "credentialsSecret")]
247249
pub credentials_secret_name: String,
248250

249251
/// Cluster operations like pause reconciliation or cluster stop.
@@ -615,7 +617,7 @@ mod tests {
615617
reconciliationPaused: false
616618
stopped: true
617619
clusterConfig:
618-
credentialsSecretName: superset-admin-credentials
620+
credentialsSecret: superset-admin-credentials
619621
metadataDatabase:
620622
postgresql:
621623
host: superset-postgresql

tests/templates/kuttl/celery-worker/40-install-superset.yaml.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ spec:
4747
{% endif %}
4848
pullPolicy: IfNotPresent
4949
clusterConfig:
50-
credentialsSecretName: superset-admin-credentials
50+
credentialsSecret: superset-admin-credentials
5151
metadataDatabase:
5252
postgresql:
5353
host: superset-postgresql

tests/templates/kuttl/cluster-operation/20-install-superset.yaml.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ spec:
3939
{% endif %}
4040
pullPolicy: IfNotPresent
4141
clusterConfig:
42-
credentialsSecretName: superset-admin-credentials
42+
credentialsSecret: superset-admin-credentials
4343
metadataDatabase:
4444
postgresql:
4545
host: superset-postgresql

0 commit comments

Comments
 (0)