From a1d67d734bbb281158f9df58a6f2c2681eabdde2 Mon Sep 17 00:00:00 2001 From: Techassi Date: Mon, 18 Nov 2024 16:15:40 +0100 Subject: [PATCH 1/6] Update CHANGELOG.md from release 24.11.0 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d19d70e7..6fc34dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## [24.11.0] - 2024-11-18 + ### Added - Allowing arbitrary python code as `EXPERIMENTAL_FILE_HEADER` and `EXPERIMENTAL_FILE_FOOTER` in `webserver_config.py` ([#493]). From 4f76f25f2d2bbcf980cc7adb654d31c373362b3b Mon Sep 17 00:00:00 2001 From: Stacky McStackface <95074132+stackable-bot@users.noreply.github.com> Date: Mon, 18 Nov 2024 22:45:20 +0100 Subject: [PATCH 2/6] chore: Generated commit to update templated files since the last template run up to stackabletech/operator-templating@fd40109c1bd66c79fa74bf67a5b5bff1e3a96ce8 (#542) Reference-to: stackabletech/operator-templating@fd40109 (Add make render-doc command) --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 47c8abc2..16b67fcc 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,9 @@ SHELL=/usr/bin/env bash -euo pipefail render-readme: scripts/render_readme.sh +render-docs: + scripts/docs_templating.sh + ## Docker related targets docker-build: docker build --force-rm --build-arg VERSION=${VERSION} -t "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}" -f docker/Dockerfile . From 97b716004dcabe3f13895d1f89ca33cba2af06c6 Mon Sep 17 00:00:00 2001 From: Nick <10092581+NickLarsenNZ@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:15:08 +1300 Subject: [PATCH 3/6] chore(getting_started): replace templating instructions with make (#543) --- .../getting_started/code/getting_started.sh | 14 +------------- .../getting_started/code/getting_started.sh.j2 | 14 +------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/docs/modules/airflow/examples/getting_started/code/getting_started.sh b/docs/modules/airflow/examples/getting_started/code/getting_started.sh index 1d03c8e2..ed340cb9 100755 --- a/docs/modules/airflow/examples/getting_started/code/getting_started.sh +++ b/docs/modules/airflow/examples/getting_started/code/getting_started.sh @@ -2,19 +2,7 @@ set -euo pipefail # DO NOT EDIT THE SCRIPT -# Instead, update the j2 template, and regenerate it for dev: -# cat < Date: Mon, 25 Nov 2024 11:10:46 +0100 Subject: [PATCH 4/6] Patch op-rs version to use one that fixes SUP-148. (#545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Patch op-rs version to use one that fixes SUP-148. * Updated changelog Use op-rs 0.82 instead of PR branch. * Regenerate Nix files --------- Co-authored-by: Sönke Liebau Co-authored-by: Siegfried Weber --- CHANGELOG.md | 2 ++ Cargo.lock | 8 ++++---- Cargo.nix | 14 +++++++------- Cargo.toml | 2 +- crate-hashes.json | 6 +++--- rust/operator-binary/src/airflow_controller.rs | 10 +++++----- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fc34dbb..99a5fb67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Pass gitsync credentials through properly and use a fine-grained access token ([#489]). - Failing to parse one `AirflowCluster`/`AuthenticationClass` should no longer cause the whole operator to stop functioning ([#520]). +- BREAKING: Use distinct ServiceAccounts for the Stacklets, so that multiple Stacklets can be deployed in one namespace. Existing Stacklets will use the newly created ServiceAccounts after restart ([#545]). [#488]: https://github.com/stackabletech/airflow-operator/pull/488 [#489]: https://github.com/stackabletech/airflow-operator/pull/489 @@ -35,6 +36,7 @@ [#520]: https://github.com/stackabletech/airflow-operator/pull/520 [#524]: https://github.com/stackabletech/airflow-operator/pull/524 [#530]: https://github.com/stackabletech/airflow-operator/pull/530 +[#545]: https://github.com/stackabletech/airflow-operator/pull/545 ## [24.7.0] - 2024-07-24 diff --git a/Cargo.lock b/Cargo.lock index 0efb5c36..82c1dfcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2210,8 +2210,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.80.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#6fbe32300b60f95e0baa2ab0ff2daf961b06531c" +version = "0.82.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" dependencies = [ "chrono", "clap", @@ -2249,7 +2249,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#6fbe32300b60f95e0baa2ab0ff2daf961b06531c" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" dependencies = [ "darling", "proc-macro2", @@ -2260,7 +2260,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.0.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#6fbe32300b60f95e0baa2ab0ff2daf961b06531c" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" dependencies = [ "kube", "semver", diff --git a/Cargo.nix b/Cargo.nix index 22c13476..584ea7b0 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -6831,13 +6831,13 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.80.0"; + version = "0.82.0"; edition = "2021"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "6fbe32300b60f95e0baa2ab0ff2daf961b06531c"; - sha256 = "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3"; + rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; + sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; }; libName = "stackable_operator"; authors = [ @@ -6994,8 +6994,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "6fbe32300b60f95e0baa2ab0ff2daf961b06531c"; - sha256 = "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3"; + rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; + sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -7029,8 +7029,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "6fbe32300b60f95e0baa2ab0ff2daf961b06531c"; - sha256 = "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3"; + rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; + sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; }; libName = "stackable_shared"; authors = [ diff --git a/Cargo.toml b/Cargo.toml index 38123e38..7d75ac6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_yaml = "0.9" snafu = "0.8" -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.80.0" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.82.0" } strum = { version = "0.26", features = ["derive"] } tokio = { version = "1.40", features = ["full"] } tracing = "0.1" diff --git a/crate-hashes.json b/crate-hashes.json index 562fb18b..0ca37e6e 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,6 +1,6 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#stackable-operator-derive@0.3.1": "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#stackable-operator@0.80.0": "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.80.0#stackable-shared@0.0.1": "16jrq3wdwz63210jgmqbx3snrr15wxw6l1smqhzv7b7jpq8qvya3", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-operator-derive@0.3.1": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-operator@0.82.0": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-shared@0.0.1": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", "git+https://github.com/stackabletech/product-config.git?tag=0.7.0#product-config@0.7.0": "0gjsm80g6r75pm3824dcyiz4ysq1ka4c1if6k1mjm9cnd5ym0gny" } \ No newline at end of file diff --git a/rust/operator-binary/src/airflow_controller.rs b/rust/operator-binary/src/airflow_controller.rs index c5b9efbb..cf9c0ff1 100644 --- a/rust/operator-binary/src/airflow_controller.rs +++ b/rust/operator-binary/src/airflow_controller.rs @@ -46,7 +46,7 @@ use stackable_operator::{ apps::v1::{StatefulSet, StatefulSetSpec}, core::v1::{ ConfigMap, EmptyDirVolumeSource, EnvVar, PodTemplateSpec, Probe, Service, - ServicePort, ServiceSpec, TCPSocketAction, VolumeMount, + ServiceAccount, ServicePort, ServiceSpec, TCPSocketAction, VolumeMount, }, }, apimachinery::pkg::{apis::meta::v1::LabelSelector, util::intstr::IntOrString}, @@ -416,7 +416,7 @@ pub async fn reconcile_airflow( build_rbac_resources(airflow, APP_NAME, required_labels).context(BuildRBACObjectsSnafu)?; let rbac_sa = cluster_resources - .add(client, rbac_sa) + .add(client, rbac_sa.clone()) .await .context(ApplyServiceAccountSnafu)?; cluster_resources @@ -488,7 +488,7 @@ pub async fn reconcile_airflow( &rolegroup, rolegroup_config, &authentication_config, - &rbac_sa.name_unchecked(), + &rbac_sa, &merged_airflow_config, airflow_executor, )?; @@ -836,7 +836,7 @@ fn build_server_rolegroup_statefulset( rolegroup_ref: &RoleGroupRef, rolegroup_config: &HashMap>, authentication_config: &AirflowClientAuthenticationDetailsResolved, - sa_name: &str, + service_account: &ServiceAccount, merged_airflow_config: &AirflowConfig, executor: &AirflowExecutor, ) -> Result { @@ -861,7 +861,7 @@ fn build_server_rolegroup_statefulset( pb.metadata(pb_metadata) .image_pull_secrets_from_product_image(resolved_product_image) .affinity(&merged_airflow_config.affinity) - .service_account_name(sa_name) + .service_account_name(service_account.name_any()) .security_context( PodSecurityContextBuilder::new() .run_as_user(AIRFLOW_UID) From f3eb0af611b556d9f635b29ef9c3e41d2ac164f0 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 25 Nov 2024 13:59:11 +0100 Subject: [PATCH 5/6] fix: Construction of OIDC endpoint when rootPath has a trailing slash (#547) * fix: Construction of OIDC endpoint when rootPath has a trailing slash * changelog * changelog --- CHANGELOG.md | 2 + Cargo.lock | 1 + Cargo.nix | 4 ++ Cargo.toml | 1 + rust/operator-binary/Cargo.toml | 2 +- rust/operator-binary/src/config.rs | 103 ++++++++++++++++++----------- 6 files changed, 75 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a5fb67..593f0951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Pass gitsync credentials through properly and use a fine-grained access token ([#489]). - Failing to parse one `AirflowCluster`/`AuthenticationClass` should no longer cause the whole operator to stop functioning ([#520]). - BREAKING: Use distinct ServiceAccounts for the Stacklets, so that multiple Stacklets can be deployed in one namespace. Existing Stacklets will use the newly created ServiceAccounts after restart ([#545]). +- Fix OIDC endpoint construction in case the `rootPath` does not have a trailing slash ([#547]). [#488]: https://github.com/stackabletech/airflow-operator/pull/488 [#489]: https://github.com/stackabletech/airflow-operator/pull/489 @@ -37,6 +38,7 @@ [#524]: https://github.com/stackabletech/airflow-operator/pull/524 [#530]: https://github.com/stackabletech/airflow-operator/pull/530 [#545]: https://github.com/stackabletech/airflow-operator/pull/545 +[#547]: https://github.com/stackabletech/airflow-operator/pull/547 ## [24.7.0] - 2024-07-24 diff --git a/Cargo.lock b/Cargo.lock index 82c1dfcd..fdda7751 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2198,6 +2198,7 @@ dependencies = [ "futures 0.3.31", "indoc", "product-config", + "rstest", "serde", "serde_yaml", "snafu 0.8.5", diff --git a/Cargo.nix b/Cargo.nix index 584ea7b0..f3b0d8be 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -6822,6 +6822,10 @@ rec { } ]; devDependencies = [ + { + name = "rstest"; + packageId = "rstest"; + } { name = "serde_yaml"; packageId = "serde_yaml"; diff --git a/Cargo.toml b/Cargo.toml index 7d75ac6f..1ec6feb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,3 +30,4 @@ 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 = { path = "../operator-rs/crates/stackable-operator" } diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 9ffd50f7..e2e45049 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -26,8 +26,8 @@ tracing.workspace = true indoc.workspace = true [build-dependencies] - built.workspace = true [dev-dependencies] +rstest.workspace = true serde_yaml.workspace = true diff --git a/rust/operator-binary/src/config.rs b/rust/operator-binary/src/config.rs index 2d7feff7..ddc741fe 100644 --- a/rust/operator-binary/src/config.rs +++ b/rust/operator-binary/src/config.rs @@ -26,6 +26,16 @@ pub enum Error { FailedToCreateLdapEndpointUrl { source: stackable_operator::commons::authentication::ldap::Error, }, + + #[snafu(display("invalid OIDC endpoint"))] + InvalidOidcEndpoint { + source: stackable_operator::commons::authentication::oidc::Error, + }, + + #[snafu(display("invalid well-known OIDC configuration URL"))] + InvalidWellKnownConfigUrl { + source: stackable_operator::commons::authentication::oidc::Error, + }, } pub fn add_airflow_config( @@ -78,7 +88,7 @@ fn append_authentication_config( } if !oidc_providers.is_empty() { - append_oidc_config(config, &oidc_providers); + append_oidc_config(config, &oidc_providers)?; } config.insert( @@ -192,7 +202,7 @@ fn append_oidc_config( &oidc::AuthenticationProvider, &oidc::ClientAuthenticationOptions<()>, )], -) { +) -> Result<(), Error> { // Debatable: AUTH_OAUTH or AUTH_OID // Additionally can be set via config config.insert( @@ -217,6 +227,13 @@ fn append_oidc_config( let oauth_providers_config_entry = match oidc_provider { oidc::IdentityProviderHint::Keycloak => { + let endpoint_url = oidc.endpoint_url().context(InvalidOidcEndpointSnafu)?; + let mut api_base_url = endpoint_url.as_str().trim_end_matches('/').to_owned(); + api_base_url.push_str("/protocol/"); + let well_known_config_url = oidc + .well_known_config_url() + .context(InvalidWellKnownConfigUrlSnafu)?; + formatdoc!( " {{ 'name': 'keycloak', @@ -228,11 +245,10 @@ fn append_oidc_config( 'client_kwargs': {{ 'scope': '{scopes}' }}, - 'api_base_url': '{url}/protocol/', - 'server_metadata_url': '{url}/.well-known/openid-configuration', + 'api_base_url': '{api_base_url}', + 'server_metadata_url': '{well_known_config_url}', }}, }}", - url = oidc.endpoint_url().unwrap(), scopes = scopes.join(" "), ) } @@ -251,12 +267,15 @@ fn append_oidc_config( joined_oauth_providers_config = oauth_providers_config.join(",\n") ), ); + + Ok(()) } #[cfg(test)] mod tests { use crate::config::add_airflow_config; - use indoc::indoc; + use indoc::formatdoc; + use rstest::rstest; use stackable_airflow_crd::authentication::{ default_sync_roles_at, default_user_registration, AirflowAuthenticationClassResolved, AirflowClientAuthenticationDetailsResolved, FlaskRolesSyncMoment, @@ -339,12 +358,15 @@ mod tests { ]), result); } - #[test] - fn test_oidc_config() { - let oidc_provider_yaml1 = r#" - hostname: my.keycloak1.server + #[rstest] + #[case("/realms/sdp")] + #[case("/realms/sdp/")] + #[case("/realms/sdp/////")] + fn test_oidc_config(#[case] root_path: &str) { + let oidc_provider_yaml1 = formatdoc!( + "hostname: my.keycloak1.server port: 12345 - rootPath: my-root-path + rootPath: {root_path} tls: verification: server: @@ -356,8 +378,9 @@ mod tests { - email - profile provider_hint: Keycloak - "#; - let deserializer = serde_yaml::Deserializer::from_str(oidc_provider_yaml1); + " + ); + let deserializer = serde_yaml::Deserializer::from_str(&oidc_provider_yaml1); let oidc_provider1: oidc::AuthenticationProvider = serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap(); @@ -399,41 +422,47 @@ mod tests { let mut result = BTreeMap::new(); add_airflow_config(&mut result, &authentication_config).expect("Ok"); - assert_eq!(BTreeMap::from([ - ("AUTH_ROLES_SYNC_AT_LOGIN".into(), "false".into()), - ("AUTH_TYPE".into(), "AUTH_OAUTH".into()), - ("AUTH_USER_REGISTRATION".into(), "true".into()), - ("AUTH_USER_REGISTRATION_ROLE".into(), "Admin".into()), - ("OAUTH_PROVIDERS".into(), indoc!(" + assert_eq!( + BTreeMap::from([ + ("AUTH_ROLES_SYNC_AT_LOGIN".into(), "false".into()), + ("AUTH_TYPE".into(), "AUTH_OAUTH".into()), + ("AUTH_USER_REGISTRATION".into(), "true".into()), + ("AUTH_USER_REGISTRATION_ROLE".into(), "Admin".into()), + ( + "OAUTH_PROVIDERS".into(), + formatdoc! {" [ - { 'name': 'keycloak', + {{ 'name': 'keycloak', 'icon': 'fa-key', 'token_key': 'access_token', - 'remote_app': { + 'remote_app': {{ 'client_id': os.environ.get('OIDC_A96BCC4FA49835D2_CLIENT_ID'), 'client_secret': os.environ.get('OIDC_A96BCC4FA49835D2_CLIENT_SECRET'), - 'client_kwargs': { + 'client_kwargs': {{ 'scope': 'openid email profile roles' - }, - 'api_base_url': 'https://my.keycloak1.server:12345/my-root-path/protocol/', - 'server_metadata_url': 'https://my.keycloak1.server:12345/my-root-path/.well-known/openid-configuration', - }, - }, - { 'name': 'keycloak', + }}, + 'api_base_url': 'https://my.keycloak1.server:12345/realms/sdp/protocol/', + 'server_metadata_url': 'https://my.keycloak1.server:12345/realms/sdp/.well-known/openid-configuration', + }}, + }}, + {{ 'name': 'keycloak', 'icon': 'fa-key', 'token_key': 'access_token', - 'remote_app': { + 'remote_app': {{ 'client_id': os.environ.get('OIDC_3A305E38C3B561F3_CLIENT_ID'), 'client_secret': os.environ.get('OIDC_3A305E38C3B561F3_CLIENT_SECRET'), - 'client_kwargs': { + 'client_kwargs': {{ 'scope': 'openid' - }, - 'api_base_url': 'http://my.keycloak2.server//protocol/', - 'server_metadata_url': 'http://my.keycloak2.server//.well-known/openid-configuration', - }, - } + }}, + 'api_base_url': 'http://my.keycloak2.server/protocol/', + 'server_metadata_url': 'http://my.keycloak2.server/.well-known/openid-configuration', + }}, + }} ] - ").into()) - ]), result); + "} + ) + ]), + result + ); } } From cbbcc1705054c9c4f401b363373904623eb542fc Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 26 Nov 2024 09:37:05 +0100 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a5fb67..947d583e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +### Fixed + +- BREAKING: Use distinct ServiceAccounts for the Stacklets, so that multiple Stacklets can be + deployed in one namespace. Existing Stacklets will use the newly created ServiceAccounts after + restart ([#545]). + +[#545]: https://github.com/stackabletech/airflow-operator/pull/545 + ## [24.11.0] - 2024-11-18 ### Added @@ -26,7 +34,6 @@ - Pass gitsync credentials through properly and use a fine-grained access token ([#489]). - Failing to parse one `AirflowCluster`/`AuthenticationClass` should no longer cause the whole operator to stop functioning ([#520]). -- BREAKING: Use distinct ServiceAccounts for the Stacklets, so that multiple Stacklets can be deployed in one namespace. Existing Stacklets will use the newly created ServiceAccounts after restart ([#545]). [#488]: https://github.com/stackabletech/airflow-operator/pull/488 [#489]: https://github.com/stackabletech/airflow-operator/pull/489 @@ -36,7 +43,6 @@ [#520]: https://github.com/stackabletech/airflow-operator/pull/520 [#524]: https://github.com/stackabletech/airflow-operator/pull/524 [#530]: https://github.com/stackabletech/airflow-operator/pull/530 -[#545]: https://github.com/stackabletech/airflow-operator/pull/545 ## [24.7.0] - 2024-07-24