From 483e5190d9221c64b2395fdbdaec5dae3ab7a8be Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 24 Jun 2026 15:59:15 +0200 Subject: [PATCH 1/2] feat: Allow tweaking catalog name in Trino --- CHANGELOG.md | 4 +- .../pages/usage-guide/catalogs/index.adoc | 22 ++++++++ extra/crds.yaml | 28 +++++++++++ rust/operator-binary/src/catalog/config.rs | 10 ++-- .../src/controller/dereference.rs | 44 +++++++++++++--- rust/operator-binary/src/crd/catalog/mod.rs | 50 ++++++++++++++++++- 6 files changed, 142 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77fd18bda..176810f90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ All notable changes to this project will be documented in this file. - BREAKING: Add required CLI argument and env var to set the image repository used to construct final product image names: `IMAGE_REPOSITORY` (`--image-repository`), eg. `oci.example.org/my/namespace` ([#884]). - Added support for the [PostgreSQL connector](https://trino.io/docs/current/connector/postgresql.html) using the new generic database connection mechanism. Previously, users had to use the `generic` connector ([#883]). -- Added support for Trino 481 ([#900]). +- Add support for Trino 481 ([#900]). +- Add a new `.spec.name.inferred.replaceHyphensWithUnderscores` field on TrinoCatalog, which allows tweaking the catalog name in Trino ([#XXX]). ### Changed @@ -40,6 +41,7 @@ All notable changes to this project will be documented in this file. [#889]: https://github.com/stackabletech/trino-operator/pull/889 [#895]: https://github.com/stackabletech/trino-operator/pull/895 [#900]: https://github.com/stackabletech/trino-operator/pull/900 +[#XXX]: https://github.com/stackabletech/trino-operator/pull/XXX ## [26.3.0] - 2026-03-16 diff --git a/docs/modules/trino/pages/usage-guide/catalogs/index.adoc b/docs/modules/trino/pages/usage-guide/catalogs/index.adoc index a1946c1c6..6a0a6123b 100644 --- a/docs/modules/trino/pages/usage-guide/catalogs/index.adoc +++ b/docs/modules/trino/pages/usage-guide/catalogs/index.adoc @@ -105,6 +105,28 @@ In this case the `hive` and `iceberg` catalogs will be used as they both match t A `TrinoCluster` can, once created, detect and use new catalogs that have been subsequently created with a matching label. This also means that it is possible to reuse a `TrinoCatalog` within multiple `TrinoClusters`. +=== Catalog name tweaking + +By default the name of the catalog in Trino is inferred from the `.metadata.name` of the TrinoCatalog object. +This ensures that no catalog names clash, as their can only be one TrinoCatalog with a given name. + +One inconvenience is that you need to quote catalogs (or schemas and tables for that matter) containing `-` in Trino, while `_` is fine. +As Kubernetes doesn't allow `_` in the object names, we offer a feature to replace `-` with `_`, which allows you to use valid Kubernetes names, but keeps the convenience of `_` in catalog names. + +You can enable it like this, the Trino catalog will be called `my_postgres`: + +[source,yaml] +---- +kind: TrinoCatalog +metadata: + name: my-postgres +spec: + name: + inferred: + replaceHyphensWithUnderscores: true +# ... +---- + === Generic fallback connector Trino supports lots of different connectors and we can not cover all the available connectors. diff --git a/extra/crds.yaml b/extra/crds.yaml index 59515338a..2fa04a48a 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -4279,6 +4279,34 @@ spec: items: type: string type: array + name: + default: + inferred: + replaceHyphensWithUnderscores: false + description: The name of the catalog + oneOf: + - required: + - inferred + properties: + inferred: + description: |- + Infer the catalog name from the `.metadata.name` of the TrinoCatalog resource. + + This ensures that no catalog names clash, as their can only be one TrinoCatalog with a + given name. + properties: + replaceHyphensWithUnderscores: + default: false + description: |- + Wether hyphens (`-`) in the name of the catalog should be replaced by underscores (`_`). + + This is recommended because Kubernetes only allows `a-z` and `-`, while Trino + requires quoting for catalogs containing `-` characters, but not for `_`. This mechanism + allows you to use valid Kubernetes names, but keeps the convenience of `_` in catalog + names. + type: boolean + type: object + type: object required: - connector type: object diff --git a/rust/operator-binary/src/catalog/config.rs b/rust/operator-binary/src/catalog/config.rs index 8d4ef5530..39b217691 100644 --- a/rust/operator-binary/src/catalog/config.rs +++ b/rust/operator-binary/src/catalog/config.rs @@ -5,7 +5,7 @@ use stackable_operator::{ k8s_openapi::api::core::v1::{ ConfigMapKeySelector, EnvVar, EnvVarSource, SecretKeySelector, Volume, VolumeMount, }, - kube::{Resource, ResourceExt}, + kube::ResourceExt, }; use super::{FromTrinoCatalogError, ToCatalogConfig}; @@ -103,15 +103,11 @@ impl CatalogConfig { } pub async fn from_catalog( + catalog_name: &str, catalog: &v1alpha1::TrinoCatalog, client: &Client, trino_version: u16, ) -> Result { - let catalog_name = catalog - .meta() - .name - .clone() - .ok_or(FromTrinoCatalogError::InvalidCatalogSpec)?; let catalog_namespace = catalog.namespace(); let to_catalog_config: &dyn ToCatalogConfig = match &catalog.spec.connector { @@ -126,7 +122,7 @@ impl CatalogConfig { TrinoCatalogConnector::Tpch(tpch_connector) => tpch_connector, }; let mut catalog_config = to_catalog_config - .to_catalog_config(&catalog_name, catalog_namespace, client, trino_version) + .to_catalog_config(catalog_name, catalog_namespace, client, trino_version) .await?; catalog_config diff --git a/rust/operator-binary/src/controller/dereference.rs b/rust/operator-binary/src/controller/dereference.rs index 81fed2d88..84145bd80 100644 --- a/rust/operator-binary/src/controller/dereference.rs +++ b/rust/operator-binary/src/controller/dereference.rs @@ -6,10 +6,13 @@ //! `ResolvedClientProtocolConfig::from_config`) currently mix fetching and validation; their //! outputs are treated as "dereferenced" for now. Splitting those helpers is a follow-up. -use std::{num::ParseIntError, str::FromStr}; +use std::{collections::HashSet, num::ParseIntError, str::FromStr}; use snafu::{OptionExt, ResultExt, Snafu}; -use stackable_operator::{client::Client, kube::runtime::reflector::ObjectRef}; +use stackable_operator::{ + client::Client, + kube::{Resource, runtime::reflector::ObjectRef}, +}; use crate::{ authorization::opa::TrinoOpaConfig, @@ -29,6 +32,9 @@ pub enum Error { #[snafu(display("object defines no namespace"))] ObjectHasNoNamespace, + #[snafu(display("object defines no name"))] + ObjectHasNoName, + #[snafu(display("failed to retrieve AuthenticationClass"))] AuthenticationClassRetrieval { source: crate::crd::authentication::Error, @@ -63,6 +69,11 @@ pub enum Error { InvalidOpaConfig { source: stackable_operator::commons::opa::Error, }, + + #[snafu(display( + "The catalog name {catalog_name:?} clashes (there are multiple catalogs with this name). Please make sure there is exactly one catalog for any given name" + ))] + ClashingCatalogName { catalog_name: String }, } type Result = std::result::Result; @@ -108,13 +119,32 @@ pub async fn dereference( })?; let mut catalogs = Vec::with_capacity(catalog_definitions.len()); + let mut catalog_names: HashSet = HashSet::new(); for catalog in &catalog_definitions { let catalog_ref = ObjectRef::from_obj(catalog); - let catalog_config = CatalogConfig::from_catalog(catalog, client, product_version) - .await - .context(ParseCatalogSnafu { - catalog: catalog_ref, - })?; + // We are using a match here, as we might support other ways of naming (e.g. custom) later + let catalog_name = match catalog.spec.name { + catalog::v1alpha1::TrinoCatalogNameSpec::Inferred { + replace_hyphens_with_underscores, + } => { + let mut catalog_name = catalog.meta().name.clone().context(ObjectHasNoNameSnafu)?; + if replace_hyphens_with_underscores { + catalog_name = catalog_name.replace('-', "_"); + } + catalog_name + } + }; + + if catalog_names.insert(catalog_name.clone()) { + return ClashingCatalogNameSnafu { catalog_name }.fail(); + } + + let catalog_config = + CatalogConfig::from_catalog(&catalog_name, catalog, client, product_version) + .await + .context(ParseCatalogSnafu { + catalog: catalog_ref, + })?; catalogs.push(catalog_config); } diff --git a/rust/operator-binary/src/crd/catalog/mod.rs b/rust/operator-binary/src/crd/catalog/mod.rs index 73df79f82..d61858c3c 100644 --- a/rust/operator-binary/src/crd/catalog/mod.rs +++ b/rust/operator-binary/src/crd/catalog/mod.rs @@ -48,6 +48,10 @@ pub mod versioned { #[derive(Clone, CustomResource, Debug, Deserialize, JsonSchema, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct TrinoCatalogSpec { + /// The name of the catalog + #[serde(default)] + pub name: TrinoCatalogNameSpec, + /// The `connector` defines which connector is used. pub connector: TrinoCatalogConnector, @@ -65,6 +69,47 @@ pub mod versioned { #[serde(default, rename = "experimentalConfigRemovals")] pub config_removals: Vec, } + + #[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub enum TrinoCatalogNameSpec { + /// Infer the catalog name from the `.metadata.name` of the TrinoCatalog resource. + /// + /// This ensures that no catalog names clash, as their can only be one TrinoCatalog with a + /// given name. + #[serde(rename_all = "camelCase")] + Inferred { + /// Wether hyphens (`-`) in the name of the catalog should be replaced by underscores (`_`). + /// + /// This is recommended because Kubernetes only allows `a-z` and `-`, while Trino + /// requires quoting for catalogs containing `-` characters, but not for `_`. This mechanism + /// allows you to use valid Kubernetes names, but keeps the convenience of `_` in catalog + /// names. + // + // /// In case you need complete flexibility over the catalog name, you can use + // /// `name.custom`. + #[serde(default)] + replace_hyphens_with_underscores: bool, + }, + // As requested in https://github.com/stackabletech/trino-operator/issues/891 we are not + // implementing the custom variant yet. Please re-open or create a new decision before + // implementing this. + // + // /// Specify the name of the catalog as it shows up in Trino. + // /// + // /// It is your responsibility to make sure that no catalog names clash, the operator will + // /// raise an error in that case. + // /// + // /// TIP: If you only want to replace `-` with `_` use + // /// `name.inferred.replaceHyphensWithUnderscores` instead. + // Custom(String), + } +} + +impl Default for v1alpha1::TrinoCatalogNameSpec { + fn default() -> Self { + Self::Inferred { replace_hyphens_with_underscores: false } + } } #[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)] @@ -172,7 +217,10 @@ mod tests { secretClass: minio-credentials - connector: tpcds: {} - - connector: + - name: + inferred: + replaceHyphensWithUnderscores: true + connector: tpch: {} "}) .expect("Failed to parse TrinoCatalogSpec YAML") From 3c722fd1f110a31cae7515ae3e3b27c15bfa5ac4 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 24 Jun 2026 16:00:48 +0200 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 176810f90..bc634eb86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file. - Added support for the [PostgreSQL connector](https://trino.io/docs/current/connector/postgresql.html) using the new generic database connection mechanism. Previously, users had to use the `generic` connector ([#883]). - Add support for Trino 481 ([#900]). -- Add a new `.spec.name.inferred.replaceHyphensWithUnderscores` field on TrinoCatalog, which allows tweaking the catalog name in Trino ([#XXX]). +- Add a new `.spec.name.inferred.replaceHyphensWithUnderscores` field on TrinoCatalog, which allows tweaking the catalog name in Trino ([#903]). ### Changed @@ -41,7 +41,7 @@ All notable changes to this project will be documented in this file. [#889]: https://github.com/stackabletech/trino-operator/pull/889 [#895]: https://github.com/stackabletech/trino-operator/pull/895 [#900]: https://github.com/stackabletech/trino-operator/pull/900 -[#XXX]: https://github.com/stackabletech/trino-operator/pull/XXX +[#903]: https://github.com/stackabletech/trino-operator/pull/903 ## [26.3.0] - 2026-03-16